UNPKG

@aws-amplify/auth

Version:
206 lines (204 loc) • 9.2 kB
'use strict'; // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 Object.defineProperty(exports, "__esModule", { value: true }); exports.CognitoAWSCredentialsAndIdentityIdProvider = void 0; const core_1 = require("@aws-amplify/core"); const utils_1 = require("@aws-amplify/core/internals/utils"); const AuthError_1 = require("../../../errors/AuthError"); const assertServiceError_1 = require("../../../errors/utils/assertServiceError"); const parsers_1 = require("../../../foundation/parsers"); const types_1 = require("../utils/types"); const factories_1 = require("../factories"); const IdentityIdProvider_1 = require("./IdentityIdProvider"); const utils_2 = require("./utils"); const logger = new core_1.ConsoleLogger('CognitoCredentialsProvider'); const CREDENTIALS_TTL = 50 * 60 * 1000; // 50 min, can be modified on config if required in the future class CognitoAWSCredentialsAndIdentityIdProvider { constructor(identityIdStore) { this._nextCredentialsRefresh = 0; this._identityIdStore = identityIdStore; } async clearCredentialsAndIdentityId() { logger.debug('Clearing out credentials and identityId'); this._credentialsAndIdentityId = undefined; await this._identityIdStore.clearIdentityId(); } async clearCredentials() { logger.debug('Clearing out in-memory credentials'); this._credentialsAndIdentityId = undefined; } async getCredentialsAndIdentityId(getCredentialsOptions) { const isAuthenticated = getCredentialsOptions.authenticated; const { tokens } = getCredentialsOptions; const { authConfig } = getCredentialsOptions; try { (0, utils_1.assertIdentityPoolIdConfig)(authConfig?.Cognito); } catch { // No identity pool configured, skipping return; } if (!isAuthenticated && !authConfig.Cognito.allowGuestAccess) { // TODO(V6): return partial result like Native platforms return; } const { forceRefresh } = getCredentialsOptions; const tokenHasChanged = this.hasTokenChanged(tokens); const identityId = await (0, IdentityIdProvider_1.cognitoIdentityIdProvider)({ tokens, authConfig: authConfig.Cognito, identityIdStore: this._identityIdStore, }); // Clear cached credentials when forceRefresh is true OR the cache token has changed if (forceRefresh || tokenHasChanged) { this.clearCredentials(); } if (!isAuthenticated) { return this.getGuestCredentials(identityId, authConfig.Cognito); } else { (0, types_1.assertIdTokenInAuthTokens)(tokens); return this.credsForOIDCTokens(authConfig.Cognito, tokens, identityId); } } async getGuestCredentials(identityId, authConfig) { // Return existing in-memory cached credentials only if it exists, is not past it's lifetime and is unauthenticated credentials if (this._credentialsAndIdentityId && !this.isPastTTL() && this._credentialsAndIdentityId.isAuthenticatedCreds === false) { logger.info('returning stored credentials as they neither past TTL nor expired.'); return this._credentialsAndIdentityId; } // Clear to discard if any authenticated credentials are set and start with a clean slate this.clearCredentials(); const region = (0, parsers_1.getRegionFromIdentityPoolId)(authConfig.identityPoolId); const getCredentialsForIdentity = (0, core_1.createGetCredentialsForIdentityClient)({ endpointResolver: (0, factories_1.createCognitoIdentityPoolEndpointResolver)({ endpointOverride: authConfig.identityPoolEndpoint, }), }); // use identityId to obtain guest credentials // save credentials in-memory // No logins params should be passed for guest creds: // https://docs.aws.amazon.com/cognitoidentity/latest/APIReference/API_GetCredentialsForIdentity.html let clientResult; try { clientResult = await getCredentialsForIdentity({ region }, { IdentityId: identityId, }); } catch (e) { (0, assertServiceError_1.assertServiceError)(e); throw new AuthError_1.AuthError(e); } if (clientResult?.Credentials?.AccessKeyId && clientResult?.Credentials?.SecretKey) { this._nextCredentialsRefresh = new Date().getTime() + CREDENTIALS_TTL; const res = { credentials: { accessKeyId: clientResult.Credentials.AccessKeyId, secretAccessKey: clientResult.Credentials.SecretKey, sessionToken: clientResult.Credentials.SessionToken, expiration: clientResult.Credentials.Expiration, }, identityId, }; if (clientResult.IdentityId) { res.identityId = clientResult.IdentityId; this._identityIdStore.storeIdentityId({ id: clientResult.IdentityId, type: 'guest', }); } this._credentialsAndIdentityId = { ...res, isAuthenticatedCreds: false, }; return res; } else { throw new AuthError_1.AuthError({ name: 'CredentialsNotFoundException', message: `Cognito did not respond with either Credentials, AccessKeyId or SecretKey.`, }); } } async credsForOIDCTokens(authConfig, authTokens, identityId) { if (this._credentialsAndIdentityId && !this.isPastTTL() && this._credentialsAndIdentityId.isAuthenticatedCreds === true) { logger.debug('returning stored credentials as they neither past TTL nor expired.'); return this._credentialsAndIdentityId; } // Clear to discard if any unauthenticated credentials are set and start with a clean slate this.clearCredentials(); const logins = authTokens.idToken ? (0, utils_2.formLoginsMap)(authTokens.idToken.toString()) : {}; const region = (0, parsers_1.getRegionFromIdentityPoolId)(authConfig.identityPoolId); const getCredentialsForIdentity = (0, core_1.createGetCredentialsForIdentityClient)({ endpointResolver: (0, factories_1.createCognitoIdentityPoolEndpointResolver)({ endpointOverride: authConfig.identityPoolEndpoint, }), }); let clientResult; try { clientResult = await getCredentialsForIdentity({ region }, { IdentityId: identityId, Logins: logins, }); } catch (e) { (0, assertServiceError_1.assertServiceError)(e); throw new AuthError_1.AuthError(e); } if (clientResult?.Credentials?.AccessKeyId && clientResult?.Credentials?.SecretKey) { this._nextCredentialsRefresh = new Date().getTime() + CREDENTIALS_TTL; const res = { credentials: { accessKeyId: clientResult.Credentials.AccessKeyId, secretAccessKey: clientResult.Credentials.SecretKey, sessionToken: clientResult.Credentials.SessionToken, expiration: clientResult.Credentials.Expiration, }, identityId, }; if (clientResult.IdentityId) { res.identityId = clientResult.IdentityId; // note: the following call removes guest identityId from the persistent store (localStorage) this._identityIdStore.storeIdentityId({ id: clientResult.IdentityId, type: 'primary', }); } // Store the credentials in-memory along with the expiration this._credentialsAndIdentityId = { ...res, isAuthenticatedCreds: true, associatedIdToken: authTokens.idToken?.toString(), }; return res; } else { throw new AuthError_1.AuthError({ name: 'CredentialsException', message: `Cognito did not respond with either Credentials, AccessKeyId or SecretKey.`, }); } } isPastTTL() { return this._nextCredentialsRefresh === undefined ? true : this._nextCredentialsRefresh <= Date.now(); } hasTokenChanged(tokens) { return (!!tokens && !!this._credentialsAndIdentityId?.associatedIdToken && tokens.idToken?.toString() !== this._credentialsAndIdentityId.associatedIdToken); } } exports.CognitoAWSCredentialsAndIdentityIdProvider = CognitoAWSCredentialsAndIdentityIdProvider; //# sourceMappingURL=credentialsProvider.js.map