Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't use proxy to do JWT authentication with googleapis #998

Closed
kevguy opened this issue Feb 13, 2018 · 7 comments
Closed

Can't use proxy to do JWT authentication with googleapis #998

kevguy opened this issue Feb 13, 2018 · 7 comments
Assignees
Labels
external This issue is blocked on a bug with the actual product. 🚨 This issue needs some love. type: bug Error or flaw in code with unintended results or allowing sub-optimal usage patterns.

Comments

@kevguy
Copy link

kevguy commented Feb 13, 2018

I have a NodeJS API working behind a corporate proxy and I have been trying to do authentication with Google with their NodeJS client:

    const google = require('googleapis');

    function getServiceAccountInfo() {
      return {
        type: 'service_account',
        project_id: 'XXXXX',
        private_key_id: 'XXXXXX',
        private_key: 'XXXX',
        client_email: 'XXXX',
        client_id: 'XXXX',
        auth_uri: 'XXXX',
        token_uri: 'XXXX',
        auth_provider_x509_cert_url: 'XXXX',
        client_x509_cert_url: 'XXXXX'
      };
    }

    const SCOPES = 'https://www.googleapis.com/auth/firebase.messaging';

    let proxy2 = {
      host: 'proxy.hkcsl.net',
      port: 8080
    };

    const proxy3 = {
      proxy: 'http://172.25.2.6:8080'
    }

    const proxy4 = {
      proxy: {
        host: '172.25.2.6',
        port: 8080,
        auth: {
          username: '',
          password: '',
        },
      }
    }

    process.env.HTTPS_PROXY = 'https://172.25.2.6:8080';
    process.env.https_proxy = 'https://172.25.2.6:8080';
    process.env.HTTP_PROXY = 'http://172.25.2.6:8080';
    process.env.http_proxy = 'http://172.25.2.6:8080';
    google.options({
      proxy: proxy4.proxy
    });

    const key = getServiceAccountInfo();
    const jwtClient = new google.auth.JWT(
      key.client_email,
      undefined, // null,
      key.private_key,
      SCOPES,
      undefined, // null
    );
    jwtClient.authorize(function(err, tokens) {
      if (err) {
        console.error(err);
        return;
      }
      console.log(tokens.access_token);
    });

However, no matter how I configure the proxy option, I still either get a timeout error or something like

ERROR Error: write EPROTO 101057795:error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol:openssl\ssl\s23_clnt.c:827:

Some people managed to fix it by changing the port to 443 but it doesn't apply to my case since that port is not available to me inside the server. And I've already referenced on the discussions and solutions proposed here:

StackOverflow: node-request - Getting error “SSL23_GET_SERVER_HELLO:unknown protocol”

googleapis: There is no facility for passing a proxy to the oauth2client

Axios: Request to HTTPS with HTTP proxy fails

Using jwtClient.authenticate() behind a proxy results in ETIMEDOUT error

It also seems like Vue is also encountering a similar problem yesterday, they changed from using axios to using request instead. Is there a similar workaround for googleapis too?

Note that I have also asked this question on StackOverflow (https://stackoverflow.com/questions/48766209/cant-use-proxy-to-do-jwt-authentication-with-googleapis).

@kevguy
Copy link
Author

kevguy commented Feb 14, 2018

After referencing on the workaround regarding the proxy issues with axios, which google-api-nodejs-client (i.e. googleapis) is using, and crawling through the source code of google-auth-library-nodejs (jwtclient.ts) and node-gtoken (index.ts), I wrote the following method to request token from Google manually as a temporary workaround:

const axios = require('axios-https-proxy-fix');
const querystring = require('querystring');
const jws = require('jws');

const GOOGLE_TOKEN_URL = 'https://www.googleapis.com/oauth2/v4/token';
const GOOGLE_REVOKE_TOKEN_URL =
    'https://accounts.google.com/o/oauth2/revoke?token=';

const SCOPES = 'https://www.googleapis.com/auth/firebase.messaging';

const PROXY = {
  host: '172.25.2.6',
  port: 8080,
  auth: {
    username: '',
    password: '',
  }
};

function getServiceAccountInfo() {
  return {
    type: 'service_account',
    project_id: 'XXXX',
    private_key_id: 'XXXX',
    private_key: 'XXXX',
    client_email: 'XXXX',
    client_id: 'XXXX',
    auth_uri: 'https://accounts.google.com/o/oauth2/auth',
    token_uri: 'https://accounts.google.com/o/oauth2/token',
    auth_provider_x509_cert_url: 'https://www.googleapis.com/oauth2/v1/certs',
    client_x509_cert_url: 'XXXX'
  };
}

function requestToken(client_email, private_key) {
  const iat = Math.floor(new Date().getTime() / 1000);
  const additionalClaims = {};
  const payload = Object.assign(
    {
      iss: client_email,
      scope: SCOPES,
      aud: GOOGLE_TOKEN_URL,
      exp: iat + 3600,
      iat,
      sub: undefined
    },
    additionalClaims);
  const signedJWT =
    jws.sign({header: {alg: 'RS256'}, payload, secret: private_key});
  return axios({
    method: 'post',
    url: GOOGLE_TOKEN_URL,
    data: querystring.stringify({
      grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
      assertion: signedJWT
    }),
    headers: {'Content-Type': 'application/x-www-form-urlencoded'},
    proxy: PROXY
  })
  .then(r => {
    const body = r.data;
    console.log(body);
    return body.access_token;
  })
  .catch(e => {
    const body = (e.response && e.response.data) ? e.response.data : {};
    let err = e;
    if (body.error) {
      const desc =
          body.error_description ? `: ${body.error_description}` : '';
      err = new Error(`${body.error}${desc}`);
    }
    throw err;
  });
}

const key = getServiceAccountInfo();
requestToken(key.client_email, key.private_key);

Reference: StackOverflow

@fruch
Copy link

fruch commented Mar 18, 2018

I've encounter this also,
setting HTTPS_PROXY isn't helping at all, as the docs says

@JustinBeckwith JustinBeckwith added type: bug Error or flaw in code with unintended results or allowing sub-optimal usage patterns. external This issue is blocked on a bug with the actual product. Status: Acknowledged and removed Status: Acknowledged labels Apr 15, 2018
@theflyingape
Copy link

Google My Business customers, such as ours, that need to use Google APIs to make best use of this service should not be held hostage by a glaring external issue that was opened "May 30, 2017". And this external issue is begging to merge a proposed fix for the past 6+ months??
I just ran into this myself yesterday when promoting new code into our data center that fails simply because it's behind a corporate proxy. This is not a "feel good" story at all.

@JustinBeckwith JustinBeckwith added the priority: p1 Important issue which blocks shipping the next release. Will be fixed prior to next release. label May 28, 2018
@JustinBeckwith JustinBeckwith self-assigned this Jun 7, 2018
@JustinBeckwith JustinBeckwith added the 🚨 This issue needs some love. label Jun 8, 2018
@marcoancona
Copy link

marcoancona commented Aug 2, 2018

Update: axios/axios#959 has been merged. I guess we are waiting for a new axios release?

@neorxna
Copy link

neorxna commented Aug 28, 2018

A workaround I found is to clear the http_proxy env variables and instead run the node app in proxychains:
proxychains node app.js
with a proxychains.conf in the working directory such as:

strict_chain

tcp_read_time_out 15000
tcp_connect_time_out 8000

localnet 127.0.0.0/255.0.0.0

[ProxyList]
http {your proxy ip address} {your proxy port}

or change http to socks5 for socks proxy etc.

@romain130492
Copy link

nothing solving, explaining that issue yet ?

@JustinBeckwith
Copy link
Contributor

This is a 3 year old bug that was fixed. If you're having problems, please open a new issue with as many details as possible.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
external This issue is blocked on a bug with the actual product. 🚨 This issue needs some love. type: bug Error or flaw in code with unintended results or allowing sub-optimal usage patterns.
Projects
None yet
Development

No branches or pull requests

7 participants