UNPKG

@aws-amplify/auth

Version:
1,071 lines • 125 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 }); var tslib_1 = require("tslib"); var types_1 = require("./types"); var core_1 = require("@aws-amplify/core"); var amazon_cognito_identity_js_1 = require("amazon-cognito-identity-js"); var url_1 = require("url"); var OAuth_1 = tslib_1.__importDefault(require("./OAuth/OAuth")); var urlListener_1 = tslib_1.__importDefault(require("./urlListener")); var Errors_1 = require("./Errors"); var Auth_1 = require("./types/Auth"); var logger = new core_1.ConsoleLogger('AuthClass'); var USER_ADMIN_SCOPE = 'aws.cognito.signin.user.admin'; // 10 sec, following this guide https://www.nngroup.com/articles/response-times-3-important-limits/ var OAUTH_FLOW_MS_TIMEOUT = 10 * 1000; var AMPLIFY_SYMBOL = (typeof Symbol !== 'undefined' && typeof Symbol.for === 'function' ? Symbol.for('amplify_default') : '@@amplify_default'); var dispatchAuthEvent = function (event, data, message) { core_1.Hub.dispatch('auth', { event: event, data: data, message: message }, 'Auth', AMPLIFY_SYMBOL); }; // Cognito Documentation for max device // tslint:disable-next-line:max-line-length // https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ListDevices.html#API_ListDevices_RequestSyntax var MAX_DEVICES = 60; var MAX_AUTOSIGNIN_POLLING_MS = 3 * 60 * 1000; /** * Provide authentication steps */ var AuthClass = /** @class */ (function () { /** * Initialize Auth with AWS configurations * @param {Object} config - Configuration of the Auth */ function AuthClass(config) { var _this = this; this.userPool = null; this.user = null; this.oAuthFlowInProgress = false; this.autoSignInInitiated = false; this.inflightSessionPromise = null; this.inflightSessionPromiseCounter = 0; this.Credentials = core_1.Credentials; this.wrapRefreshSessionCallback = function (callback) { var wrapped = function (error, data) { if (data) { dispatchAuthEvent('tokenRefresh', undefined, "New token retrieved"); } else { dispatchAuthEvent('tokenRefresh_failure', error, "Failed to retrieve new token"); } return callback(error, data); }; return wrapped; }; // prettier-ignore this.configure(config); this.currentCredentials = this.currentCredentials.bind(this); this.currentUserCredentials = this.currentUserCredentials.bind(this); core_1.Hub.listen('auth', function (_a) { var payload = _a.payload; var event = payload.event; switch (event) { case 'verify': case 'signIn': _this._storage.setItem('amplify-signin-with-hostedUI', 'false'); break; case 'signOut': _this._storage.removeItem('amplify-signin-with-hostedUI'); break; case 'cognitoHostedUI': _this._storage.setItem('amplify-signin-with-hostedUI', 'true'); break; } }); } AuthClass.prototype.getModuleName = function () { return 'Auth'; }; AuthClass.prototype.configure = function (config) { var _this = this; if (!config) return this._config || {}; logger.debug('configure Auth'); var conf = Object.assign({}, this._config, core_1.parseAWSExports(config).Auth, config); this._config = conf; var _a = this._config, userPoolId = _a.userPoolId, userPoolWebClientId = _a.userPoolWebClientId, cookieStorage = _a.cookieStorage, oauth = _a.oauth, region = _a.region, identityPoolId = _a.identityPoolId, mandatorySignIn = _a.mandatorySignIn, refreshHandlers = _a.refreshHandlers, identityPoolRegion = _a.identityPoolRegion, clientMetadata = _a.clientMetadata, endpoint = _a.endpoint, storage = _a.storage; if (!storage) { // backward compatability if (cookieStorage) this._storage = new amazon_cognito_identity_js_1.CookieStorage(cookieStorage); else { this._storage = config.ssr ? new core_1.UniversalStorage() : new core_1.StorageHelper().getStorage(); } } else { if (!this._isValidAuthStorage(storage)) { logger.error('The storage in the Auth config is not valid!'); throw new Error('Empty storage object'); } this._storage = storage; } this._storageSync = Promise.resolve(); if (typeof this._storage['sync'] === 'function') { this._storageSync = this._storage['sync'](); } if (userPoolId) { var userPoolData = { UserPoolId: userPoolId, ClientId: userPoolWebClientId, endpoint: endpoint, }; userPoolData.Storage = this._storage; this.userPool = new amazon_cognito_identity_js_1.CognitoUserPool(userPoolData, this.wrapRefreshSessionCallback); } this.Credentials.configure({ mandatorySignIn: mandatorySignIn, region: region, userPoolId: userPoolId, identityPoolId: identityPoolId, refreshHandlers: refreshHandlers, storage: this._storage, identityPoolRegion: identityPoolRegion, }); // initialize cognitoauth client if hosted ui options provided // to keep backward compatibility: var cognitoHostedUIConfig = oauth ? types_1.isCognitoHostedOpts(this._config.oauth) ? oauth : oauth.awsCognito : undefined; if (cognitoHostedUIConfig) { var cognitoAuthParams = Object.assign({ cognitoClientId: userPoolWebClientId, UserPoolId: userPoolId, domain: cognitoHostedUIConfig['domain'], scopes: cognitoHostedUIConfig['scope'], redirectSignIn: cognitoHostedUIConfig['redirectSignIn'], redirectSignOut: cognitoHostedUIConfig['redirectSignOut'], responseType: cognitoHostedUIConfig['responseType'], Storage: this._storage, urlOpener: cognitoHostedUIConfig['urlOpener'], clientMetadata: clientMetadata, }, cognitoHostedUIConfig['options']); this._oAuthHandler = new OAuth_1.default({ scopes: cognitoAuthParams.scopes, config: cognitoAuthParams, cognitoClientId: cognitoAuthParams.cognitoClientId, }); // **NOTE** - Remove this in a future major release as it is a breaking change // Prevents _handleAuthResponse from being called multiple times in Expo // See https://github.com/aws-amplify/amplify-js/issues/4388 var usedResponseUrls_1 = {}; urlListener_1.default(function (_a) { var url = _a.url; if (usedResponseUrls_1[url]) { return; } usedResponseUrls_1[url] = true; _this._handleAuthResponse(url); }); } dispatchAuthEvent('configured', null, "The Auth category has been configured successfully"); if (!this.autoSignInInitiated && typeof this._storage['getItem'] === 'function') { var pollingInitiated = this.isTrueStorageValue('amplify-polling-started'); if (pollingInitiated) { dispatchAuthEvent('autoSignIn_failure', null, Auth_1.AuthErrorTypes.AutoSignInError); this._storage.removeItem('amplify-auto-sign-in'); } this._storage.removeItem('amplify-polling-started'); } return this._config; }; /** * Sign up with username, password and other attributes like phone, email * @param {String | object} params - The user attributes used for signin * @param {String[]} restOfAttrs - for the backward compatability * @return - A promise resolves callback data if success */ AuthClass.prototype.signUp = function (params) { var _this = this; var restOfAttrs = []; for (var _i = 1; _i < arguments.length; _i++) { restOfAttrs[_i - 1] = arguments[_i]; } var _a, _b, _c; if (!this.userPool) { return this.rejectNoUserPool(); } var username = null; var password = null; var attributes = []; var validationData = null; var clientMetadata; var autoSignIn = { enabled: false }; var autoSignInValidationData = {}; var autoSignInClientMetaData = {}; if (params && typeof params === 'string') { username = params; password = restOfAttrs ? restOfAttrs[0] : null; var email = restOfAttrs ? restOfAttrs[1] : null; var phone_number = restOfAttrs ? restOfAttrs[2] : null; if (email) attributes.push(new amazon_cognito_identity_js_1.CognitoUserAttribute({ Name: 'email', Value: email })); if (phone_number) attributes.push(new amazon_cognito_identity_js_1.CognitoUserAttribute({ Name: 'phone_number', Value: phone_number, })); } else if (params && typeof params === 'object') { username = params['username']; password = params['password']; if (params && params.clientMetadata) { clientMetadata = params.clientMetadata; } else if (this._config.clientMetadata) { clientMetadata = this._config.clientMetadata; } var attrs_1 = params['attributes']; if (attrs_1) { Object.keys(attrs_1).map(function (key) { attributes.push(new amazon_cognito_identity_js_1.CognitoUserAttribute({ Name: key, Value: attrs_1[key] })); }); } var validationDataObject_1 = params['validationData']; if (validationDataObject_1) { validationData = []; Object.keys(validationDataObject_1).map(function (key) { validationData.push(new amazon_cognito_identity_js_1.CognitoUserAttribute({ Name: key, Value: validationDataObject_1[key], })); }); } autoSignIn = (_a = params.autoSignIn) !== null && _a !== void 0 ? _a : { enabled: false }; if (autoSignIn.enabled) { this._storage.setItem('amplify-auto-sign-in', 'true'); autoSignInValidationData = (_b = autoSignIn.validationData) !== null && _b !== void 0 ? _b : {}; autoSignInClientMetaData = (_c = autoSignIn.clientMetaData) !== null && _c !== void 0 ? _c : {}; } } else { return this.rejectAuthError(Auth_1.AuthErrorTypes.SignUpError); } if (!username) { return this.rejectAuthError(Auth_1.AuthErrorTypes.EmptyUsername); } if (!password) { return this.rejectAuthError(Auth_1.AuthErrorTypes.EmptyPassword); } logger.debug('signUp attrs:', attributes); logger.debug('signUp validation data:', validationData); return new Promise(function (resolve, reject) { _this.userPool.signUp(username, password, attributes, validationData, function (err, data) { if (err) { dispatchAuthEvent('signUp_failure', err, username + " failed to signup"); reject(err); } else { dispatchAuthEvent('signUp', data, username + " has signed up successfully"); if (autoSignIn.enabled) { _this.handleAutoSignIn(username, password, autoSignInValidationData, autoSignInClientMetaData, data); } resolve(data); } }, clientMetadata); }); }; AuthClass.prototype.handleAutoSignIn = function (username, password, validationData, clientMetadata, data) { this.autoSignInInitiated = true; var authDetails = new amazon_cognito_identity_js_1.AuthenticationDetails({ Username: username, Password: password, ValidationData: validationData, ClientMetadata: clientMetadata, }); if (data.userConfirmed) { this.signInAfterUserConfirmed(authDetails); } else if (this._config.signUpVerificationMethod === 'link') { this.handleLinkAutoSignIn(authDetails); } else { this.handleCodeAutoSignIn(authDetails); } }; AuthClass.prototype.handleCodeAutoSignIn = function (authDetails) { var _this = this; var listenEvent = function (_a) { var payload = _a.payload; if (payload.event === 'confirmSignUp') { _this.signInAfterUserConfirmed(authDetails, listenEvent); } }; core_1.Hub.listen('auth', listenEvent); }; AuthClass.prototype.handleLinkAutoSignIn = function (authDetails) { var _this = this; this._storage.setItem('amplify-polling-started', 'true'); var start = Date.now(); var autoSignInPollingIntervalId = setInterval(function () { if (Date.now() - start > MAX_AUTOSIGNIN_POLLING_MS) { clearInterval(autoSignInPollingIntervalId); dispatchAuthEvent('autoSignIn_failure', null, 'Please confirm your account and use your credentials to sign in.'); _this._storage.removeItem('amplify-auto-sign-in'); } else { _this.signInAfterUserConfirmed(authDetails, null, autoSignInPollingIntervalId); } }, 5000); }; AuthClass.prototype.signInAfterUserConfirmed = function (authDetails, listenEvent, autoSignInPollingIntervalId) { return tslib_1.__awaiter(this, void 0, void 0, function () { var user, error_1; var _this = this; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: user = this.createCognitoUser(authDetails.getUsername()); _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); return [4 /*yield*/, user.authenticateUser(authDetails, this.authCallbacks(user, function (value) { dispatchAuthEvent('autoSignIn', value, authDetails.getUsername() + " has signed in successfully"); if (listenEvent) { core_1.Hub.remove('auth', listenEvent); } if (autoSignInPollingIntervalId) { clearInterval(autoSignInPollingIntervalId); _this._storage.removeItem('amplify-polling-started'); } _this._storage.removeItem('amplify-auto-sign-in'); }, function (error) { logger.error(error); _this._storage.removeItem('amplify-auto-sign-in'); }))]; case 2: _a.sent(); return [3 /*break*/, 4]; case 3: error_1 = _a.sent(); logger.error(error_1); return [3 /*break*/, 4]; case 4: return [2 /*return*/]; } }); }); }; /** * Send the verification code to confirm sign up * @param {String} username - The username to be confirmed * @param {String} code - The verification code * @param {ConfirmSignUpOptions} options - other options for confirm signup * @return - A promise resolves callback data if success */ AuthClass.prototype.confirmSignUp = function (username, code, options) { var _this = this; if (!this.userPool) { return this.rejectNoUserPool(); } if (!username) { return this.rejectAuthError(Auth_1.AuthErrorTypes.EmptyUsername); } if (!code) { return this.rejectAuthError(Auth_1.AuthErrorTypes.EmptyCode); } var user = this.createCognitoUser(username); var forceAliasCreation = options && typeof options.forceAliasCreation === 'boolean' ? options.forceAliasCreation : true; var clientMetadata; if (options && options.clientMetadata) { clientMetadata = options.clientMetadata; } else if (this._config.clientMetadata) { clientMetadata = this._config.clientMetadata; } return new Promise(function (resolve, reject) { user.confirmRegistration(code, forceAliasCreation, function (err, data) { if (err) { reject(err); } else { dispatchAuthEvent('confirmSignUp', data, username + " has been confirmed successfully"); var autoSignIn = _this.isTrueStorageValue('amplify-auto-sign-in'); if (autoSignIn && !_this.autoSignInInitiated) { dispatchAuthEvent('autoSignIn_failure', null, Auth_1.AuthErrorTypes.AutoSignInError); _this._storage.removeItem('amplify-auto-sign-in'); } resolve(data); } }, clientMetadata); }); }; AuthClass.prototype.isTrueStorageValue = function (value) { var item = this._storage.getItem(value); return item ? item === 'true' : false; }; /** * Resend the verification code * @param {String} username - The username to be confirmed * @param {ClientMetadata} clientMetadata - Metadata to be passed to Cognito Lambda triggers * @return - A promise resolves code delivery details if successful */ AuthClass.prototype.resendSignUp = function (username, clientMetadata) { if (clientMetadata === void 0) { clientMetadata = this._config.clientMetadata; } if (!this.userPool) { return this.rejectNoUserPool(); } if (!username) { return this.rejectAuthError(Auth_1.AuthErrorTypes.EmptyUsername); } var user = this.createCognitoUser(username); return new Promise(function (resolve, reject) { user.resendConfirmationCode(function (err, data) { if (err) { reject(err); } else { resolve(data); } }, clientMetadata); }); }; /** * Sign in * @param {String | SignInOpts} usernameOrSignInOpts - The username to be signed in or the sign in options * @param {String} pw - The password of the username * @param {ClientMetaData} clientMetadata - Client metadata for custom workflows * @return - A promise resolves the CognitoUser */ AuthClass.prototype.signIn = function (usernameOrSignInOpts, pw, clientMetadata) { if (clientMetadata === void 0) { clientMetadata = this._config.clientMetadata; } if (!this.userPool) { return this.rejectNoUserPool(); } var username = null; var password = null; var validationData = {}; // for backward compatibility if (typeof usernameOrSignInOpts === 'string') { username = usernameOrSignInOpts; password = pw; } else if (types_1.isUsernamePasswordOpts(usernameOrSignInOpts)) { if (typeof pw !== 'undefined') { logger.warn('The password should be defined under the first parameter object!'); } username = usernameOrSignInOpts.username; password = usernameOrSignInOpts.password; validationData = usernameOrSignInOpts.validationData; } else { return this.rejectAuthError(Auth_1.AuthErrorTypes.InvalidUsername); } if (!username) { return this.rejectAuthError(Auth_1.AuthErrorTypes.EmptyUsername); } var authDetails = new amazon_cognito_identity_js_1.AuthenticationDetails({ Username: username, Password: password, ValidationData: validationData, ClientMetadata: clientMetadata, }); if (password) { return this.signInWithPassword(authDetails); } else { return this.signInWithoutPassword(authDetails); } }; /** * Return an object with the authentication callbacks * @param {CognitoUser} user - the cognito user object * @param {} resolve - function called when resolving the current step * @param {} reject - function called when rejecting the current step * @return - an object with the callback methods for user authentication */ AuthClass.prototype.authCallbacks = function (user, resolve, reject) { var _this = this; var that = this; return { onSuccess: function (session) { return tslib_1.__awaiter(_this, void 0, void 0, function () { var cred, e_1, currentUser, e_2; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: logger.debug(session); delete user['challengeName']; delete user['challengeParam']; _a.label = 1; case 1: _a.trys.push([1, 4, 5, 9]); return [4 /*yield*/, this.Credentials.clear()]; case 2: _a.sent(); return [4 /*yield*/, this.Credentials.set(session, 'session')]; case 3: cred = _a.sent(); logger.debug('succeed to get cognito credentials', cred); return [3 /*break*/, 9]; case 4: e_1 = _a.sent(); logger.debug('cannot get cognito credentials', e_1); return [3 /*break*/, 9]; case 5: _a.trys.push([5, 7, , 8]); return [4 /*yield*/, this.currentUserPoolUser()]; case 6: currentUser = _a.sent(); that.user = currentUser; dispatchAuthEvent('signIn', currentUser, "A user " + user.getUsername() + " has been signed in"); resolve(currentUser); return [3 /*break*/, 8]; case 7: e_2 = _a.sent(); logger.error('Failed to get the signed in user', e_2); reject(e_2); return [3 /*break*/, 8]; case 8: return [7 /*endfinally*/]; case 9: return [2 /*return*/]; } }); }); }, onFailure: function (err) { logger.debug('signIn failure', err); dispatchAuthEvent('signIn_failure', err, user.getUsername() + " failed to signin"); reject(err); }, customChallenge: function (challengeParam) { logger.debug('signIn custom challenge answer required'); user['challengeName'] = 'CUSTOM_CHALLENGE'; user['challengeParam'] = challengeParam; resolve(user); }, mfaRequired: function (challengeName, challengeParam) { logger.debug('signIn MFA required'); user['challengeName'] = challengeName; user['challengeParam'] = challengeParam; resolve(user); }, mfaSetup: function (challengeName, challengeParam) { logger.debug('signIn mfa setup', challengeName); user['challengeName'] = challengeName; user['challengeParam'] = challengeParam; resolve(user); }, newPasswordRequired: function (userAttributes, requiredAttributes) { logger.debug('signIn new password'); user['challengeName'] = 'NEW_PASSWORD_REQUIRED'; user['challengeParam'] = { userAttributes: userAttributes, requiredAttributes: requiredAttributes, }; resolve(user); }, totpRequired: function (challengeName, challengeParam) { logger.debug('signIn totpRequired'); user['challengeName'] = challengeName; user['challengeParam'] = challengeParam; resolve(user); }, selectMFAType: function (challengeName, challengeParam) { logger.debug('signIn selectMFAType', challengeName); user['challengeName'] = challengeName; user['challengeParam'] = challengeParam; resolve(user); }, }; }; /** * Sign in with a password * @private * @param {AuthenticationDetails} authDetails - the user sign in data * @return - A promise resolves the CognitoUser object if success or mfa required */ AuthClass.prototype.signInWithPassword = function (authDetails) { var _this = this; if (this.pendingSignIn) { throw new Error('Pending sign-in attempt already in progress'); } var user = this.createCognitoUser(authDetails.getUsername()); this.pendingSignIn = new Promise(function (resolve, reject) { user.authenticateUser(authDetails, _this.authCallbacks(user, function (value) { _this.pendingSignIn = null; resolve(value); }, function (error) { _this.pendingSignIn = null; reject(error); })); }); return this.pendingSignIn; }; /** * Sign in without a password * @private * @param {AuthenticationDetails} authDetails - the user sign in data * @return - A promise resolves the CognitoUser object if success or mfa required */ AuthClass.prototype.signInWithoutPassword = function (authDetails) { var _this = this; var user = this.createCognitoUser(authDetails.getUsername()); user.setAuthenticationFlowType('CUSTOM_AUTH'); return new Promise(function (resolve, reject) { user.initiateAuth(authDetails, _this.authCallbacks(user, resolve, reject)); }); }; /** * This was previously used by an authenticated user to get MFAOptions, * but no longer returns a meaningful response. Refer to the documentation for * how to setup and use MFA: https://docs.amplify.aws/lib/auth/mfa/q/platform/js * @deprecated * @param {CognitoUser} user - the current user * @return - A promise resolves the current preferred mfa option if success */ AuthClass.prototype.getMFAOptions = function (user) { return new Promise(function (res, rej) { user.getMFAOptions(function (err, mfaOptions) { if (err) { logger.debug('get MFA Options failed', err); rej(err); return; } logger.debug('get MFA options success', mfaOptions); res(mfaOptions); return; }); }); }; /** * get preferred mfa method * @param {CognitoUser} user - the current cognito user * @param {GetPreferredMFAOpts} params - options for getting the current user preferred MFA */ AuthClass.prototype.getPreferredMFA = function (user, params) { var _this = this; var that = this; return new Promise(function (res, rej) { var clientMetadata = _this._config.clientMetadata; // TODO: verify behavior if this is override during signIn var bypassCache = params ? params.bypassCache : false; user.getUserData(function (err, data) { return tslib_1.__awaiter(_this, void 0, void 0, function () { var cleanUpError_1, mfaType; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: if (!err) return [3 /*break*/, 5]; logger.debug('getting preferred mfa failed', err); if (!this.isSessionInvalid(err)) return [3 /*break*/, 4]; _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); return [4 /*yield*/, this.cleanUpInvalidSession(user)]; case 2: _a.sent(); return [3 /*break*/, 4]; case 3: cleanUpError_1 = _a.sent(); rej(new Error("Session is invalid due to: " + err.message + " and failed to clean up invalid session: " + cleanUpError_1.message)); return [2 /*return*/]; case 4: rej(err); return [2 /*return*/]; case 5: mfaType = that._getMfaTypeFromUserData(data); if (!mfaType) { rej('invalid MFA Type'); return [2 /*return*/]; } else { res(mfaType); return [2 /*return*/]; } return [2 /*return*/]; } }); }); }, { bypassCache: bypassCache, clientMetadata: clientMetadata }); }); }; AuthClass.prototype._getMfaTypeFromUserData = function (data) { var ret = null; var preferredMFA = data.PreferredMfaSetting; // if the user has used Auth.setPreferredMFA() to setup the mfa type // then the "PreferredMfaSetting" would exist in the response if (preferredMFA) { ret = preferredMFA; } else { // if mfaList exists but empty, then its noMFA var mfaList = data.UserMFASettingList; if (!mfaList) { // if SMS was enabled by using Auth.enableSMS(), // the response would contain MFAOptions // as for now Cognito only supports for SMS, so we will say it is 'SMS_MFA' // if it does not exist, then it should be NOMFA var MFAOptions = data.MFAOptions; if (MFAOptions) { ret = 'SMS_MFA'; } else { ret = 'NOMFA'; } } else if (mfaList.length === 0) { ret = 'NOMFA'; } else { logger.debug('invalid case for getPreferredMFA', data); } } return ret; }; AuthClass.prototype._getUserData = function (user, params) { var _this = this; return new Promise(function (res, rej) { user.getUserData(function (err, data) { return tslib_1.__awaiter(_this, void 0, void 0, function () { var cleanUpError_2; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: if (!err) return [3 /*break*/, 5]; logger.debug('getting user data failed', err); if (!this.isSessionInvalid(err)) return [3 /*break*/, 4]; _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); return [4 /*yield*/, this.cleanUpInvalidSession(user)]; case 2: _a.sent(); return [3 /*break*/, 4]; case 3: cleanUpError_2 = _a.sent(); rej(new Error("Session is invalid due to: " + err.message + " and failed to clean up invalid session: " + cleanUpError_2.message)); return [2 /*return*/]; case 4: rej(err); return [2 /*return*/]; case 5: res(data); _a.label = 6; case 6: return [2 /*return*/]; } }); }); }, params); }); }; /** * set preferred MFA method * @param {CognitoUser} user - the current Cognito user * @param {string} mfaMethod - preferred mfa method * @return - A promise resolve if success */ AuthClass.prototype.setPreferredMFA = function (user, mfaMethod) { return tslib_1.__awaiter(this, void 0, void 0, function () { var clientMetadata, userData, smsMfaSettings, totpMfaSettings, _a, mfaList, currentMFAType, that; var _this = this; return tslib_1.__generator(this, function (_b) { switch (_b.label) { case 0: clientMetadata = this._config.clientMetadata; return [4 /*yield*/, this._getUserData(user, { bypassCache: true, clientMetadata: clientMetadata, })]; case 1: userData = _b.sent(); smsMfaSettings = null; totpMfaSettings = null; _a = mfaMethod; switch (_a) { case 'TOTP': return [3 /*break*/, 2]; case 'SOFTWARE_TOKEN_MFA': return [3 /*break*/, 2]; case 'SMS': return [3 /*break*/, 3]; case 'SMS_MFA': return [3 /*break*/, 3]; case 'NOMFA': return [3 /*break*/, 4]; } return [3 /*break*/, 6]; case 2: totpMfaSettings = { PreferredMfa: true, Enabled: true, }; return [3 /*break*/, 7]; case 3: smsMfaSettings = { PreferredMfa: true, Enabled: true, }; return [3 /*break*/, 7]; case 4: mfaList = userData['UserMFASettingList']; return [4 /*yield*/, this._getMfaTypeFromUserData(userData)]; case 5: currentMFAType = _b.sent(); if (currentMFAType === 'NOMFA') { return [2 /*return*/, Promise.resolve('No change for mfa type')]; } else if (currentMFAType === 'SMS_MFA') { smsMfaSettings = { PreferredMfa: false, Enabled: false, }; } else if (currentMFAType === 'SOFTWARE_TOKEN_MFA') { totpMfaSettings = { PreferredMfa: false, Enabled: false, }; } else { return [2 /*return*/, this.rejectAuthError(Auth_1.AuthErrorTypes.InvalidMFA)]; } // if there is a UserMFASettingList in the response // we need to disable every mfa type in that list if (mfaList && mfaList.length !== 0) { // to disable SMS or TOTP if exists in that list mfaList.forEach(function (mfaType) { if (mfaType === 'SMS_MFA') { smsMfaSettings = { PreferredMfa: false, Enabled: false, }; } else if (mfaType === 'SOFTWARE_TOKEN_MFA') { totpMfaSettings = { PreferredMfa: false, Enabled: false, }; } }); } return [3 /*break*/, 7]; case 6: logger.debug('no validmfa method provided'); return [2 /*return*/, this.rejectAuthError(Auth_1.AuthErrorTypes.NoMFA)]; case 7: that = this; return [2 /*return*/, new Promise(function (res, rej) { user.setUserMfaPreference(smsMfaSettings, totpMfaSettings, function (err, result) { if (err) { logger.debug('Set user mfa preference error', err); return rej(err); } logger.debug('Set user mfa success', result); logger.debug('Caching the latest user data into local'); // cache the latest result into user data user.getUserData(function (err, data) { return tslib_1.__awaiter(_this, void 0, void 0, function () { var cleanUpError_3; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: if (!err) return [3 /*break*/, 5]; logger.debug('getting user data failed', err); if (!this.isSessionInvalid(err)) return [3 /*break*/, 4]; _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); return [4 /*yield*/, this.cleanUpInvalidSession(user)]; case 2: _a.sent(); return [3 /*break*/, 4]; case 3: cleanUpError_3 = _a.sent(); rej(new Error("Session is invalid due to: " + err.message + " and failed to clean up invalid session: " + cleanUpError_3.message)); return [2 /*return*/]; case 4: return [2 /*return*/, rej(err)]; case 5: return [2 /*return*/, res(result)]; } }); }); }, { bypassCache: true, clientMetadata: clientMetadata, }); }); })]; } }); }); }; /** * disable SMS * @deprecated * @param {CognitoUser} user - the current user * @return - A promise resolves is success */ AuthClass.prototype.disableSMS = function (user) { return new Promise(function (res, rej) { user.disableMFA(function (err, data) { if (err) { logger.debug('disable mfa failed', err); rej(err); return; } logger.debug('disable mfa succeed', data); res(data); return; }); }); }; /** * enable SMS * @deprecated * @param {CognitoUser} user - the current user * @return - A promise resolves is success */ AuthClass.prototype.enableSMS = function (user) { return new Promise(function (res, rej) { user.enableMFA(function (err, data) { if (err) { logger.debug('enable mfa failed', err); rej(err); return; } logger.debug('enable mfa succeed', data); res(data); return; }); }); }; /** * Setup TOTP * @param {CognitoUser} user - the current user * @return - A promise resolves with the secret code if success */ AuthClass.prototype.setupTOTP = function (user) { return new Promise(function (res, rej) { user.associateSoftwareToken({ onFailure: function (err) { logger.debug('associateSoftwareToken failed', err); rej(err); return; }, associateSecretCode: function (secretCode) { logger.debug('associateSoftwareToken sucess', secretCode); res(secretCode); return; }, }); }); }; /** * verify TOTP setup * @param {CognitoUser} user - the current user * @param {string} challengeAnswer - challenge answer * @return - A promise resolves is success */ AuthClass.prototype.verifyTotpToken = function (user, challengeAnswer) { logger.debug('verification totp token', user, challengeAnswer); var signInUserSession; if (user && typeof user.getSignInUserSession === 'function') { signInUserSession = user.getSignInUserSession(); } var isLoggedIn = signInUserSession === null || signInUserSession === void 0 ? void 0 : signInUserSession.isValid(); return new Promise(function (res, rej) { user.verifySoftwareToken(challengeAnswer, 'My TOTP device', { onFailure: function (err) { logger.debug('verifyTotpToken failed', err); rej(err); return; }, onSuccess: function (data) { if (!isLoggedIn) { dispatchAuthEvent('signIn', user, "A user " + user.getUsername() + " has been signed in"); } dispatchAuthEvent('verify', user, "A user " + user.getUsername() + " has been verified"); logger.debug('verifyTotpToken success', data); res(data); return; }, }); }); }; /** * Send MFA code to confirm sign in * @param {Object} user - The CognitoUser object * @param {String} code - The confirmation code */ AuthClass.prototype.confirmSignIn = function (user, code, mfaType, clientMetadata) { var _this = this; if (clientMetadata === void 0) { clientMetadata = this._config.clientMetadata; } if (!code) { return this.rejectAuthError(Auth_1.AuthErrorTypes.EmptyCode); } var that = this; return new Promise(function (resolve, reject) { user.sendMFACode(code, { onSuccess: function (session) { return tslib_1.__awaiter(_this, void 0, void 0, function () { var cred, e_3, currentUser, e_4; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: logger.debug(session); _a.label = 1; case 1: _a.trys.push([1, 4, 5, 10]); return [4 /*yield*/, this.Credentials.clear()]; case 2: _a.sent(); return [4 /*yield*/, this.Credentials.set(session, 'session')]; case 3: cred = _a.sent(); logger.debug('succeed to get cognito credentials', cred); return [3 /*break*/, 10]; case 4: e_3 = _a.sent(); logger.debug('cannot get cognito credentials', e_3); return [3 /*break*/, 10]; case 5: that.user = user; _a.label = 6; case 6: _a.trys.push([6, 8, , 9]); return [4 /*yield*/, this.currentUserPoolUser()]; case 7: currentUser = _a.sent(); user.attributes = currentUser.attributes; return [3 /*break*/, 9]; case 8: e_4 = _a.sent(); logger.debug('cannot get updated Cognito User', e_4); return [3 /*break*/, 9]; case 9: dispatchAuthEvent('signIn', user, "A user " + user.getUsername() + " has been signed in"); resolve(user); return [7 /*endfinally*/]; case 10: return [2 /*return*/]; } }); }); }, onFailure: function (err) { logger.debug('confirm signIn failure', err); reject(err); }, }, mfaType, clientMetadata); }); }; AuthClass.prototype.completeNewPassword = function (user, password, requiredAttributes, clientMetadata) { var _this = this; if (requiredAttributes === void 0) { requiredAttributes = {}; } if (clientMetadata === void 0) { clientMetadata = this._config.clientMetadata; } if (!password) { return this.rejectAuthError(Auth_1.AuthErrorTypes.EmptyPassword); } var that = this; return new Promise(function (resolve, reject) { user.completeNewPasswordChallenge(password, requiredAttributes, { onSuccess: function (session) { return tslib_1.__awaiter(_this, void 0, void 0, function () { var cred, e_5; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: logger.debug(session); _a.label = 1; case 1: _a.trys.push([1, 4, 5, 6]); return [4 /*yield*/, this.Credentials.clear()]; case 2: _a.sent(); return [4 /*yield*/, this.Credentials.set(session, 'session')]; case 3: cred = _a.sent(); logger.debug('succeed to get cognito credentials', cred); return [3 /*break*/, 6]; case 4: e_5 = _a.sent(); logger.debug('cannot get cognito credentials', e_5); return [3 /*b