isotoma / react-cognito

Library for integrating Facebook React and Amazon Cognito
Apache License 2.0
116 stars 48 forks source link

Stale Token #32

Closed NatalieFrecka closed 6 years ago

NatalieFrecka commented 6 years ago

I'm having trouble with stale auth tokens. I'm sending the signInUserSession.idToken.jwtToken as an Authorization header in all of my fetch requests, but it appears that the token expires fairly quickly and is only refreshed on page reload. This is an issue when the webapp is left open and idle and then a fetch request is made without reloading the page.

Is there something I've missed in the setup, or some function I've overlooked that will refresh the token? I didn't see anything about this in the docs. If anyone could offer up any solutions or insight it would be greatly appreciated.

Edit: Figured it out by checking out theamazon-cognito-identity-js docs.

orther commented 6 years ago

@NatalieFrecka would you share what solution to this you figured out?

NatalieFrecka commented 6 years ago

@orther This seems to have solved our issues. Hopefully this at least points you in a good direction.

import { CognitoUser, CognitoRefreshToken } from 'amazon-cognito-identity-js';

return new Promise(function(resolve, reject) {
   user.getSession(function(err, session) {
      if (err) { throw err; }
      if (session.isValid()) {
         resolve(user.signInUserSession.idToken.jwtToken);
      } else {
         const RefreshToken = new CognitoRefreshToken({
            RefreshToken: user.signInUserSession.refreshToken.token
         });

         user.refreshSession(RefreshToken, (err, session) => {
            if (err) { throw err; }
            resolve(session.idToken.jwtToken);
         });
      }
   });
});
orther commented 6 years ago

Thanks @NatalieFrecka I really appreciate this. One last question, when do you call that code? I would think it either needs to be called on a regular interval to prevent the session from going stale unless you can call it once you detect the token expired/stale.

NatalieFrecka commented 6 years ago

@orther No problem. Happy to help. In our situation we send the user's idToken to the server as an authorization header, so we call this before every fetch, which is why I'm resolving with the token. It's a quick process, especially if the token is valid, so I don't feel like it's adding a perceptible wait time to our fetching. It's worked out well for us so far.

bmoquist commented 6 years ago

Thanks for sharing @NatalieFrecka -- I looked into the source and looks like getSession already does the checking (both if the session is valid, and if it isn't, then it checks if there a valid cached session). Based on the checks, it returns the existing valid signInUserSession object or uses the refresh token to return a new valid signInUserSession object if the others have expired. Thus, think only the following is needed:

user.getSession(function(err, session) {
    if (err) {
        throw err;
    } else {
        resolve(session)
    }
})

If only the id or access token is needed, the token could be returned by resolving session.idToken.jwtToken:

Here is the source code for the getSession method: https://github.com/aws/amazon-cognito-identity-js/blob/f11d39b14d5952c97dbb993ad1390ed70b3300cc/src/CognitoUser.js#L801