How to persist Cognito identity across pages in browser

牧云@^-^@ 提交于 2019-12-31 13:44:22

问题


I am authenticating through Cognito on client side browser using a developer authenticated identity. When my page loads (or is refreshed) I would like my application to remember the Identity for as long as the object is not expired (I think it lasts about an hour). However, I don't know how to retrieve the identity from Cognito without having to go through the developer authentication again.

Here is what the code does on page load:

var cognitoCredentials

$(document).ready(function() { 
    "use strict";

    cognitoParams = {
      IdentityPoolId: 'us-east-1:xxxxxxx'
    };

    cognitoCredentials = new AWS.CognitoIdentityCredentials(cognitoParams);
    AWS.config.credentials = cognitoCredentials;

});

And after logging in through the developer authentication:

cognitoCredentials.params.IdentityId = output.identityId;
cognitoCredentials.params.Logins = {
    'cognito-identity.amazonaws.com': output.token
};
cognitoCredentials.expired = true;

If I have already logged in, and then refresh the page, and try to log in again I get an error that I am trying to get an identity when I already have one Error: Missing credentials in config(…) NotAuthorizedException: Missing credentials in config "Access to Identity 'us-east-1:xxxxxxx' is forbidden."

However, I don't know how to access it. How do I retrieve the credentials so that when the page is refreshed, I can detect the previous identity given by Cognito?


回答1:


The only way to get back to the same identity on page refresh would be to use the same token used to initialize that identity. You may want to refer to this question as the problems are similar (replacing the Facebook token with the OpenId Connect token from the developer authenticated identities flow).

To reiterate what that question says: the credentials in the SDK will not be persisted across pages, so you should cache the token to be reused.




回答2:


Save at least accessKeyId, secretAccessKey, sessionToken in sessionStorage between pages. You can load these into AWS.config.credentials (after the AWS SDK has been loaded of course). It is much faster than waiting for Cognito to respond. Keep in mind, you'll have to manually refresh them with a token from one of the providers and this is only good until the temporary token expires (~1 hour).

var credKeys = [
    'accessKeyId',
    'secretAccessKey',
    'sessionToken'
];

// After Cognito login
credKeys.forEach(function(key) {
    sessionStorage.setItem(key, AWS.config.credentials[key]);
});

// After AWS SDK load

AWS.config.region = 'us-east-1'; // pick your region

credKeys.forEach(function(key) {
    AWS.config.credentials[key] = sessionStorage.getItem(key);
});

// Now make your AWS calls to S3, DynamoDB, etc



回答3:


I take a slightly different approach, that allows the SDK to refresh the credentials.

In short, I serialize the AssumeRoleWithWebIdentityRequest JSON object to session storage.

Here is an example using Angular, but concept applies in any JS app:

const AWS = require('aws-sdk/global');
import { STS } from 'aws-sdk';

import { environment } from '../../environments/environment';

const WEB_IDENT_CREDS_SS_KEY = 'ic.tmpAwsCreds';

// Handle tmp aws creds across page refreshes
const tmpCreds = sessionStorage.getItem(WEB_IDENT_CREDS_SS_KEY);
if (!!tmpCreds) {
  AWS.config.credentials = new AWS.WebIdentityCredentials(JSON.parse(tmpCreds));
}

@Injectable({
  providedIn: 'root'
})
export class AuthService {

...

  async assumeAwsRoleFromWebIdent(fbUser: firebase.User) {
    const token = await fbUser.getIdToken(false);
    let p: STS.Types.AssumeRoleWithWebIdentityRequest = {
      ...environment.stsAssumeWebIdentConfig,
      //environment.stsAssumeWebIdentConfig contains:
      //DurationSeconds: 3600,
      //RoleArn: 'arn:aws:iam::xxx:role/investmentclub-fbase-trust',
      RoleSessionName: fbUser.uid + '@' + (+new Date()),
      WebIdentityToken: token
    };

    // Store creds across page refresh, duno WTF `new AWS.WebIdentityCredentials(p)` don't have an option for this
    AWS.config.credentials = new AWS.WebIdentityCredentials(p);
    sessionStorage.setItem(WEB_IDENT_CREDS_SS_KEY, JSON.stringify(p));
  }

  removeAwsTempCreds() {
    AWS.config.credentials = {};
    sessionStorage.removeItem(WEB_IDENT_CREDS_SS_KEY);
  }

...

Few things to note:

  • Upon login, I store the WebIdentityCredentials parameters as a JSON string in session cache.
  • You'll notice I check the browser session cache in global scope, to handle page refreshes (sets creds before they can be used).

A tutorial with complete example can be found on my blog



来源:https://stackoverflow.com/questions/32612530/how-to-persist-cognito-identity-across-pages-in-browser

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!