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

Error handling is unclear - client.login returns wrapped error object #540

Closed
panigrah opened this issue Oct 30, 2017 · 9 comments
Closed

Comments

@panigrah
Copy link

Hi,
I am unable to identify the error appropriately when the network connection is down and the auth0 services are not available.

This is my code.

webAuth.client.login({ username, password, realm: authRealm },
        (err, authResult) => {
          // the error object is wrapped and error code + message are blank   
          if (err) {  return reject(err); }        
          resolve(authResult);
     });

This is the error when I print the error

{ original: "Error: Request has been terminated Possible causes: the network is offline, Origin is not allowed by…, code: null, description: null, name: "Error"}

There is no error code or description. How do I cleanly catch this and other errors that may not be authentication errors?

thanks

@amoldavsky
Copy link

in Chrome this is intermittent , in Safari it is always an issue basically getting stuck in an infinite login loop.
This is very annoying so i am debugging to get to the bottom of this...

@amoldavsky
Copy link

ok, debugging the source leads to this for me...
when putting a breakpoint in:

verifier.verify(token, nonce, function(err, payload) {
    if (err) {
        return cb(error.invalidJwt(err.message));
    }

    cb(null, payload);
});

The actual error is:
"{"line":34205,"column":22,"sourceURL":"http://dev.donr.io:4200/vendor.bundle.js\",\"crossDomain\":true,\"method\":\"GET\",\"url\":\"https://donr-staging.auth0.com/.well-known/jwks.json\"}" = $2

So I did the following in the Safari console:

fetch( 'https://donr-staging.auth0.com/.well-known/jwks.json' ).then( console.dir );

and got
Fetch API cannot load https://donr-staging.auth0.com/.well-known/jwks.json due to access control checks.

I would take a wild guess that the issue is because the site is running off of https and making a XHR GET request to another https and Safari does not like this dues to some CORS issue.

I will debug deeper

@amoldavsky
Copy link

amoldavsky commented Nov 13, 2017

something with superagent....

console.log( err.message )
"Request has been terminated
Possible causes: the network is offline, Origin is not allowed by Access-Control-Allow-Origin, the page is being unloaded, etc."

when i try to explicitly set the request headers ( even though it's a GET request ):

function getJWKS(options, cb) {
  var url = urljoin(options.iss, '.well-known', 'jwks.json');

  return request
    .get(url)
    .withCredentials()
    .set( 'Origin', window.location.origin )
    .set( 'Access-Control-Request-Method', 'GET' )
    .end(function (err, data) { ... });
}

I get:

Refused to set unsafe header "Origin"
Refused to set unsafe header "Access-Control-Request-Method"

@amoldavsky
Copy link

i guess it's one of these issues....

so doing this work:

function getJWKS(options, cb) {
  var url = urljoin(options.iss, '.well-known', 'jwks.json');

  console.log( "moo1!" );
  fetch( 'https://donr-staging.auth0.com/.well-known/jwks.json')
    .then( (response) => {
      console.log( "moo moo 1 !!" )
    })
    .catch( (err) => {
      console.error( err );
    });

  return request
    .get(url)
    .end(function (err, data) {
      console.log( "moo moo 9 !!!" );
      var matchingKey = null;
      var a;
      var key;

      if (err) {
        cb(err);
      }

      // eslint-disable-next-line no-plusplus
      for (a = 0; a < data.body.keys.length && matchingKey === null; a++) {
        key = data.body.keys[a];
        if (key.kid === options.kid) {
          matchingKey = key;
        }
      }

      cb(null, process(matchingKey));
    });
}

so pre-fetchign the file beforehand makes superagent work.

@luisrudge
Copy link
Contributor

luisrudge commented Nov 14, 2017

Since you can reproduce in your machine, can you get me a .HAR file of the failed request? I'll send this to our infra team.

https://auth0.com/docs/support/troubleshooting-with-har-files

@amoldavsky
Copy link

amoldavsky commented Nov 14, 2017

@luisrudge unfortunately stupid Safari does not have the capability to export HARs... 👎

I will try to catch this case in Chrome again and get the HAR.

For Safari I captured screenshots of the broken and working request details, they look very different...

broken:
broken-request

working:
working-request

@amoldavsky
Copy link

amoldavsky commented Nov 14, 2017

@luisrudge I believe i figured the issue... it was a combination of things.

since I was working off of my dev box i dont use https, so in the jwks.js file I have forced the well kmnown hosts url to be non https just to take out all kind of SSL issues out of the way. Doing this triggers some kind of a weird redirect effect ( that is why the weird error in the Safari screenshot about redirect and CORS ), while in Chrome i saw all the responses clearly. I have attached the HAR files.

auth0-error.zip

When that been resolved, I noticed that the intermittent issue that I was talking about earlier in Chrome, actually was about the state in the transaction not matching the state that was coming back with the
token.

{error: "invalid_token", errorDescription: "`state` does not match."}

Though, @luisrudge going through the code I have a question.
Why isn't the transaction property allowed to be passed in to WebAuth?
the constructor has:

function WebAuth(options) {
  /* eslint-disable */
  assert.check(
    options,
    { type: 'object', message: 'options parameter is not valid' },
    {
      domain: { type: 'string', message: 'domain option is required' },
      clientID: { type: 'string', message: 'clientID option is required' },
      responseType: { optional: true, type: 'string', message: 'responseType is not valid' },
      responseMode: { optional: true, type: 'string', message: 'responseMode is not valid' },
      redirectUri: { optional: true, type: 'string', message: 'redirectUri is not valid' },
      scope: { optional: true, type: 'string', message: 'scope is not valid' },
      audience: { optional: true, type: 'string', message: 'audience is not valid' },
      leeway: { optional: true, type: 'number', message: 'leeway is not valid' },
      plugins: { optional: true, type: 'array', message: 'plugins is not valid' },
      _disableDeprecationWarnings: {
        optional: true,
        type: 'boolean',
        message: '_disableDeprecationWarnings option is not valid'
      },
      _sendTelemetry: {
        optional: true,
        type: 'boolean',
        message: '_sendTelemetry option is not valid'
      },
      _telemetryInfo: {
        optional: true,
        type: 'object',
        message: '_telemetryInfo option is not valid'
      },
      _timesToRetryFailedRequests: {
        optional: true,
        type: 'number',
        message: '_timesToRetryFailedRequests option is not valid'
      }
    }
  );
  ...
  this.baseOptions = options;
  ...
  this.transactionManager = new TransactionManager(this.baseOptions.transaction);
  ...
}

As I am reading this, this.baseOptions.transaction will never be set to anything?

Thanks
-Assaf

@luisrudge
Copy link
Contributor

You can set the namespace and keyLenght, but you can't set the actual transaction. We manage all the steps of the transaction: https://github.com/auth0/auth0.js/blob/master/src/web-auth/transaction-manager.js#L6

Since yours is a different issue than the original one, please open a new issue with the proper steps to reproduce the error and a code snippet so I can understand how are you using the SDK.

@luisrudge
Copy link
Contributor

@panigrah I just tested this and you're right. The real issue here is that we can't not for sure if it's a connectivity issue (offline) or a CORS issue. I know it sucks, but the workaround here is to check for the property error. If it's undefined, it's probably a connection/CORS issue. If it has a value, use that. If you use the new method webAuth.login, it will handle an offline connection gracefully. To use that, you need to enable Cross Origin Authentication. See more here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants