Amplify-js: Auth.currentSession keeps calling https://cognito-idp.<region>.amazonaws.com/

Created on 2 Oct 2018  路  12Comments  路  Source: aws-amplify/amplify-js

Describe the bug
Whenever Auth.currentSession() is called, it will do a request to https://cognito-idp.us-east-1.amazonaws.com/ (AWSCognitoIdentityProviderService.GetUser). I think session should be cached until it expires.

To Reproduce
Steps to reproduce the behavior:
Call:

let session = await Auth.currentSession(); 

Check network tab in (say) Chrome and see new request to https://cognito-idp.us-east-1.amazonaws.com/
Headers:

Content-Type: application/x-amz-json-1.1
DNT: 1
Origin: http://localhost:3000
Referer: http://localhost:3000/
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36
X-Amz-Target: AWSCognitoIdentityProviderService.GetUser
X-Amz-User-Agent: aws-amplify/0.1.x js

Expected behavior
Auth.currentSession() returns cached version until it has expired. Token info does get stored in local storage.

Additional context
aws-amplify:1.14
aws-amplify-react: 2.0.5

config:

Amplify.configure({
    Auth: {
        mandatorySignIn: true,
        identityPoolId: xxx,
        region: xxx,
        userPoolId: xxx,
        userPoolWebClientId: xxx,

    },
    Analytics: {
        disabled: true
    }
});
Auth feature-request

Most helpful comment

@powerful23 Please consider filing this as a bug. The implementation leaks HTTP requests, which is obviously not intended. IME it is not a feature to have unintended behavior removed.

All 12 comments

@bh213 thanks for you feedback. I agree that we should provide an option for the user to get the user/session only from the cache without sending a request to Cognito. This would also allow us to let Auth module work under offline scenario. Mark as feature request.

@powerful23 Is there a best practice on how to cache idToken.jwtToken that would also properly handle signout/switch user scenario?

From my debugging it seems idToken gets stored in local storage while user data (attributes and such) are always refreshed using AWSCognitoIdentityProviderService.GetUser. So just loading id from storage might actually work but unfortunately there is no expire date (except encoded in jwt)...

I am facing this issue too, there are a lot of calls to Cognito when calling currentUserInfo(), sometimes, there are 6 requests. Hopefully, we can fix this issue soon.

Just a reminder: "@aws-amplify/auth": "1.0.3" didn't make a request to Cognito servers. It returned a cached session. We are really missing this behaviour in the latest version.

My current workaround:

async function currentIdentity() {
  const cachePrefix = `CognitoIdentityServiceProvider.${environment.cognito.clientId}`;
  const lastUser = localStorage.getItem(`${cachePrefix}.LastAuthUser`);
  if (lastUser == null) return null;

  const idToken = localStorage.getItem(`${cachePrefix}.${lastUser}.idToken`);
  if (idToken == null) throw Error('Failed to read IdToken from cache!');

  const identity = JSON.parse(atob(idToken.split('.')[1]));

  const expires = identity.exp;
  const clockDrift = Number(localStorage.getItem(`${cachePrefix}.${lastUser}.clockDrift`) || 0);

  const now = Math.ceil(Date.now() / 1000);
  if (expires + clockDrift < now) {
    const session = await Auth.currentSession();
    if (session == null) return null;
    return session.getIdToken().decodePayload();
  }

  return identity;
}

The last if is there just for the case when Amplify is already trying to refresh the token. But to be honest, I'm not sure if Auth.currentSession() returns a new token or not. However, it is an edge case so it is probably enough for now.

I faced the same issue and found the cause:

For my case, I need only fresh JWT for API requests, so, I fixed this issue in the following way:

import { CognitoUserPool } from 'amazon-cognito-identity-js';
import AWSConfig from './AwsConfig';

function getUserSession() {
  const NO_USER_ERROR_MESSAGE = 'Could not find the cognito user';

  return new Promise((resolve, reject) => {
    const USER_POOL_CONFIG = {
      UserPoolId: AWSConfig.UserPoolId,
      ClientId: AWSConfig.ClientId
    };
    const userPool = new CognitoUserPool(USER_POOL_CONFIG);
    const cognitoUser = userPool.getCurrentUser();

    if (cognitoUser) {
      cognitoUser.getSession((err, session) => {
        if (!err) {
          resolve(session);
        } else {
          reject(err);
        }
      });
    } else {
      reject(new Error(NO_USER_ERROR_MESSAGE));
    }
  });
}

I just removed the code that calls the server every time and used the 'amazon-cognito-identity-js' library directly. getSession() should refresh token automatically. I hope this can help someone

@powerful23 is there any ETA for this feature?

@powerful23 Please consider filing this as a bug. The implementation leaks HTTP requests, which is obviously not intended. IME it is not a feature to have unintended behavior removed.

I think so too @lgrapenthin!
This is not intended and that should be a bug. Do we just need a PR or who is in charge of getting this done? /cc @powerful23

Is there any way of not having to cache the Authentication token yourself currently? We have quite a few requests on a dashboard like page and this is driving our cognito requests into rate limitation by Amplify. This is really an issue :/

Maintainers? How can we help? Should we provide a PR?

@kjellski hey we just had an internal discussion around this issue. We will take an action to resolve this in the next two days.

@powerful23 wonderful news! Thank you a lot for considering this a priority and fixing it ASAP! Keep up the good work!

Was this page helpful?
0 / 5 - 0 ratings