UNPKG

124 kBJavaScriptView Raw
1"use strict";
2// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3// SPDX-License-Identifier: Apache-2.0
4Object.defineProperty(exports, "__esModule", { value: true });
5var tslib_1 = require("tslib");
6var types_1 = require("./types");
7var core_1 = require("@aws-amplify/core");
8var amazon_cognito_identity_js_1 = require("amazon-cognito-identity-js");
9var url_1 = require("url");
10var OAuth_1 = tslib_1.__importDefault(require("./OAuth/OAuth"));
11var urlListener_1 = tslib_1.__importDefault(require("./urlListener"));
12var Errors_1 = require("./Errors");
13var Auth_1 = require("./types/Auth");
14var logger = new core_1.ConsoleLogger('AuthClass');
15var USER_ADMIN_SCOPE = 'aws.cognito.signin.user.admin';
16// 10 sec, following this guide https://www.nngroup.com/articles/response-times-3-important-limits/
17var OAUTH_FLOW_MS_TIMEOUT = 10 * 1000;
18var AMPLIFY_SYMBOL = (typeof Symbol !== 'undefined' && typeof Symbol.for === 'function'
19 ? Symbol.for('amplify_default')
20 : '@@amplify_default');
21var dispatchAuthEvent = function (event, data, message) {
22 core_1.Hub.dispatch('auth', { event: event, data: data, message: message }, 'Auth', AMPLIFY_SYMBOL);
23};
24// Cognito Documentation for max device
25// tslint:disable-next-line:max-line-length
26// https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ListDevices.html#API_ListDevices_RequestSyntax
27var MAX_DEVICES = 60;
28var MAX_AUTOSIGNIN_POLLING_MS = 3 * 60 * 1000;
29/**
30 * Provide authentication steps
31 */
32var AuthClass = /** @class */ (function () {
33 /**
34 * Initialize Auth with AWS configurations
35 * @param {Object} config - Configuration of the Auth
36 */
37 function AuthClass(config) {
38 var _this = this;
39 this.userPool = null;
40 this.user = null;
41 this.oAuthFlowInProgress = false;
42 this.autoSignInInitiated = false;
43 this.inflightSessionPromise = null;
44 this.inflightSessionPromiseCounter = 0;
45 this.Credentials = core_1.Credentials;
46 this.wrapRefreshSessionCallback = function (callback) {
47 var wrapped = function (error, data) {
48 if (data) {
49 dispatchAuthEvent('tokenRefresh', undefined, "New token retrieved");
50 }
51 else {
52 dispatchAuthEvent('tokenRefresh_failure', error, "Failed to retrieve new token");
53 }
54 return callback(error, data);
55 };
56 return wrapped;
57 }; // prettier-ignore
58 this.configure(config);
59 this.currentCredentials = this.currentCredentials.bind(this);
60 this.currentUserCredentials = this.currentUserCredentials.bind(this);
61 core_1.Hub.listen('auth', function (_a) {
62 var payload = _a.payload;
63 var event = payload.event;
64 switch (event) {
65 case 'verify':
66 case 'signIn':
67 _this._storage.setItem('amplify-signin-with-hostedUI', 'false');
68 break;
69 case 'signOut':
70 _this._storage.removeItem('amplify-signin-with-hostedUI');
71 break;
72 case 'cognitoHostedUI':
73 _this._storage.setItem('amplify-signin-with-hostedUI', 'true');
74 break;
75 }
76 });
77 }
78 AuthClass.prototype.getModuleName = function () {
79 return 'Auth';
80 };
81 AuthClass.prototype.configure = function (config) {
82 var _this = this;
83 if (!config)
84 return this._config || {};
85 logger.debug('configure Auth');
86 var conf = Object.assign({}, this._config, core_1.parseAWSExports(config).Auth, config);
87 this._config = conf;
88 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;
89 if (!this._config.storage) {
90 // backward compatability
91 if (cookieStorage)
92 this._storage = new amazon_cognito_identity_js_1.CookieStorage(cookieStorage);
93 else {
94 this._storage = config.ssr
95 ? new core_1.UniversalStorage()
96 : new core_1.StorageHelper().getStorage();
97 }
98 }
99 else {
100 if (!this._isValidAuthStorage(this._config.storage)) {
101 logger.error('The storage in the Auth config is not valid!');
102 throw new Error('Empty storage object');
103 }
104 this._storage = this._config.storage;
105 }
106 this._storageSync = Promise.resolve();
107 if (typeof this._storage['sync'] === 'function') {
108 this._storageSync = this._storage['sync']();
109 }
110 if (userPoolId) {
111 var userPoolData = {
112 UserPoolId: userPoolId,
113 ClientId: userPoolWebClientId,
114 endpoint: endpoint,
115 };
116 userPoolData.Storage = this._storage;
117 this.userPool = new amazon_cognito_identity_js_1.CognitoUserPool(userPoolData, this.wrapRefreshSessionCallback);
118 }
119 this.Credentials.configure({
120 mandatorySignIn: mandatorySignIn,
121 region: region,
122 userPoolId: userPoolId,
123 identityPoolId: identityPoolId,
124 refreshHandlers: refreshHandlers,
125 storage: this._storage,
126 identityPoolRegion: identityPoolRegion
127 });
128 // initialize cognitoauth client if hosted ui options provided
129 // to keep backward compatibility:
130 var cognitoHostedUIConfig = oauth
131 ? types_1.isCognitoHostedOpts(this._config.oauth)
132 ? oauth
133 : oauth.awsCognito
134 : undefined;
135 if (cognitoHostedUIConfig) {
136 var cognitoAuthParams = Object.assign({
137 cognitoClientId: userPoolWebClientId,
138 UserPoolId: userPoolId,
139 domain: cognitoHostedUIConfig['domain'],
140 scopes: cognitoHostedUIConfig['scope'],
141 redirectSignIn: cognitoHostedUIConfig['redirectSignIn'],
142 redirectSignOut: cognitoHostedUIConfig['redirectSignOut'],
143 responseType: cognitoHostedUIConfig['responseType'],
144 Storage: this._storage,
145 urlOpener: cognitoHostedUIConfig['urlOpener'],
146 clientMetadata: clientMetadata,
147 }, cognitoHostedUIConfig['options']);
148 this._oAuthHandler = new OAuth_1.default({
149 scopes: cognitoAuthParams.scopes,
150 config: cognitoAuthParams,
151 cognitoClientId: cognitoAuthParams.cognitoClientId,
152 });
153 // **NOTE** - Remove this in a future major release as it is a breaking change
154 // Prevents _handleAuthResponse from being called multiple times in Expo
155 // See https://github.com/aws-amplify/amplify-js/issues/4388
156 var usedResponseUrls_1 = {};
157 urlListener_1.default(function (_a) {
158 var url = _a.url;
159 if (usedResponseUrls_1[url]) {
160 return;
161 }
162 usedResponseUrls_1[url] = true;
163 _this._handleAuthResponse(url);
164 });
165 }
166 dispatchAuthEvent('configured', null, "The Auth category has been configured successfully");
167 if (!this.autoSignInInitiated &&
168 typeof this._storage['getItem'] === 'function') {
169 var pollingInitiated = this.isTrueStorageValue('amplify-polling-started');
170 if (pollingInitiated) {
171 dispatchAuthEvent('autoSignIn_failure', null, Auth_1.AuthErrorTypes.AutoSignInError);
172 this._storage.removeItem('amplify-auto-sign-in');
173 }
174 this._storage.removeItem('amplify-polling-started');
175 }
176 return this._config;
177 };
178 /**
179 * Sign up with username, password and other attributes like phone, email
180 * @param {String | object} params - The user attributes used for signin
181 * @param {String[]} restOfAttrs - for the backward compatability
182 * @return - A promise resolves callback data if success
183 */
184 AuthClass.prototype.signUp = function (params) {
185 var _this = this;
186 var restOfAttrs = [];
187 for (var _i = 1; _i < arguments.length; _i++) {
188 restOfAttrs[_i - 1] = arguments[_i];
189 }
190 var _a, _b, _c;
191 if (!this.userPool) {
192 return this.rejectNoUserPool();
193 }
194 var username = null;
195 var password = null;
196 var attributes = [];
197 var validationData = null;
198 var clientMetadata;
199 var autoSignIn = { enabled: false };
200 var autoSignInValidationData = {};
201 var autoSignInClientMetaData = {};
202 if (params && typeof params === 'string') {
203 username = params;
204 password = restOfAttrs ? restOfAttrs[0] : null;
205 var email = restOfAttrs ? restOfAttrs[1] : null;
206 var phone_number = restOfAttrs ? restOfAttrs[2] : null;
207 if (email)
208 attributes.push(new amazon_cognito_identity_js_1.CognitoUserAttribute({ Name: 'email', Value: email }));
209 if (phone_number)
210 attributes.push(new amazon_cognito_identity_js_1.CognitoUserAttribute({
211 Name: 'phone_number',
212 Value: phone_number,
213 }));
214 }
215 else if (params && typeof params === 'object') {
216 username = params['username'];
217 password = params['password'];
218 if (params && params.clientMetadata) {
219 clientMetadata = params.clientMetadata;
220 }
221 else if (this._config.clientMetadata) {
222 clientMetadata = this._config.clientMetadata;
223 }
224 var attrs_1 = params['attributes'];
225 if (attrs_1) {
226 Object.keys(attrs_1).map(function (key) {
227 attributes.push(new amazon_cognito_identity_js_1.CognitoUserAttribute({ Name: key, Value: attrs_1[key] }));
228 });
229 }
230 var validationDataObject_1 = params['validationData'];
231 if (validationDataObject_1) {
232 validationData = [];
233 Object.keys(validationDataObject_1).map(function (key) {
234 validationData.push(new amazon_cognito_identity_js_1.CognitoUserAttribute({
235 Name: key,
236 Value: validationDataObject_1[key],
237 }));
238 });
239 }
240 autoSignIn = (_a = params.autoSignIn) !== null && _a !== void 0 ? _a : { enabled: false };
241 if (autoSignIn.enabled) {
242 this._storage.setItem('amplify-auto-sign-in', 'true');
243 autoSignInValidationData = (_b = autoSignIn.validationData) !== null && _b !== void 0 ? _b : {};
244 autoSignInClientMetaData = (_c = autoSignIn.clientMetaData) !== null && _c !== void 0 ? _c : {};
245 }
246 }
247 else {
248 return this.rejectAuthError(Auth_1.AuthErrorTypes.SignUpError);
249 }
250 if (!username) {
251 return this.rejectAuthError(Auth_1.AuthErrorTypes.EmptyUsername);
252 }
253 if (!password) {
254 return this.rejectAuthError(Auth_1.AuthErrorTypes.EmptyPassword);
255 }
256 logger.debug('signUp attrs:', attributes);
257 logger.debug('signUp validation data:', validationData);
258 return new Promise(function (resolve, reject) {
259 _this.userPool.signUp(username, password, attributes, validationData, function (err, data) {
260 if (err) {
261 dispatchAuthEvent('signUp_failure', err, username + " failed to signup");
262 reject(err);
263 }
264 else {
265 dispatchAuthEvent('signUp', data, username + " has signed up successfully");
266 if (autoSignIn.enabled) {
267 _this.handleAutoSignIn(username, password, autoSignInValidationData, autoSignInClientMetaData, data);
268 }
269 resolve(data);
270 }
271 }, clientMetadata);
272 });
273 };
274 AuthClass.prototype.handleAutoSignIn = function (username, password, validationData, clientMetadata, data) {
275 this.autoSignInInitiated = true;
276 var authDetails = new amazon_cognito_identity_js_1.AuthenticationDetails({
277 Username: username,
278 Password: password,
279 ValidationData: validationData,
280 ClientMetadata: clientMetadata,
281 });
282 if (data.userConfirmed) {
283 this.signInAfterUserConfirmed(authDetails);
284 }
285 else if (this._config.signUpVerificationMethod === 'link') {
286 this.handleLinkAutoSignIn(authDetails);
287 }
288 else {
289 this.handleCodeAutoSignIn(authDetails);
290 }
291 };
292 AuthClass.prototype.handleCodeAutoSignIn = function (authDetails) {
293 var _this = this;
294 var listenEvent = function (_a) {
295 var payload = _a.payload;
296 if (payload.event === 'confirmSignUp') {
297 _this.signInAfterUserConfirmed(authDetails, listenEvent);
298 }
299 };
300 core_1.Hub.listen('auth', listenEvent);
301 };
302 AuthClass.prototype.handleLinkAutoSignIn = function (authDetails) {
303 var _this = this;
304 this._storage.setItem('amplify-polling-started', 'true');
305 var start = Date.now();
306 var autoSignInPollingIntervalId = setInterval(function () {
307 if (Date.now() - start > MAX_AUTOSIGNIN_POLLING_MS) {
308 clearInterval(autoSignInPollingIntervalId);
309 dispatchAuthEvent('autoSignIn_failure', null, 'Please confirm your account and use your credentials to sign in.');
310 _this._storage.removeItem('amplify-auto-sign-in');
311 }
312 else {
313 _this.signInAfterUserConfirmed(authDetails, null, autoSignInPollingIntervalId);
314 }
315 }, 5000);
316 };
317 AuthClass.prototype.signInAfterUserConfirmed = function (authDetails, listenEvent, autoSignInPollingIntervalId) {
318 return tslib_1.__awaiter(this, void 0, void 0, function () {
319 var user, error_1;
320 var _this = this;
321 return tslib_1.__generator(this, function (_a) {
322 switch (_a.label) {
323 case 0:
324 user = this.createCognitoUser(authDetails.getUsername());
325 _a.label = 1;
326 case 1:
327 _a.trys.push([1, 3, , 4]);
328 return [4 /*yield*/, user.authenticateUser(authDetails, this.authCallbacks(user, function (value) {
329 dispatchAuthEvent('autoSignIn', value, authDetails.getUsername() + " has signed in successfully");
330 if (listenEvent) {
331 core_1.Hub.remove('auth', listenEvent);
332 }
333 if (autoSignInPollingIntervalId) {
334 clearInterval(autoSignInPollingIntervalId);
335 _this._storage.removeItem('amplify-polling-started');
336 }
337 _this._storage.removeItem('amplify-auto-sign-in');
338 }, function (error) {
339 logger.error(error);
340 _this._storage.removeItem('amplify-auto-sign-in');
341 }))];
342 case 2:
343 _a.sent();
344 return [3 /*break*/, 4];
345 case 3:
346 error_1 = _a.sent();
347 logger.error(error_1);
348 return [3 /*break*/, 4];
349 case 4: return [2 /*return*/];
350 }
351 });
352 });
353 };
354 /**
355 * Send the verification code to confirm sign up
356 * @param {String} username - The username to be confirmed
357 * @param {String} code - The verification code
358 * @param {ConfirmSignUpOptions} options - other options for confirm signup
359 * @return - A promise resolves callback data if success
360 */
361 AuthClass.prototype.confirmSignUp = function (username, code, options) {
362 var _this = this;
363 if (!this.userPool) {
364 return this.rejectNoUserPool();
365 }
366 if (!username) {
367 return this.rejectAuthError(Auth_1.AuthErrorTypes.EmptyUsername);
368 }
369 if (!code) {
370 return this.rejectAuthError(Auth_1.AuthErrorTypes.EmptyCode);
371 }
372 var user = this.createCognitoUser(username);
373 var forceAliasCreation = options && typeof options.forceAliasCreation === 'boolean'
374 ? options.forceAliasCreation
375 : true;
376 var clientMetadata;
377 if (options && options.clientMetadata) {
378 clientMetadata = options.clientMetadata;
379 }
380 else if (this._config.clientMetadata) {
381 clientMetadata = this._config.clientMetadata;
382 }
383 return new Promise(function (resolve, reject) {
384 user.confirmRegistration(code, forceAliasCreation, function (err, data) {
385 if (err) {
386 reject(err);
387 }
388 else {
389 dispatchAuthEvent('confirmSignUp', data, username + " has been confirmed successfully");
390 var autoSignIn = _this.isTrueStorageValue('amplify-auto-sign-in');
391 if (autoSignIn && !_this.autoSignInInitiated) {
392 dispatchAuthEvent('autoSignIn_failure', null, Auth_1.AuthErrorTypes.AutoSignInError);
393 _this._storage.removeItem('amplify-auto-sign-in');
394 }
395 resolve(data);
396 }
397 }, clientMetadata);
398 });
399 };
400 AuthClass.prototype.isTrueStorageValue = function (value) {
401 var item = this._storage.getItem(value);
402 return item ? item === 'true' : false;
403 };
404 /**
405 * Resend the verification code
406 * @param {String} username - The username to be confirmed
407 * @param {ClientMetadata} clientMetadata - Metadata to be passed to Cognito Lambda triggers
408 * @return - A promise resolves code delivery details if successful
409 */
410 AuthClass.prototype.resendSignUp = function (username, clientMetadata) {
411 if (clientMetadata === void 0) { clientMetadata = this._config.clientMetadata; }
412 if (!this.userPool) {
413 return this.rejectNoUserPool();
414 }
415 if (!username) {
416 return this.rejectAuthError(Auth_1.AuthErrorTypes.EmptyUsername);
417 }
418 var user = this.createCognitoUser(username);
419 return new Promise(function (resolve, reject) {
420 user.resendConfirmationCode(function (err, data) {
421 if (err) {
422 reject(err);
423 }
424 else {
425 resolve(data);
426 }
427 }, clientMetadata);
428 });
429 };
430 /**
431 * Sign in
432 * @param {String | SignInOpts} usernameOrSignInOpts - The username to be signed in or the sign in options
433 * @param {String} pw - The password of the username
434 * @param {ClientMetaData} clientMetadata - Client metadata for custom workflows
435 * @return - A promise resolves the CognitoUser
436 */
437 AuthClass.prototype.signIn = function (usernameOrSignInOpts, pw, clientMetadata) {
438 if (clientMetadata === void 0) { clientMetadata = this._config.clientMetadata; }
439 if (!this.userPool) {
440 return this.rejectNoUserPool();
441 }
442 var username = null;
443 var password = null;
444 var validationData = {};
445 // for backward compatibility
446 if (typeof usernameOrSignInOpts === 'string') {
447 username = usernameOrSignInOpts;
448 password = pw;
449 }
450 else if (types_1.isUsernamePasswordOpts(usernameOrSignInOpts)) {
451 if (typeof pw !== 'undefined') {
452 logger.warn('The password should be defined under the first parameter object!');
453 }
454 username = usernameOrSignInOpts.username;
455 password = usernameOrSignInOpts.password;
456 validationData = usernameOrSignInOpts.validationData;
457 }
458 else {
459 return this.rejectAuthError(Auth_1.AuthErrorTypes.InvalidUsername);
460 }
461 if (!username) {
462 return this.rejectAuthError(Auth_1.AuthErrorTypes.EmptyUsername);
463 }
464 var authDetails = new amazon_cognito_identity_js_1.AuthenticationDetails({
465 Username: username,
466 Password: password,
467 ValidationData: validationData,
468 ClientMetadata: clientMetadata,
469 });
470 if (password) {
471 return this.signInWithPassword(authDetails);
472 }
473 else {
474 return this.signInWithoutPassword(authDetails);
475 }
476 };
477 /**
478 * Return an object with the authentication callbacks
479 * @param {CognitoUser} user - the cognito user object
480 * @param {} resolve - function called when resolving the current step
481 * @param {} reject - function called when rejecting the current step
482 * @return - an object with the callback methods for user authentication
483 */
484 AuthClass.prototype.authCallbacks = function (user, resolve, reject) {
485 var _this = this;
486 var that = this;
487 return {
488 onSuccess: function (session) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
489 var cred, e_1, currentUser, e_2;
490 return tslib_1.__generator(this, function (_a) {
491 switch (_a.label) {
492 case 0:
493 logger.debug(session);
494 delete user['challengeName'];
495 delete user['challengeParam'];
496 _a.label = 1;
497 case 1:
498 _a.trys.push([1, 4, 5, 9]);
499 return [4 /*yield*/, this.Credentials.clear()];
500 case 2:
501 _a.sent();
502 return [4 /*yield*/, this.Credentials.set(session, 'session')];
503 case 3:
504 cred = _a.sent();
505 logger.debug('succeed to get cognito credentials', cred);
506 return [3 /*break*/, 9];
507 case 4:
508 e_1 = _a.sent();
509 logger.debug('cannot get cognito credentials', e_1);
510 return [3 /*break*/, 9];
511 case 5:
512 _a.trys.push([5, 7, , 8]);
513 return [4 /*yield*/, this.currentUserPoolUser()];
514 case 6:
515 currentUser = _a.sent();
516 that.user = currentUser;
517 dispatchAuthEvent('signIn', currentUser, "A user " + user.getUsername() + " has been signed in");
518 resolve(currentUser);
519 return [3 /*break*/, 8];
520 case 7:
521 e_2 = _a.sent();
522 logger.error('Failed to get the signed in user', e_2);
523 reject(e_2);
524 return [3 /*break*/, 8];
525 case 8: return [7 /*endfinally*/];
526 case 9: return [2 /*return*/];
527 }
528 });
529 }); },
530 onFailure: function (err) {
531 logger.debug('signIn failure', err);
532 dispatchAuthEvent('signIn_failure', err, user.getUsername() + " failed to signin");
533 reject(err);
534 },
535 customChallenge: function (challengeParam) {
536 logger.debug('signIn custom challenge answer required');
537 user['challengeName'] = 'CUSTOM_CHALLENGE';
538 user['challengeParam'] = challengeParam;
539 resolve(user);
540 },
541 mfaRequired: function (challengeName, challengeParam) {
542 logger.debug('signIn MFA required');
543 user['challengeName'] = challengeName;
544 user['challengeParam'] = challengeParam;
545 resolve(user);
546 },
547 mfaSetup: function (challengeName, challengeParam) {
548 logger.debug('signIn mfa setup', challengeName);
549 user['challengeName'] = challengeName;
550 user['challengeParam'] = challengeParam;
551 resolve(user);
552 },
553 newPasswordRequired: function (userAttributes, requiredAttributes) {
554 logger.debug('signIn new password');
555 user['challengeName'] = 'NEW_PASSWORD_REQUIRED';
556 user['challengeParam'] = {
557 userAttributes: userAttributes,
558 requiredAttributes: requiredAttributes,
559 };
560 resolve(user);
561 },
562 totpRequired: function (challengeName, challengeParam) {
563 logger.debug('signIn totpRequired');
564 user['challengeName'] = challengeName;
565 user['challengeParam'] = challengeParam;
566 resolve(user);
567 },
568 selectMFAType: function (challengeName, challengeParam) {
569 logger.debug('signIn selectMFAType', challengeName);
570 user['challengeName'] = challengeName;
571 user['challengeParam'] = challengeParam;
572 resolve(user);
573 },
574 };
575 };
576 /**
577 * Sign in with a password
578 * @private
579 * @param {AuthenticationDetails} authDetails - the user sign in data
580 * @return - A promise resolves the CognitoUser object if success or mfa required
581 */
582 AuthClass.prototype.signInWithPassword = function (authDetails) {
583 var _this = this;
584 if (this.pendingSignIn) {
585 throw new Error('Pending sign-in attempt already in progress');
586 }
587 var user = this.createCognitoUser(authDetails.getUsername());
588 this.pendingSignIn = new Promise(function (resolve, reject) {
589 user.authenticateUser(authDetails, _this.authCallbacks(user, function (value) {
590 _this.pendingSignIn = null;
591 resolve(value);
592 }, function (error) {
593 _this.pendingSignIn = null;
594 reject(error);
595 }));
596 });
597 return this.pendingSignIn;
598 };
599 /**
600 * Sign in without a password
601 * @private
602 * @param {AuthenticationDetails} authDetails - the user sign in data
603 * @return - A promise resolves the CognitoUser object if success or mfa required
604 */
605 AuthClass.prototype.signInWithoutPassword = function (authDetails) {
606 var _this = this;
607 var user = this.createCognitoUser(authDetails.getUsername());
608 user.setAuthenticationFlowType('CUSTOM_AUTH');
609 return new Promise(function (resolve, reject) {
610 user.initiateAuth(authDetails, _this.authCallbacks(user, resolve, reject));
611 });
612 };
613 /**
614 * This was previously used by an authenticated user to get MFAOptions,
615 * but no longer returns a meaningful response. Refer to the documentation for
616 * how to setup and use MFA: https://docs.amplify.aws/lib/auth/mfa/q/platform/js
617 * @deprecated
618 * @param {CognitoUser} user - the current user
619 * @return - A promise resolves the current preferred mfa option if success
620 */
621 AuthClass.prototype.getMFAOptions = function (user) {
622 return new Promise(function (res, rej) {
623 user.getMFAOptions(function (err, mfaOptions) {
624 if (err) {
625 logger.debug('get MFA Options failed', err);
626 rej(err);
627 return;
628 }
629 logger.debug('get MFA options success', mfaOptions);
630 res(mfaOptions);
631 return;
632 });
633 });
634 };
635 /**
636 * get preferred mfa method
637 * @param {CognitoUser} user - the current cognito user
638 * @param {GetPreferredMFAOpts} params - options for getting the current user preferred MFA
639 */
640 AuthClass.prototype.getPreferredMFA = function (user, params) {
641 var _this = this;
642 var that = this;
643 return new Promise(function (res, rej) {
644 var clientMetadata = _this._config.clientMetadata; // TODO: verify behavior if this is override during signIn
645 var bypassCache = params ? params.bypassCache : false;
646 user.getUserData(function (err, data) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
647 var cleanUpError_1, mfaType;
648 return tslib_1.__generator(this, function (_a) {
649 switch (_a.label) {
650 case 0:
651 if (!err) return [3 /*break*/, 5];
652 logger.debug('getting preferred mfa failed', err);
653 if (!this.isSessionInvalid(err)) return [3 /*break*/, 4];
654 _a.label = 1;
655 case 1:
656 _a.trys.push([1, 3, , 4]);
657 return [4 /*yield*/, this.cleanUpInvalidSession(user)];
658 case 2:
659 _a.sent();
660 return [3 /*break*/, 4];
661 case 3:
662 cleanUpError_1 = _a.sent();
663 rej(new Error("Session is invalid due to: " + err.message + " and failed to clean up invalid session: " + cleanUpError_1.message));
664 return [2 /*return*/];
665 case 4:
666 rej(err);
667 return [2 /*return*/];
668 case 5:
669 mfaType = that._getMfaTypeFromUserData(data);
670 if (!mfaType) {
671 rej('invalid MFA Type');
672 return [2 /*return*/];
673 }
674 else {
675 res(mfaType);
676 return [2 /*return*/];
677 }
678 return [2 /*return*/];
679 }
680 });
681 }); }, { bypassCache: bypassCache, clientMetadata: clientMetadata });
682 });
683 };
684 AuthClass.prototype._getMfaTypeFromUserData = function (data) {
685 var ret = null;
686 var preferredMFA = data.PreferredMfaSetting;
687 // if the user has used Auth.setPreferredMFA() to setup the mfa type
688 // then the "PreferredMfaSetting" would exist in the response
689 if (preferredMFA) {
690 ret = preferredMFA;
691 }
692 else {
693 // if mfaList exists but empty, then its noMFA
694 var mfaList = data.UserMFASettingList;
695 if (!mfaList) {
696 // if SMS was enabled by using Auth.enableSMS(),
697 // the response would contain MFAOptions
698 // as for now Cognito only supports for SMS, so we will say it is 'SMS_MFA'
699 // if it does not exist, then it should be NOMFA
700 var MFAOptions = data.MFAOptions;
701 if (MFAOptions) {
702 ret = 'SMS_MFA';
703 }
704 else {
705 ret = 'NOMFA';
706 }
707 }
708 else if (mfaList.length === 0) {
709 ret = 'NOMFA';
710 }
711 else {
712 logger.debug('invalid case for getPreferredMFA', data);
713 }
714 }
715 return ret;
716 };
717 AuthClass.prototype._getUserData = function (user, params) {
718 var _this = this;
719 return new Promise(function (res, rej) {
720 user.getUserData(function (err, data) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
721 var cleanUpError_2;
722 return tslib_1.__generator(this, function (_a) {
723 switch (_a.label) {
724 case 0:
725 if (!err) return [3 /*break*/, 5];
726 logger.debug('getting user data failed', err);
727 if (!this.isSessionInvalid(err)) return [3 /*break*/, 4];
728 _a.label = 1;
729 case 1:
730 _a.trys.push([1, 3, , 4]);
731 return [4 /*yield*/, this.cleanUpInvalidSession(user)];
732 case 2:
733 _a.sent();
734 return [3 /*break*/, 4];
735 case 3:
736 cleanUpError_2 = _a.sent();
737 rej(new Error("Session is invalid due to: " + err.message + " and failed to clean up invalid session: " + cleanUpError_2.message));
738 return [2 /*return*/];
739 case 4:
740 rej(err);
741 return [2 /*return*/];
742 case 5:
743 res(data);
744 _a.label = 6;
745 case 6: return [2 /*return*/];
746 }
747 });
748 }); }, params);
749 });
750 };
751 /**
752 * set preferred MFA method
753 * @param {CognitoUser} user - the current Cognito user
754 * @param {string} mfaMethod - preferred mfa method
755 * @return - A promise resolve if success
756 */
757 AuthClass.prototype.setPreferredMFA = function (user, mfaMethod) {
758 return tslib_1.__awaiter(this, void 0, void 0, function () {
759 var clientMetadata, userData, smsMfaSettings, totpMfaSettings, _a, mfaList, currentMFAType, that;
760 var _this = this;
761 return tslib_1.__generator(this, function (_b) {
762 switch (_b.label) {
763 case 0:
764 clientMetadata = this._config.clientMetadata;
765 return [4 /*yield*/, this._getUserData(user, {
766 bypassCache: true,
767 clientMetadata: clientMetadata,
768 })];
769 case 1:
770 userData = _b.sent();
771 smsMfaSettings = null;
772 totpMfaSettings = null;
773 _a = mfaMethod;
774 switch (_a) {
775 case 'TOTP': return [3 /*break*/, 2];
776 case 'SOFTWARE_TOKEN_MFA': return [3 /*break*/, 2];
777 case 'SMS': return [3 /*break*/, 3];
778 case 'SMS_MFA': return [3 /*break*/, 3];
779 case 'NOMFA': return [3 /*break*/, 4];
780 }
781 return [3 /*break*/, 6];
782 case 2:
783 totpMfaSettings = {
784 PreferredMfa: true,
785 Enabled: true,
786 };
787 return [3 /*break*/, 7];
788 case 3:
789 smsMfaSettings = {
790 PreferredMfa: true,
791 Enabled: true,
792 };
793 return [3 /*break*/, 7];
794 case 4:
795 mfaList = userData['UserMFASettingList'];
796 return [4 /*yield*/, this._getMfaTypeFromUserData(userData)];
797 case 5:
798 currentMFAType = _b.sent();
799 if (currentMFAType === 'NOMFA') {
800 return [2 /*return*/, Promise.resolve('No change for mfa type')];
801 }
802 else if (currentMFAType === 'SMS_MFA') {
803 smsMfaSettings = {
804 PreferredMfa: false,
805 Enabled: false,
806 };
807 }
808 else if (currentMFAType === 'SOFTWARE_TOKEN_MFA') {
809 totpMfaSettings = {
810 PreferredMfa: false,
811 Enabled: false,
812 };
813 }
814 else {
815 return [2 /*return*/, this.rejectAuthError(Auth_1.AuthErrorTypes.InvalidMFA)];
816 }
817 // if there is a UserMFASettingList in the response
818 // we need to disable every mfa type in that list
819 if (mfaList && mfaList.length !== 0) {
820 // to disable SMS or TOTP if exists in that list
821 mfaList.forEach(function (mfaType) {
822 if (mfaType === 'SMS_MFA') {
823 smsMfaSettings = {
824 PreferredMfa: false,
825 Enabled: false,
826 };
827 }
828 else if (mfaType === 'SOFTWARE_TOKEN_MFA') {
829 totpMfaSettings = {
830 PreferredMfa: false,
831 Enabled: false,
832 };
833 }
834 });
835 }
836 return [3 /*break*/, 7];
837 case 6:
838 logger.debug('no validmfa method provided');
839 return [2 /*return*/, this.rejectAuthError(Auth_1.AuthErrorTypes.NoMFA)];
840 case 7:
841 that = this;
842 return [2 /*return*/, new Promise(function (res, rej) {
843 user.setUserMfaPreference(smsMfaSettings, totpMfaSettings, function (err, result) {
844 if (err) {
845 logger.debug('Set user mfa preference error', err);
846 return rej(err);
847 }
848 logger.debug('Set user mfa success', result);
849 logger.debug('Caching the latest user data into local');
850 // cache the latest result into user data
851 user.getUserData(function (err, data) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
852 var cleanUpError_3;
853 return tslib_1.__generator(this, function (_a) {
854 switch (_a.label) {
855 case 0:
856 if (!err) return [3 /*break*/, 5];
857 logger.debug('getting user data failed', err);
858 if (!this.isSessionInvalid(err)) return [3 /*break*/, 4];
859 _a.label = 1;
860 case 1:
861 _a.trys.push([1, 3, , 4]);
862 return [4 /*yield*/, this.cleanUpInvalidSession(user)];
863 case 2:
864 _a.sent();
865 return [3 /*break*/, 4];
866 case 3:
867 cleanUpError_3 = _a.sent();
868 rej(new Error("Session is invalid due to: " + err.message + " and failed to clean up invalid session: " + cleanUpError_3.message));
869 return [2 /*return*/];
870 case 4: return [2 /*return*/, rej(err)];
871 case 5: return [2 /*return*/, res(result)];
872 }
873 });
874 }); }, {
875 bypassCache: true,
876 clientMetadata: clientMetadata,
877 });
878 });
879 })];
880 }
881 });
882 });
883 };
884 /**
885 * disable SMS
886 * @deprecated
887 * @param {CognitoUser} user - the current user
888 * @return - A promise resolves is success
889 */
890 AuthClass.prototype.disableSMS = function (user) {
891 return new Promise(function (res, rej) {
892 user.disableMFA(function (err, data) {
893 if (err) {
894 logger.debug('disable mfa failed', err);
895 rej(err);
896 return;
897 }
898 logger.debug('disable mfa succeed', data);
899 res(data);
900 return;
901 });
902 });
903 };
904 /**
905 * enable SMS
906 * @deprecated
907 * @param {CognitoUser} user - the current user
908 * @return - A promise resolves is success
909 */
910 AuthClass.prototype.enableSMS = function (user) {
911 return new Promise(function (res, rej) {
912 user.enableMFA(function (err, data) {
913 if (err) {
914 logger.debug('enable mfa failed', err);
915 rej(err);
916 return;
917 }
918 logger.debug('enable mfa succeed', data);
919 res(data);
920 return;
921 });
922 });
923 };
924 /**
925 * Setup TOTP
926 * @param {CognitoUser} user - the current user
927 * @return - A promise resolves with the secret code if success
928 */
929 AuthClass.prototype.setupTOTP = function (user) {
930 return new Promise(function (res, rej) {
931 user.associateSoftwareToken({
932 onFailure: function (err) {
933 logger.debug('associateSoftwareToken failed', err);
934 rej(err);
935 return;
936 },
937 associateSecretCode: function (secretCode) {
938 logger.debug('associateSoftwareToken sucess', secretCode);
939 res(secretCode);
940 return;
941 },
942 });
943 });
944 };
945 /**
946 * verify TOTP setup
947 * @param {CognitoUser} user - the current user
948 * @param {string} challengeAnswer - challenge answer
949 * @return - A promise resolves is success
950 */
951 AuthClass.prototype.verifyTotpToken = function (user, challengeAnswer) {
952 logger.debug('verification totp token', user, challengeAnswer);
953 return new Promise(function (res, rej) {
954 user.verifySoftwareToken(challengeAnswer, 'My TOTP device', {
955 onFailure: function (err) {
956 logger.debug('verifyTotpToken failed', err);
957 rej(err);
958 return;
959 },
960 onSuccess: function (data) {
961 dispatchAuthEvent('signIn', user, "A user " + user.getUsername() + " has been signed in");
962 dispatchAuthEvent('verify', user, "A user " + user.getUsername() + " has been verified");
963 logger.debug('verifyTotpToken success', data);
964 res(data);
965 return;
966 },
967 });
968 });
969 };
970 /**
971 * Send MFA code to confirm sign in
972 * @param {Object} user - The CognitoUser object
973 * @param {String} code - The confirmation code
974 */
975 AuthClass.prototype.confirmSignIn = function (user, code, mfaType, clientMetadata) {
976 var _this = this;
977 if (clientMetadata === void 0) { clientMetadata = this._config.clientMetadata; }
978 if (!code) {
979 return this.rejectAuthError(Auth_1.AuthErrorTypes.EmptyCode);
980 }
981 var that = this;
982 return new Promise(function (resolve, reject) {
983 user.sendMFACode(code, {
984 onSuccess: function (session) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
985 var cred, e_3;
986 return tslib_1.__generator(this, function (_a) {
987 switch (_a.label) {
988 case 0:
989 logger.debug(session);
990 _a.label = 1;
991 case 1:
992 _a.trys.push([1, 4, 5, 6]);
993 return [4 /*yield*/, this.Credentials.clear()];
994 case 2:
995 _a.sent();
996 return [4 /*yield*/, this.Credentials.set(session, 'session')];
997 case 3:
998 cred = _a.sent();
999 logger.debug('succeed to get cognito credentials', cred);
1000 return [3 /*break*/, 6];
1001 case 4:
1002 e_3 = _a.sent();
1003 logger.debug('cannot get cognito credentials', e_3);
1004 return [3 /*break*/, 6];
1005 case 5:
1006 that.user = user;
1007 dispatchAuthEvent('signIn', user, "A user " + user.getUsername() + " has been signed in");
1008 resolve(user);
1009 return [7 /*endfinally*/];
1010 case 6: return [2 /*return*/];
1011 }
1012 });
1013 }); },
1014 onFailure: function (err) {
1015 logger.debug('confirm signIn failure', err);
1016 reject(err);
1017 },
1018 }, mfaType, clientMetadata);
1019 });
1020 };
1021 AuthClass.prototype.completeNewPassword = function (user, password, requiredAttributes, clientMetadata) {
1022 var _this = this;
1023 if (requiredAttributes === void 0) { requiredAttributes = {}; }
1024 if (clientMetadata === void 0) { clientMetadata = this._config.clientMetadata; }
1025 if (!password) {
1026 return this.rejectAuthError(Auth_1.AuthErrorTypes.EmptyPassword);
1027 }
1028 var that = this;
1029 return new Promise(function (resolve, reject) {
1030 user.completeNewPasswordChallenge(password, requiredAttributes, {
1031 onSuccess: function (session) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
1032 var cred, e_4;
1033 return tslib_1.__generator(this, function (_a) {
1034 switch (_a.label) {
1035 case 0:
1036 logger.debug(session);
1037 _a.label = 1;
1038 case 1:
1039 _a.trys.push([1, 4, 5, 6]);
1040 return [4 /*yield*/, this.Credentials.clear()];
1041 case 2:
1042 _a.sent();
1043 return [4 /*yield*/, this.Credentials.set(session, 'session')];
1044 case 3:
1045 cred = _a.sent();
1046 logger.debug('succeed to get cognito credentials', cred);
1047 return [3 /*break*/, 6];
1048 case 4:
1049 e_4 = _a.sent();
1050 logger.debug('cannot get cognito credentials', e_4);
1051 return [3 /*break*/, 6];
1052 case 5:
1053 that.user = user;
1054 dispatchAuthEvent('signIn', user, "A user " + user.getUsername() + " has been signed in");
1055 resolve(user);
1056 return [7 /*endfinally*/];
1057 case 6: return [2 /*return*/];
1058 }
1059 });
1060 }); },
1061 onFailure: function (err) {
1062 logger.debug('completeNewPassword failure', err);
1063 dispatchAuthEvent('completeNewPassword_failure', err, _this.user + " failed to complete the new password flow");
1064 reject(err);
1065 },
1066 mfaRequired: function (challengeName, challengeParam) {
1067 logger.debug('signIn MFA required');
1068 user['challengeName'] = challengeName;
1069 user['challengeParam'] = challengeParam;
1070 resolve(user);
1071 },
1072 mfaSetup: function (challengeName, challengeParam) {
1073 logger.debug('signIn mfa setup', challengeName);
1074 user['challengeName'] = challengeName;
1075 user['challengeParam'] = challengeParam;
1076 resolve(user);
1077 },
1078 totpRequired: function (challengeName, challengeParam) {
1079 logger.debug('signIn mfa setup', challengeName);
1080 user['challengeName'] = challengeName;
1081 user['challengeParam'] = challengeParam;
1082 resolve(user);
1083 },
1084 }, clientMetadata);
1085 });
1086 };
1087 /**
1088 * Send the answer to a custom challenge
1089 * @param {CognitoUser} user - The CognitoUser object
1090 * @param {String} challengeResponses - The confirmation code
1091 */
1092 AuthClass.prototype.sendCustomChallengeAnswer = function (user, challengeResponses, clientMetadata) {
1093 var _this = this;
1094 if (clientMetadata === void 0) { clientMetadata = this._config.clientMetadata; }
1095 if (!this.userPool) {
1096 return this.rejectNoUserPool();
1097 }
1098 if (!challengeResponses) {
1099 return this.rejectAuthError(Auth_1.AuthErrorTypes.EmptyChallengeResponse);
1100 }
1101 var that = this;
1102 return new Promise(function (resolve, reject) {
1103 user.sendCustomChallengeAnswer(challengeResponses, _this.authCallbacks(user, resolve, reject), clientMetadata);
1104 });
1105 };
1106 /**
1107 * Delete an authenticated users' attributes
1108 * @param {CognitoUser} - The currently logged in user object
1109 * @return {Promise}
1110 **/
1111 AuthClass.prototype.deleteUserAttributes = function (user, attributeNames) {
1112 var that = this;
1113 return new Promise(function (resolve, reject) {
1114 that.userSession(user).then(function (session) {
1115 user.deleteAttributes(attributeNames, function (err, result) {
1116 if (err) {
1117 return reject(err);
1118 }
1119 else {
1120 return resolve(result);
1121 }
1122 });
1123 });
1124 });
1125 };
1126 /**
1127 * Delete the current authenticated user
1128 * @return {Promise}
1129 **/
1130 // TODO: Check return type void
1131 AuthClass.prototype.deleteUser = function () {
1132 return tslib_1.__awaiter(this, void 0, void 0, function () {
1133 var e_5, isSignedInHostedUI;
1134 var _this = this;
1135 return tslib_1.__generator(this, function (_a) {
1136 switch (_a.label) {
1137 case 0:
1138 _a.trys.push([0, 2, , 3]);
1139 return [4 /*yield*/, this._storageSync];
1140 case 1:
1141 _a.sent();
1142 return [3 /*break*/, 3];
1143 case 2:
1144 e_5 = _a.sent();
1145 logger.debug('Failed to sync cache info into memory', e_5);
1146 throw new Error(e_5);
1147 case 3:
1148 isSignedInHostedUI = this._oAuthHandler &&
1149 this._storage.getItem('amplify-signin-with-hostedUI') === 'true';
1150 return [2 /*return*/, new Promise(function (res, rej) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
1151 var user_1;
1152 var _this = this;
1153 return tslib_1.__generator(this, function (_a) {
1154 if (this.userPool) {
1155 user_1 = this.userPool.getCurrentUser();
1156 if (!user_1) {
1157 logger.debug('Failed to get user from user pool');
1158 return [2 /*return*/, rej(new Error('No current user.'))];
1159 }
1160 else {
1161 user_1.getSession(function (err, session) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
1162 var cleanUpError_4;
1163 var _this = this;
1164 return tslib_1.__generator(this, function (_a) {
1165 switch (_a.label) {
1166 case 0:
1167 if (!err) return [3 /*break*/, 5];
1168 logger.debug('Failed to get the user session', err);
1169 if (!this.isSessionInvalid(err)) return [3 /*break*/, 4];
1170 _a.label = 1;
1171 case 1:
1172 _a.trys.push([1, 3, , 4]);
1173 return [4 /*yield*/, this.cleanUpInvalidSession(user_1)];
1174 case 2:
1175 _a.sent();
1176 return [3 /*break*/, 4];
1177 case 3:
1178 cleanUpError_4 = _a.sent();
1179 rej(new Error("Session is invalid due to: " + err.message + " and failed to clean up invalid session: " + cleanUpError_4.message));
1180 return [2 /*return*/];
1181 case 4: return [2 /*return*/, rej(err)];
1182 case 5:
1183 user_1.deleteUser(function (err, result) {
1184 if (err) {
1185 rej(err);
1186 }
1187 else {
1188 dispatchAuthEvent('userDeleted', result, 'The authenticated user has been deleted.');
1189 user_1.signOut();
1190 _this.user = null;
1191 try {
1192 _this.cleanCachedItems(); // clean aws credentials
1193 }
1194 catch (e) {
1195 // TODO: change to rejects in refactor
1196 logger.debug('failed to clear cached items');
1197 }
1198 if (isSignedInHostedUI) {
1199 _this.oAuthSignOutRedirect(res, rej);
1200 }
1201 else {
1202 dispatchAuthEvent('signOut', _this.user, "A user has been signed out");
1203 res(result);
1204 }
1205 }
1206 });
1207 _a.label = 6;
1208 case 6: return [2 /*return*/];
1209 }
1210 });
1211 }); });
1212 }
1213 }
1214 else {
1215 logger.debug('no Congito User pool');
1216 rej(new Error('Cognito User pool does not exist'));
1217 }
1218 return [2 /*return*/];
1219 });
1220 }); })];
1221 }
1222 });
1223 });
1224 };
1225 /**
1226 * Update an authenticated users' attributes
1227 * @param {CognitoUser} - The currently logged in user object
1228 * @return {Promise}
1229 **/
1230 AuthClass.prototype.updateUserAttributes = function (user, attributes, clientMetadata) {
1231 var _this = this;
1232 if (clientMetadata === void 0) { clientMetadata = this._config.clientMetadata; }
1233 var attributeList = [];
1234 var that = this;
1235 return new Promise(function (resolve, reject) {
1236 that.userSession(user).then(function (session) {
1237 for (var key in attributes) {
1238 if (key !== 'sub' && key.indexOf('_verified') < 0) {
1239 var attr = {
1240 Name: key,
1241 Value: attributes[key],
1242 };
1243 attributeList.push(attr);
1244 }
1245 }
1246 user.updateAttributes(attributeList, function (err, result, details) {
1247 if (err) {
1248 dispatchAuthEvent('updateUserAttributes_failure', err, 'Failed to update attributes');
1249 return reject(err);
1250 }
1251 else {
1252 var attrs = _this.createUpdateAttributesResultList(attributes, details === null || details === void 0 ? void 0 : details.CodeDeliveryDetailsList);
1253 dispatchAuthEvent('updateUserAttributes', attrs, 'Attributes successfully updated');
1254 return resolve(result);
1255 }
1256 }, clientMetadata);
1257 });
1258 });
1259 };
1260 AuthClass.prototype.createUpdateAttributesResultList = function (attributes, codeDeliveryDetailsList) {
1261 var attrs = {};
1262 Object.keys(attributes).forEach(function (key) {
1263 attrs[key] = {
1264 isUpdated: true
1265 };
1266 var codeDeliveryDetails = codeDeliveryDetailsList === null || codeDeliveryDetailsList === void 0 ? void 0 : codeDeliveryDetailsList.find(function (value) { return value.AttributeName === key; });
1267 if (codeDeliveryDetails) {
1268 attrs[key].isUpdated = false;
1269 attrs[key].codeDeliveryDetails = codeDeliveryDetails;
1270 }
1271 });
1272 return attrs;
1273 };
1274 /**
1275 * Return user attributes
1276 * @param {Object} user - The CognitoUser object
1277 * @return - A promise resolves to user attributes if success
1278 */
1279 AuthClass.prototype.userAttributes = function (user) {
1280 var _this = this;
1281 return new Promise(function (resolve, reject) {
1282 _this.userSession(user).then(function (session) {
1283 user.getUserAttributes(function (err, attributes) {
1284 if (err) {
1285 reject(err);
1286 }
1287 else {
1288 resolve(attributes);
1289 }
1290 });
1291 });
1292 });
1293 };
1294 AuthClass.prototype.verifiedContact = function (user) {
1295 var that = this;
1296 return this.userAttributes(user).then(function (attributes) {
1297 var attrs = that.attributesToObject(attributes);
1298 var unverified = {};
1299 var verified = {};
1300 if (attrs['email']) {
1301 if (attrs['email_verified']) {
1302 verified['email'] = attrs['email'];
1303 }
1304 else {
1305 unverified['email'] = attrs['email'];
1306 }
1307 }
1308 if (attrs['phone_number']) {
1309 if (attrs['phone_number_verified']) {
1310 verified['phone_number'] = attrs['phone_number'];
1311 }
1312 else {
1313 unverified['phone_number'] = attrs['phone_number'];
1314 }
1315 }
1316 return {
1317 verified: verified,
1318 unverified: unverified,
1319 };
1320 });
1321 };
1322 AuthClass.prototype.isErrorWithMessage = function (err) {
1323 return (typeof err === 'object' &&
1324 Object.prototype.hasOwnProperty.call(err, 'message'));
1325 };
1326 // Session revoked by another app
1327 AuthClass.prototype.isTokenRevokedError = function (err) {
1328 return (this.isErrorWithMessage(err) &&
1329 err.message === 'Access Token has been revoked');
1330 };
1331 AuthClass.prototype.isRefreshTokenRevokedError = function (err) {
1332 return (this.isErrorWithMessage(err) &&
1333 err.message === 'Refresh Token has been revoked');
1334 };
1335 AuthClass.prototype.isUserDisabledError = function (err) {
1336 return this.isErrorWithMessage(err) && err.message === 'User is disabled.';
1337 };
1338 AuthClass.prototype.isUserDoesNotExistError = function (err) {
1339 return (this.isErrorWithMessage(err) && err.message === 'User does not exist.');
1340 };
1341 AuthClass.prototype.isRefreshTokenExpiredError = function (err) {
1342 return (this.isErrorWithMessage(err) &&
1343 err.message === 'Refresh Token has expired');
1344 };
1345 AuthClass.prototype.isSignedInHostedUI = function () {
1346 return (this._oAuthHandler &&
1347 this._storage.getItem('amplify-signin-with-hostedUI') === 'true');
1348 };
1349 AuthClass.prototype.isSessionInvalid = function (err) {
1350 return (this.isUserDisabledError(err) ||
1351 this.isUserDoesNotExistError(err) ||
1352 this.isTokenRevokedError(err) ||
1353 this.isRefreshTokenRevokedError(err) ||
1354 this.isRefreshTokenExpiredError(err));
1355 };
1356 AuthClass.prototype.cleanUpInvalidSession = function (user) {
1357 return tslib_1.__awaiter(this, void 0, void 0, function () {
1358 var e_6;
1359 var _this = this;
1360 return tslib_1.__generator(this, function (_a) {
1361 switch (_a.label) {
1362 case 0:
1363 user.signOut();
1364 this.user = null;
1365 _a.label = 1;
1366 case 1:
1367 _a.trys.push([1, 3, , 4]);
1368 return [4 /*yield*/, this.cleanCachedItems()];
1369 case 2:
1370 _a.sent(); // clean aws credentials
1371 return [3 /*break*/, 4];
1372 case 3:
1373 e_6 = _a.sent();
1374 logger.debug('failed to clear cached items');
1375 return [3 /*break*/, 4];
1376 case 4:
1377 if (this.isSignedInHostedUI()) {
1378 return [2 /*return*/, new Promise(function (res, rej) {
1379 _this.oAuthSignOutRedirect(res, rej);
1380 })];
1381 }
1382 else {
1383 dispatchAuthEvent('signOut', this.user, "A user has been signed out");
1384 }
1385 return [2 /*return*/];
1386 }
1387 });
1388 });
1389 };
1390 /**
1391 * Get current authenticated user
1392 * @return - A promise resolves to current authenticated CognitoUser if success
1393 */
1394 AuthClass.prototype.currentUserPoolUser = function (params) {
1395 var _this = this;
1396 if (!this.userPool) {
1397 return this.rejectNoUserPool();
1398 }
1399 return new Promise(function (res, rej) {
1400 _this._storageSync
1401 .then(function () { return tslib_1.__awaiter(_this, void 0, void 0, function () {
1402 var user, session, bypassCache, clientMetadata, _a, scope, err_1;
1403 var _this = this;
1404 return tslib_1.__generator(this, function (_b) {
1405 switch (_b.label) {
1406 case 0:
1407 if (!this.isOAuthInProgress()) return [3 /*break*/, 2];
1408 logger.debug('OAuth signIn in progress, waiting for resolution...');
1409 return [4 /*yield*/, new Promise(function (res) {
1410 var timeoutId = setTimeout(function () {
1411 logger.debug('OAuth signIn in progress timeout');
1412 core_1.Hub.remove('auth', hostedUISignCallback);
1413 res();
1414 }, OAUTH_FLOW_MS_TIMEOUT);
1415 core_1.Hub.listen('auth', hostedUISignCallback);
1416 function hostedUISignCallback(_a) {
1417 var payload = _a.payload;
1418 var event = payload.event;
1419 if (event === 'cognitoHostedUI' ||
1420 event === 'cognitoHostedUI_failure') {
1421 logger.debug("OAuth signIn resolved: " + event);
1422 clearTimeout(timeoutId);
1423 core_1.Hub.remove('auth', hostedUISignCallback);
1424 res();
1425 }
1426 }
1427 })];
1428 case 1:
1429 _b.sent();
1430 _b.label = 2;
1431 case 2:
1432 user = this.userPool.getCurrentUser();
1433 if (!user) {
1434 logger.debug('Failed to get user from user pool');
1435 rej('No current user');
1436 return [2 /*return*/];
1437 }
1438 _b.label = 3;
1439 case 3:
1440 _b.trys.push([3, 7, , 8]);
1441 return [4 /*yield*/, this._userSession(user)];
1442 case 4:
1443 session = _b.sent();
1444 bypassCache = params ? params.bypassCache : false;
1445 if (!bypassCache) return [3 /*break*/, 6];
1446 return [4 /*yield*/, this.Credentials.clear()];
1447 case 5:
1448 _b.sent();
1449 _b.label = 6;
1450 case 6:
1451 clientMetadata = this._config.clientMetadata;
1452 _a = session.getAccessToken().decodePayload().scope, scope = _a === void 0 ? '' : _a;
1453 if (scope.split(' ').includes(USER_ADMIN_SCOPE)) {
1454 user.getUserData(function (err, data) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
1455 var cleanUpError_5, preferredMFA, attributeList, i, attribute, userAttribute, attributes;
1456 return tslib_1.__generator(this, function (_a) {
1457 switch (_a.label) {
1458 case 0:
1459 if (!err) return [3 /*break*/, 7];
1460 logger.debug('getting user data failed', err);
1461 if (!this.isSessionInvalid(err)) return [3 /*break*/, 5];
1462 _a.label = 1;
1463 case 1:
1464 _a.trys.push([1, 3, , 4]);
1465 return [4 /*yield*/, this.cleanUpInvalidSession(user)];
1466 case 2:
1467 _a.sent();
1468 return [3 /*break*/, 4];
1469 case 3:
1470 cleanUpError_5 = _a.sent();
1471 rej(new Error("Session is invalid due to: " + err.message + " and failed to clean up invalid session: " + cleanUpError_5.message));
1472 return [2 /*return*/];
1473 case 4:
1474 rej(err);
1475 return [3 /*break*/, 6];
1476 case 5:
1477 res(user);
1478 _a.label = 6;
1479 case 6: return [2 /*return*/];
1480 case 7:
1481 preferredMFA = data.PreferredMfaSetting || 'NOMFA';
1482 attributeList = [];
1483 for (i = 0; i < data.UserAttributes.length; i++) {
1484 attribute = {
1485 Name: data.UserAttributes[i].Name,
1486 Value: data.UserAttributes[i].Value,
1487 };
1488 userAttribute = new amazon_cognito_identity_js_1.CognitoUserAttribute(attribute);
1489 attributeList.push(userAttribute);
1490 }
1491 attributes = this.attributesToObject(attributeList);
1492 Object.assign(user, { attributes: attributes, preferredMFA: preferredMFA });
1493 return [2 /*return*/, res(user)];
1494 }
1495 });
1496 }); }, { bypassCache: bypassCache, clientMetadata: clientMetadata });
1497 }
1498 else {
1499 logger.debug("Unable to get the user data because the " + USER_ADMIN_SCOPE + " " +
1500 "is not in the scopes of the access token");
1501 return [2 /*return*/, res(user)];
1502 }
1503 return [3 /*break*/, 8];
1504 case 7:
1505 err_1 = _b.sent();
1506 rej(err_1);
1507 return [3 /*break*/, 8];
1508 case 8: return [2 /*return*/];
1509 }
1510 });
1511 }); })
1512 .catch(function (e) {
1513 logger.debug('Failed to sync cache info into memory', e);
1514 return rej(e);
1515 });
1516 });
1517 };
1518 AuthClass.prototype.isOAuthInProgress = function () {
1519 return this.oAuthFlowInProgress;
1520 };
1521 /**
1522 * Get current authenticated user
1523 * @param {CurrentUserOpts} - options for getting the current user
1524 * @return - A promise resolves to current authenticated CognitoUser if success
1525 */
1526 AuthClass.prototype.currentAuthenticatedUser = function (params) {
1527 return tslib_1.__awaiter(this, void 0, void 0, function () {
1528 var federatedUser, e_7, federatedInfo, user, e_8;
1529 return tslib_1.__generator(this, function (_a) {
1530 switch (_a.label) {
1531 case 0:
1532 logger.debug('getting current authenticated user');
1533 federatedUser = null;
1534 _a.label = 1;
1535 case 1:
1536 _a.trys.push([1, 3, , 4]);
1537 return [4 /*yield*/, this._storageSync];
1538 case 2:
1539 _a.sent();
1540 return [3 /*break*/, 4];
1541 case 3:
1542 e_7 = _a.sent();
1543 logger.debug('Failed to sync cache info into memory', e_7);
1544 throw e_7;
1545 case 4:
1546 try {
1547 federatedInfo = JSON.parse(this._storage.getItem('aws-amplify-federatedInfo'));
1548 if (federatedInfo) {
1549 federatedUser = tslib_1.__assign(tslib_1.__assign({}, federatedInfo.user), { token: federatedInfo.token });
1550 }
1551 }
1552 catch (e) {
1553 logger.debug('cannot load federated user from auth storage');
1554 }
1555 if (!federatedUser) return [3 /*break*/, 5];
1556 this.user = federatedUser;
1557 logger.debug('get current authenticated federated user', this.user);
1558 return [2 /*return*/, this.user];
1559 case 5:
1560 logger.debug('get current authenticated userpool user');
1561 user = null;
1562 _a.label = 6;
1563 case 6:
1564 _a.trys.push([6, 8, , 9]);
1565 return [4 /*yield*/, this.currentUserPoolUser(params)];
1566 case 7:
1567 user = _a.sent();
1568 return [3 /*break*/, 9];
1569 case 8:
1570 e_8 = _a.sent();
1571 if (e_8 === 'No userPool') {
1572 logger.error('Cannot get the current user because the user pool is missing. ' +
1573 'Please make sure the Auth module is configured with a valid Cognito User Pool ID');
1574 }
1575 logger.debug('The user is not authenticated by the error', e_8);
1576 return [2 /*return*/, Promise.reject('The user is not authenticated')];
1577 case 9:
1578 this.user = user;
1579 return [2 /*return*/, this.user];
1580 }
1581 });
1582 });
1583 };
1584 /**
1585 * Get current user's session
1586 * @return - A promise resolves to session object if success
1587 */
1588 AuthClass.prototype.currentSession = function () {
1589 var that = this;
1590 logger.debug('Getting current session');
1591 // Purposely not calling the reject method here because we don't need a console error
1592 if (!this.userPool) {
1593 return Promise.reject(new Error('No User Pool in the configuration.'));
1594 }
1595 return new Promise(function (res, rej) {
1596 that
1597 .currentUserPoolUser()
1598 .then(function (user) {
1599 that
1600 .userSession(user)
1601 .then(function (session) {
1602 res(session);
1603 return;
1604 })
1605 .catch(function (e) {
1606 logger.debug('Failed to get the current session', e);
1607 rej(e);
1608 return;
1609 });
1610 })
1611 .catch(function (e) {
1612 logger.debug('Failed to get the current user', e);
1613 rej(e);
1614 return;
1615 });
1616 });
1617 };
1618 AuthClass.prototype._userSession = function (user) {
1619 return tslib_1.__awaiter(this, void 0, void 0, function () {
1620 var clientMetadata, userSession;
1621 var _this = this;
1622 return tslib_1.__generator(this, function (_a) {
1623 switch (_a.label) {
1624 case 0:
1625 if (!user) {
1626 logger.debug('the user is null');
1627 return [2 /*return*/, this.rejectAuthError(Auth_1.AuthErrorTypes.NoUserSession)];
1628 }
1629 clientMetadata = this._config.clientMetadata;
1630 // Debouncing the concurrent userSession calls by caching the promise.
1631 // This solution assumes users will always call this function with the same CognitoUser instance.
1632 if (this.inflightSessionPromiseCounter === 0) {
1633 this.inflightSessionPromise = new Promise(function (res, rej) {
1634 user.getSession(function (err, session) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
1635 var cleanUpError_6;
1636 return tslib_1.__generator(this, function (_a) {
1637 switch (_a.label) {
1638 case 0:
1639 if (!err) return [3 /*break*/, 5];
1640 logger.debug('Failed to get the session from user', user);
1641 if (!this.isSessionInvalid(err)) return [3 /*break*/, 4];
1642 _a.label = 1;
1643 case 1:
1644 _a.trys.push([1, 3, , 4]);
1645 return [4 /*yield*/, this.cleanUpInvalidSession(user)];
1646 case 2:
1647 _a.sent();
1648 return [3 /*break*/, 4];
1649 case 3:
1650 cleanUpError_6 = _a.sent();
1651 rej(new Error("Session is invalid due to: " + err.message + " and failed to clean up invalid session: " + cleanUpError_6.message));
1652 return [2 /*return*/];
1653 case 4:
1654 rej(err);
1655 return [2 /*return*/];
1656 case 5:
1657 logger.debug('Succeed to get the user session', session);
1658 res(session);
1659 return [2 /*return*/];
1660 }
1661 });
1662 }); }, { clientMetadata: clientMetadata });
1663 });
1664 }
1665 this.inflightSessionPromiseCounter++;
1666 _a.label = 1;
1667 case 1:
1668 _a.trys.push([1, , 3, 4]);
1669 return [4 /*yield*/, this.inflightSessionPromise];
1670 case 2:
1671 userSession = _a.sent();
1672 // Set private member. Avoid user.setSignInUserSession() to prevent excessive localstorage refresh.
1673 // @ts-ignore
1674 user.signInUserSession = userSession;
1675 return [2 /*return*/, userSession];
1676 case 3:
1677 this.inflightSessionPromiseCounter--;
1678 return [7 /*endfinally*/];
1679 case 4: return [2 /*return*/];
1680 }
1681 });
1682 });
1683 };
1684 /**
1685 * Get the corresponding user session
1686 * @param {Object} user - The CognitoUser object
1687 * @return - A promise resolves to the session
1688 */
1689 AuthClass.prototype.userSession = function (user) {
1690 return this._userSession(user);
1691 };
1692 /**
1693 * Get authenticated credentials of current user.
1694 * @return - A promise resolves to be current user's credentials
1695 */
1696 AuthClass.prototype.currentUserCredentials = function () {
1697 return tslib_1.__awaiter(this, void 0, void 0, function () {
1698 var e_9, federatedInfo;
1699 var _this = this;
1700 return tslib_1.__generator(this, function (_a) {
1701 switch (_a.label) {
1702 case 0:
1703 logger.debug('Getting current user credentials');
1704 _a.label = 1;
1705 case 1:
1706 _a.trys.push([1, 3, , 4]);
1707 return [4 /*yield*/, this._storageSync];
1708 case 2:
1709 _a.sent();
1710 return [3 /*break*/, 4];
1711 case 3:
1712 e_9 = _a.sent();
1713 logger.debug('Failed to sync cache info into memory', e_9);
1714 throw e_9;
1715 case 4:
1716 federatedInfo = null;
1717 try {
1718 federatedInfo = JSON.parse(this._storage.getItem('aws-amplify-federatedInfo'));
1719 }
1720 catch (e) {
1721 logger.debug('failed to get or parse item aws-amplify-federatedInfo', e);
1722 }
1723 if (federatedInfo) {
1724 // refresh the jwt token here if necessary
1725 return [2 /*return*/, this.Credentials.refreshFederatedToken(federatedInfo)];
1726 }
1727 else {
1728 return [2 /*return*/, this.currentSession()
1729 .then(function (session) {
1730 logger.debug('getting session success', session);
1731 return _this.Credentials.set(session, 'session');
1732 })
1733 .catch(function () {
1734 logger.debug('getting guest credentials');
1735 return _this.Credentials.set(null, 'guest');
1736 })];
1737 }
1738 return [2 /*return*/];
1739 }
1740 });
1741 });
1742 };
1743 AuthClass.prototype.currentCredentials = function () {
1744 logger.debug('getting current credentials');
1745 return this.Credentials.get();
1746 };
1747 /**
1748 * Initiate an attribute confirmation request
1749 * @param {Object} user - The CognitoUser
1750 * @param {Object} attr - The attributes to be verified
1751 * @return - A promise resolves to callback data if success
1752 */
1753 AuthClass.prototype.verifyUserAttribute = function (user, attr, clientMetadata) {
1754 if (clientMetadata === void 0) { clientMetadata = this._config.clientMetadata; }
1755 return new Promise(function (resolve, reject) {
1756 user.getAttributeVerificationCode(attr, {
1757 onSuccess: function (success) {
1758 return resolve(success);
1759 },
1760 onFailure: function (err) {
1761 return reject(err);
1762 },
1763 }, clientMetadata);
1764 });
1765 };
1766 /**
1767 * Confirm an attribute using a confirmation code
1768 * @param {Object} user - The CognitoUser
1769 * @param {Object} attr - The attribute to be verified
1770 * @param {String} code - The confirmation code
1771 * @return - A promise resolves to callback data if success
1772 */
1773 AuthClass.prototype.verifyUserAttributeSubmit = function (user, attr, code) {
1774 if (!code) {
1775 return this.rejectAuthError(Auth_1.AuthErrorTypes.EmptyCode);
1776 }
1777 return new Promise(function (resolve, reject) {
1778 user.verifyAttribute(attr, code, {
1779 onSuccess: function (data) {
1780 resolve(data);
1781 return;
1782 },
1783 onFailure: function (err) {
1784 reject(err);
1785 return;
1786 },
1787 });
1788 });
1789 };
1790 AuthClass.prototype.verifyCurrentUserAttribute = function (attr) {
1791 var that = this;
1792 return that
1793 .currentUserPoolUser()
1794 .then(function (user) { return that.verifyUserAttribute(user, attr); });
1795 };
1796 /**
1797 * Confirm current user's attribute using a confirmation code
1798 * @param {Object} attr - The attribute to be verified
1799 * @param {String} code - The confirmation code
1800 * @return - A promise resolves to callback data if success
1801 */
1802 AuthClass.prototype.verifyCurrentUserAttributeSubmit = function (attr, code) {
1803 var that = this;
1804 return that
1805 .currentUserPoolUser()
1806 .then(function (user) { return that.verifyUserAttributeSubmit(user, attr, code); });
1807 };
1808 AuthClass.prototype.cognitoIdentitySignOut = function (opts, user) {
1809 return tslib_1.__awaiter(this, void 0, void 0, function () {
1810 var e_10, isSignedInHostedUI;
1811 var _this = this;
1812 return tslib_1.__generator(this, function (_a) {
1813 switch (_a.label) {
1814 case 0:
1815 _a.trys.push([0, 2, , 3]);
1816 return [4 /*yield*/, this._storageSync];
1817 case 1:
1818 _a.sent();
1819 return [3 /*break*/, 3];
1820 case 2:
1821 e_10 = _a.sent();
1822 logger.debug('Failed to sync cache info into memory', e_10);
1823 throw e_10;
1824 case 3:
1825 isSignedInHostedUI = this._oAuthHandler &&
1826 this._storage.getItem('amplify-signin-with-hostedUI') === 'true';
1827 return [2 /*return*/, new Promise(function (res, rej) {
1828 if (opts && opts.global) {
1829 logger.debug('user global sign out', user);
1830 // in order to use global signout
1831 // we must validate the user as an authenticated user by using getSession
1832 var clientMetadata = _this._config.clientMetadata; // TODO: verify behavior if this is override during signIn
1833 user.getSession(function (err, result) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
1834 var cleanUpError_7;
1835 var _this = this;
1836 return tslib_1.__generator(this, function (_a) {
1837 switch (_a.label) {
1838 case 0:
1839 if (!err) return [3 /*break*/, 5];
1840 logger.debug('failed to get the user session', err);
1841 if (!this.isSessionInvalid(err)) return [3 /*break*/, 4];
1842 _a.label = 1;
1843 case 1:
1844 _a.trys.push([1, 3, , 4]);
1845 return [4 /*yield*/, this.cleanUpInvalidSession(user)];
1846 case 2:
1847 _a.sent();
1848 return [3 /*break*/, 4];
1849 case 3:
1850 cleanUpError_7 = _a.sent();
1851 rej(new Error("Session is invalid due to: " + err.message + " and failed to clean up invalid session: " + cleanUpError_7.message));
1852 return [2 /*return*/];
1853 case 4: return [2 /*return*/, rej(err)];
1854 case 5:
1855 user.globalSignOut({
1856 onSuccess: function (data) {
1857 logger.debug('global sign out success');
1858 if (isSignedInHostedUI) {
1859 _this.oAuthSignOutRedirect(res, rej);
1860 }
1861 else {
1862 return res();
1863 }
1864 },
1865 onFailure: function (err) {
1866 logger.debug('global sign out failed', err);
1867 return rej(err);
1868 },
1869 });
1870 return [2 /*return*/];
1871 }
1872 });
1873 }); }, { clientMetadata: clientMetadata });
1874 }
1875 else {
1876 logger.debug('user sign out', user);
1877 user.signOut(function () {
1878 if (isSignedInHostedUI) {
1879 _this.oAuthSignOutRedirect(res, rej);
1880 }
1881 else {
1882 return res();
1883 }
1884 });
1885 }
1886 })];
1887 }
1888 });
1889 });
1890 };
1891 AuthClass.prototype.oAuthSignOutRedirect = function (resolve, reject) {
1892 var isBrowser = core_1.browserOrNode().isBrowser;
1893 if (isBrowser) {
1894 this.oAuthSignOutRedirectOrReject(reject);
1895 }
1896 else {
1897 this.oAuthSignOutAndResolve(resolve);
1898 }
1899 };
1900 AuthClass.prototype.oAuthSignOutAndResolve = function (resolve) {
1901 this._oAuthHandler.signOut();
1902 resolve();
1903 };
1904 AuthClass.prototype.oAuthSignOutRedirectOrReject = function (reject) {
1905 this._oAuthHandler.signOut(); // this method redirects url
1906 // App should be redirected to another url otherwise it will reject
1907 setTimeout(function () { return reject(Error('Signout timeout fail')); }, 3000);
1908 };
1909 /**
1910 * Sign out method
1911 * @
1912 * @return - A promise resolved if success
1913 */
1914 AuthClass.prototype.signOut = function (opts) {
1915 return tslib_1.__awaiter(this, void 0, void 0, function () {
1916 var e_11, user;
1917 return tslib_1.__generator(this, function (_a) {
1918 switch (_a.label) {
1919 case 0:
1920 _a.trys.push([0, 2, , 3]);
1921 return [4 /*yield*/, this.cleanCachedItems()];
1922 case 1:
1923 _a.sent();
1924 return [3 /*break*/, 3];
1925 case 2:
1926 e_11 = _a.sent();
1927 logger.debug('failed to clear cached items');
1928 return [3 /*break*/, 3];
1929 case 3:
1930 if (!this.userPool) return [3 /*break*/, 7];
1931 user = this.userPool.getCurrentUser();
1932 if (!user) return [3 /*break*/, 5];
1933 return [4 /*yield*/, this.cognitoIdentitySignOut(opts, user)];
1934 case 4:
1935 _a.sent();
1936 return [3 /*break*/, 6];
1937 case 5:
1938 logger.debug('no current Cognito user');
1939 _a.label = 6;
1940 case 6: return [3 /*break*/, 8];
1941 case 7:
1942 logger.debug('no Cognito User pool');
1943 _a.label = 8;
1944 case 8:
1945 /**
1946 * Note for future refactor - no reliable way to get username with
1947 * Cognito User Pools vs Identity when federating with Social Providers
1948 * This is why we need a well structured session object that can be inspected
1949 * and information passed back in the message below for Hub dispatch
1950 */
1951 dispatchAuthEvent('signOut', this.user, "A user has been signed out");
1952 this.user = null;
1953 return [2 /*return*/];
1954 }
1955 });
1956 });
1957 };
1958 AuthClass.prototype.cleanCachedItems = function () {
1959 return tslib_1.__awaiter(this, void 0, void 0, function () {
1960 return tslib_1.__generator(this, function (_a) {
1961 switch (_a.label) {
1962 case 0:
1963 // clear cognito cached item
1964 return [4 /*yield*/, this.Credentials.clear()];
1965 case 1:
1966 // clear cognito cached item
1967 _a.sent();
1968 return [2 /*return*/];
1969 }
1970 });
1971 });
1972 };
1973 /**
1974 * Change a password for an authenticated user
1975 * @param {Object} user - The CognitoUser object
1976 * @param {String} oldPassword - the current password
1977 * @param {String} newPassword - the requested new password
1978 * @return - A promise resolves if success
1979 */
1980 AuthClass.prototype.changePassword = function (user, oldPassword, newPassword, clientMetadata) {
1981 var _this = this;
1982 if (clientMetadata === void 0) { clientMetadata = this._config.clientMetadata; }
1983 return new Promise(function (resolve, reject) {
1984 _this.userSession(user).then(function (session) {
1985 user.changePassword(oldPassword, newPassword, function (err, data) {
1986 if (err) {
1987 logger.debug('change password failure', err);
1988 return reject(err);
1989 }
1990 else {
1991 return resolve(data);
1992 }
1993 }, clientMetadata);
1994 });
1995 });
1996 };
1997 /**
1998 * Initiate a forgot password request
1999 * @param {String} username - the username to change password
2000 * @return - A promise resolves if success
2001 */
2002 AuthClass.prototype.forgotPassword = function (username, clientMetadata) {
2003 if (clientMetadata === void 0) { clientMetadata = this._config.clientMetadata; }
2004 if (!this.userPool) {
2005 return this.rejectNoUserPool();
2006 }
2007 if (!username) {
2008 return this.rejectAuthError(Auth_1.AuthErrorTypes.EmptyUsername);
2009 }
2010 var user = this.createCognitoUser(username);
2011 return new Promise(function (resolve, reject) {
2012 user.forgotPassword({
2013 onSuccess: function () {
2014 resolve();
2015 return;
2016 },
2017 onFailure: function (err) {
2018 logger.debug('forgot password failure', err);
2019 dispatchAuthEvent('forgotPassword_failure', err, username + " forgotPassword failed");
2020 reject(err);
2021 return;
2022 },
2023 inputVerificationCode: function (data) {
2024 dispatchAuthEvent('forgotPassword', user, username + " has initiated forgot password flow");
2025 resolve(data);
2026 return;
2027 },
2028 }, clientMetadata);
2029 });
2030 };
2031 /**
2032 * Confirm a new password using a confirmation Code
2033 * @param {String} username - The username
2034 * @param {String} code - The confirmation code
2035 * @param {String} password - The new password
2036 * @return - A promise that resolves if success
2037 */
2038 AuthClass.prototype.forgotPasswordSubmit = function (username, code, password, clientMetadata) {
2039 if (clientMetadata === void 0) { clientMetadata = this._config.clientMetadata; }
2040 if (!this.userPool) {
2041 return this.rejectNoUserPool();
2042 }
2043 if (!username) {
2044 return this.rejectAuthError(Auth_1.AuthErrorTypes.EmptyUsername);
2045 }
2046 if (!code) {
2047 return this.rejectAuthError(Auth_1.AuthErrorTypes.EmptyCode);
2048 }
2049 if (!password) {
2050 return this.rejectAuthError(Auth_1.AuthErrorTypes.EmptyPassword);
2051 }
2052 var user = this.createCognitoUser(username);
2053 return new Promise(function (resolve, reject) {
2054 user.confirmPassword(code, password, {
2055 onSuccess: function (success) {
2056 dispatchAuthEvent('forgotPasswordSubmit', user, username + " forgotPasswordSubmit successful");
2057 resolve(success);
2058 return;
2059 },
2060 onFailure: function (err) {
2061 dispatchAuthEvent('forgotPasswordSubmit_failure', err, username + " forgotPasswordSubmit failed");
2062 reject(err);
2063 return;
2064 },
2065 }, clientMetadata);
2066 });
2067 };
2068 /**
2069 * Get user information
2070 * @async
2071 * @return {Object }- current User's information
2072 */
2073 AuthClass.prototype.currentUserInfo = function () {
2074 return tslib_1.__awaiter(this, void 0, void 0, function () {
2075 var source, user, attributes, userAttrs, credentials, e_12, info, err_2, user;
2076 return tslib_1.__generator(this, function (_a) {
2077 switch (_a.label) {
2078 case 0:
2079 source = this.Credentials.getCredSource();
2080 if (!(!source || source === 'aws' || source === 'userPool')) return [3 /*break*/, 9];
2081 return [4 /*yield*/, this.currentUserPoolUser().catch(function (err) {
2082 return logger.error(err);
2083 })];
2084 case 1:
2085 user = _a.sent();
2086 if (!user) {
2087 return [2 /*return*/, null];
2088 }
2089 _a.label = 2;
2090 case 2:
2091 _a.trys.push([2, 8, , 9]);
2092 return [4 /*yield*/, this.userAttributes(user)];
2093 case 3:
2094 attributes = _a.sent();
2095 userAttrs = this.attributesToObject(attributes);
2096 credentials = null;
2097 _a.label = 4;
2098 case 4:
2099 _a.trys.push([4, 6, , 7]);
2100 return [4 /*yield*/, this.currentCredentials()];
2101 case 5:
2102 credentials = _a.sent();
2103 return [3 /*break*/, 7];
2104 case 6:
2105 e_12 = _a.sent();
2106 logger.debug('Failed to retrieve credentials while getting current user info', e_12);
2107 return [3 /*break*/, 7];
2108 case 7:
2109 info = {
2110 id: credentials ? credentials.identityId : undefined,
2111 username: user.getUsername(),
2112 attributes: userAttrs,
2113 };
2114 return [2 /*return*/, info];
2115 case 8:
2116 err_2 = _a.sent();
2117 logger.error('currentUserInfo error', err_2);
2118 return [2 /*return*/, {}];
2119 case 9:
2120 if (source === 'federated') {
2121 user = this.user;
2122 return [2 /*return*/, user ? user : {}];
2123 }
2124 return [2 /*return*/];
2125 }
2126 });
2127 });
2128 };
2129 AuthClass.prototype.federatedSignIn = function (providerOrOptions, response, user) {
2130 return tslib_1.__awaiter(this, void 0, void 0, function () {
2131 var options, provider, customState, client_id, redirect_uri, provider, loggedInUser, token, identity_id, expires_at, credentials, currentUser;
2132 return tslib_1.__generator(this, function (_a) {
2133 switch (_a.label) {
2134 case 0:
2135 if (!this._config.identityPoolId && !this._config.userPoolId) {
2136 throw new Error("Federation requires either a User Pool or Identity Pool in config");
2137 }
2138 // Ensure backwards compatability
2139 if (typeof providerOrOptions === 'undefined') {
2140 if (this._config.identityPoolId && !this._config.userPoolId) {
2141 throw new Error("Federation with Identity Pools requires tokens passed as arguments");
2142 }
2143 }
2144 if (!(types_1.isFederatedSignInOptions(providerOrOptions) ||
2145 types_1.isFederatedSignInOptionsCustom(providerOrOptions) ||
2146 types_1.hasCustomState(providerOrOptions) ||
2147 typeof providerOrOptions === 'undefined')) return [3 /*break*/, 1];
2148 options = providerOrOptions || {
2149 provider: Auth_1.CognitoHostedUIIdentityProvider.Cognito,
2150 };
2151 provider = types_1.isFederatedSignInOptions(options)
2152 ? options.provider
2153 : options.customProvider;
2154 customState = types_1.isFederatedSignInOptions(options)
2155 ? options.customState
2156 : options.customState;
2157 if (this._config.userPoolId) {
2158 client_id = types_1.isCognitoHostedOpts(this._config.oauth)
2159 ? this._config.userPoolWebClientId
2160 : this._config.oauth.clientID;
2161 redirect_uri = types_1.isCognitoHostedOpts(this._config.oauth)
2162 ? this._config.oauth.redirectSignIn
2163 : this._config.oauth.redirectUri;
2164 this._oAuthHandler.oauthSignIn(this._config.oauth.responseType, this._config.oauth.domain, redirect_uri, client_id, provider, customState);
2165 }
2166 return [3 /*break*/, 4];
2167 case 1:
2168 provider = providerOrOptions;
2169 // To check if the user is already logged in
2170 try {
2171 loggedInUser = JSON.stringify(JSON.parse(this._storage.getItem('aws-amplify-federatedInfo')).user);
2172 if (loggedInUser) {
2173 logger.warn("There is already a signed in user: " + loggedInUser + " in your app.\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tYou should not call Auth.federatedSignIn method again as it may cause unexpected behavior.");
2174 }
2175 }
2176 catch (e) { }
2177 token = response.token, identity_id = response.identity_id, expires_at = response.expires_at;
2178 return [4 /*yield*/, this.Credentials.set({ provider: provider, token: token, identity_id: identity_id, user: user, expires_at: expires_at }, 'federation')];
2179 case 2:
2180 credentials = _a.sent();
2181 return [4 /*yield*/, this.currentAuthenticatedUser()];
2182 case 3:
2183 currentUser = _a.sent();
2184 dispatchAuthEvent('signIn', currentUser, "A user " + currentUser.username + " has been signed in");
2185 logger.debug('federated sign in credentials', credentials);
2186 return [2 /*return*/, credentials];
2187 case 4: return [2 /*return*/];
2188 }
2189 });
2190 });
2191 };
2192 /**
2193 * Used to complete the OAuth flow with or without the Cognito Hosted UI
2194 * @param {String} URL - optional parameter for customers to pass in the response URL
2195 */
2196 AuthClass.prototype._handleAuthResponse = function (URL) {
2197 return tslib_1.__awaiter(this, void 0, void 0, function () {
2198 var currentUrl, hasCodeOrError, hasTokenOrError, _a, accessToken, idToken, refreshToken, state, session, credentials, isCustomStateIncluded, currentUser, customState, err_3;
2199 return tslib_1.__generator(this, function (_b) {
2200 switch (_b.label) {
2201 case 0:
2202 if (this.oAuthFlowInProgress) {
2203 logger.debug("Skipping URL " + URL + " current flow in progress");
2204 return [2 /*return*/];
2205 }
2206 _b.label = 1;
2207 case 1:
2208 _b.trys.push([1, , 8, 9]);
2209 this.oAuthFlowInProgress = true;
2210 if (!this._config.userPoolId) {
2211 throw new Error("OAuth responses require a User Pool defined in config");
2212 }
2213 dispatchAuthEvent('parsingCallbackUrl', { url: URL }, "The callback url is being parsed");
2214 currentUrl = URL || (core_1.browserOrNode().isBrowser ? window.location.href : '');
2215 hasCodeOrError = !!(url_1.parse(currentUrl).query || '')
2216 .split('&')
2217 .map(function (entry) { return entry.split('='); })
2218 .find(function (_a) {
2219 var _b = tslib_1.__read(_a, 1), k = _b[0];
2220 return k === 'code' || k === 'error';
2221 });
2222 hasTokenOrError = !!(url_1.parse(currentUrl).hash || '#')
2223 .substr(1)
2224 .split('&')
2225 .map(function (entry) { return entry.split('='); })
2226 .find(function (_a) {
2227 var _b = tslib_1.__read(_a, 1), k = _b[0];
2228 return k === 'access_token' || k === 'error';
2229 });
2230 if (!(hasCodeOrError || hasTokenOrError)) return [3 /*break*/, 7];
2231 this._storage.setItem('amplify-redirected-from-hosted-ui', 'true');
2232 _b.label = 2;
2233 case 2:
2234 _b.trys.push([2, 6, , 7]);
2235 return [4 /*yield*/, this._oAuthHandler.handleAuthResponse(currentUrl)];
2236 case 3:
2237 _a = _b.sent(), accessToken = _a.accessToken, idToken = _a.idToken, refreshToken = _a.refreshToken, state = _a.state;
2238 session = new amazon_cognito_identity_js_1.CognitoUserSession({
2239 IdToken: new amazon_cognito_identity_js_1.CognitoIdToken({ IdToken: idToken }),
2240 RefreshToken: new amazon_cognito_identity_js_1.CognitoRefreshToken({
2241 RefreshToken: refreshToken,
2242 }),
2243 AccessToken: new amazon_cognito_identity_js_1.CognitoAccessToken({
2244 AccessToken: accessToken,
2245 }),
2246 });
2247 credentials = void 0;
2248 if (!this._config.identityPoolId) return [3 /*break*/, 5];
2249 return [4 /*yield*/, this.Credentials.set(session, 'session')];
2250 case 4:
2251 credentials = _b.sent();
2252 logger.debug('AWS credentials', credentials);
2253 _b.label = 5;
2254 case 5:
2255 isCustomStateIncluded = /-/.test(state);
2256 currentUser = this.createCognitoUser(session.getIdToken().decodePayload()['cognito:username']);
2257 // This calls cacheTokens() in Cognito SDK
2258 currentUser.setSignInUserSession(session);
2259 if (window && typeof window.history !== 'undefined') {
2260 window.history.replaceState({}, null, this._config.oauth.redirectSignIn);
2261 }
2262 dispatchAuthEvent('signIn', currentUser, "A user " + currentUser.getUsername() + " has been signed in");
2263 dispatchAuthEvent('cognitoHostedUI', currentUser, "A user " + currentUser.getUsername() + " has been signed in via Cognito Hosted UI");
2264 if (isCustomStateIncluded) {
2265 customState = state.split('-').splice(1).join('-');
2266 dispatchAuthEvent('customOAuthState', core_1.urlSafeDecode(customState), "State for user " + currentUser.getUsername());
2267 }
2268 //#endregion
2269 return [2 /*return*/, credentials];
2270 case 6:
2271 err_3 = _b.sent();
2272 logger.debug('Error in cognito hosted auth response', err_3);
2273 // Just like a successful handling of `?code`, replace the window history to "dispose" of the `code`.
2274 // Otherwise, reloading the page will throw errors as the `code` has already been spent.
2275 if (window && typeof window.history !== 'undefined') {
2276 window.history.replaceState({}, null, this._config.oauth.redirectSignIn);
2277 }
2278 dispatchAuthEvent('signIn_failure', err_3, "The OAuth response flow failed");
2279 dispatchAuthEvent('cognitoHostedUI_failure', err_3, "A failure occurred when returning to the Cognito Hosted UI");
2280 dispatchAuthEvent('customState_failure', err_3, "A failure occurred when returning state");
2281 return [3 /*break*/, 7];
2282 case 7: return [3 /*break*/, 9];
2283 case 8:
2284 this.oAuthFlowInProgress = false;
2285 return [7 /*endfinally*/];
2286 case 9: return [2 /*return*/];
2287 }
2288 });
2289 });
2290 };
2291 /**
2292 * Compact version of credentials
2293 * @param {Object} credentials
2294 * @return {Object} - Credentials
2295 */
2296 AuthClass.prototype.essentialCredentials = function (credentials) {
2297 return {
2298 accessKeyId: credentials.accessKeyId,
2299 sessionToken: credentials.sessionToken,
2300 secretAccessKey: credentials.secretAccessKey,
2301 identityId: credentials.identityId,
2302 authenticated: credentials.authenticated,
2303 };
2304 };
2305 AuthClass.prototype.attributesToObject = function (attributes) {
2306 var _this = this;
2307 var obj = {};
2308 if (attributes) {
2309 attributes.map(function (attribute) {
2310 if (attribute.Name === 'email_verified' ||
2311 attribute.Name === 'phone_number_verified') {
2312 obj[attribute.Name] =
2313 _this.isTruthyString(attribute.Value) || attribute.Value === true;
2314 }
2315 else {
2316 obj[attribute.Name] = attribute.Value;
2317 }
2318 });
2319 }
2320 return obj;
2321 };
2322 AuthClass.prototype.isTruthyString = function (value) {
2323 return (typeof value.toLowerCase === 'function' && value.toLowerCase() === 'true');
2324 };
2325 AuthClass.prototype.createCognitoUser = function (username) {
2326 var userData = {
2327 Username: username,
2328 Pool: this.userPool,
2329 };
2330 userData.Storage = this._storage;
2331 var authenticationFlowType = this._config.authenticationFlowType;
2332 var user = new amazon_cognito_identity_js_1.CognitoUser(userData);
2333 if (authenticationFlowType) {
2334 user.setAuthenticationFlowType(authenticationFlowType);
2335 }
2336 return user;
2337 };
2338 AuthClass.prototype._isValidAuthStorage = function (obj) {
2339 // We need to check if the obj has the functions of Storage
2340 return (!!obj &&
2341 typeof obj.getItem === 'function' &&
2342 typeof obj.setItem === 'function' &&
2343 typeof obj.removeItem === 'function' &&
2344 typeof obj.clear === 'function');
2345 };
2346 AuthClass.prototype.noUserPoolErrorHandler = function (config) {
2347 if (config) {
2348 if (!config.userPoolId || !config.identityPoolId) {
2349 return Auth_1.AuthErrorTypes.MissingAuthConfig;
2350 }
2351 }
2352 return Auth_1.AuthErrorTypes.NoConfig;
2353 };
2354 AuthClass.prototype.rejectAuthError = function (type) {
2355 return Promise.reject(new Errors_1.AuthError(type));
2356 };
2357 AuthClass.prototype.rejectNoUserPool = function () {
2358 var type = this.noUserPoolErrorHandler(this._config);
2359 return Promise.reject(new Errors_1.NoUserPoolError(type));
2360 };
2361 AuthClass.prototype.rememberDevice = function () {
2362 return tslib_1.__awaiter(this, void 0, void 0, function () {
2363 var currUser, error_2;
2364 return tslib_1.__generator(this, function (_a) {
2365 switch (_a.label) {
2366 case 0:
2367 _a.trys.push([0, 2, , 3]);
2368 return [4 /*yield*/, this.currentUserPoolUser()];
2369 case 1:
2370 currUser = _a.sent();
2371 return [3 /*break*/, 3];
2372 case 2:
2373 error_2 = _a.sent();
2374 logger.debug('The user is not authenticated by the error', error_2);
2375 return [2 /*return*/, Promise.reject('The user is not authenticated')];
2376 case 3:
2377 currUser.getCachedDeviceKeyAndPassword();
2378 return [2 /*return*/, new Promise(function (res, rej) {
2379 currUser.setDeviceStatusRemembered({
2380 onSuccess: function (data) {
2381 res(data);
2382 },
2383 onFailure: function (err) {
2384 if (err.code === 'InvalidParameterException') {
2385 rej(new Errors_1.AuthError(Auth_1.AuthErrorTypes.DeviceConfig));
2386 }
2387 else if (err.code === 'NetworkError') {
2388 rej(new Errors_1.AuthError(Auth_1.AuthErrorTypes.NetworkError));
2389 }
2390 else {
2391 rej(err);
2392 }
2393 },
2394 });
2395 })];
2396 }
2397 });
2398 });
2399 };
2400 AuthClass.prototype.forgetDevice = function () {
2401 return tslib_1.__awaiter(this, void 0, void 0, function () {
2402 var currUser, error_3;
2403 return tslib_1.__generator(this, function (_a) {
2404 switch (_a.label) {
2405 case 0:
2406 _a.trys.push([0, 2, , 3]);
2407 return [4 /*yield*/, this.currentUserPoolUser()];
2408 case 1:
2409 currUser = _a.sent();
2410 return [3 /*break*/, 3];
2411 case 2:
2412 error_3 = _a.sent();
2413 logger.debug('The user is not authenticated by the error', error_3);
2414 return [2 /*return*/, Promise.reject('The user is not authenticated')];
2415 case 3:
2416 currUser.getCachedDeviceKeyAndPassword();
2417 return [2 /*return*/, new Promise(function (res, rej) {
2418 currUser.forgetDevice({
2419 onSuccess: function (data) {
2420 res(data);
2421 },
2422 onFailure: function (err) {
2423 if (err.code === 'InvalidParameterException') {
2424 rej(new Errors_1.AuthError(Auth_1.AuthErrorTypes.DeviceConfig));
2425 }
2426 else if (err.code === 'NetworkError') {
2427 rej(new Errors_1.AuthError(Auth_1.AuthErrorTypes.NetworkError));
2428 }
2429 else {
2430 rej(err);
2431 }
2432 },
2433 });
2434 })];
2435 }
2436 });
2437 });
2438 };
2439 AuthClass.prototype.fetchDevices = function () {
2440 return tslib_1.__awaiter(this, void 0, void 0, function () {
2441 var currUser, error_4;
2442 return tslib_1.__generator(this, function (_a) {
2443 switch (_a.label) {
2444 case 0:
2445 _a.trys.push([0, 2, , 3]);
2446 return [4 /*yield*/, this.currentUserPoolUser()];
2447 case 1:
2448 currUser = _a.sent();
2449 return [3 /*break*/, 3];
2450 case 2:
2451 error_4 = _a.sent();
2452 logger.debug('The user is not authenticated by the error', error_4);
2453 throw new Error('The user is not authenticated');
2454 case 3:
2455 currUser.getCachedDeviceKeyAndPassword();
2456 return [2 /*return*/, new Promise(function (res, rej) {
2457 var cb = {
2458 onSuccess: function (data) {
2459 var deviceList = data.Devices.map(function (device) {
2460 var deviceName = device.DeviceAttributes.find(function (_a) {
2461 var Name = _a.Name;
2462 return Name === 'device_name';
2463 }) || {};
2464 var deviceInfo = {
2465 id: device.DeviceKey,
2466 name: deviceName.Value,
2467 };
2468 return deviceInfo;
2469 });
2470 res(deviceList);
2471 },
2472 onFailure: function (err) {
2473 if (err.code === 'InvalidParameterException') {
2474 rej(new Errors_1.AuthError(Auth_1.AuthErrorTypes.DeviceConfig));
2475 }
2476 else if (err.code === 'NetworkError') {
2477 rej(new Errors_1.AuthError(Auth_1.AuthErrorTypes.NetworkError));
2478 }
2479 else {
2480 rej(err);
2481 }
2482 },
2483 };
2484 currUser.listDevices(MAX_DEVICES, null, cb);
2485 })];
2486 }
2487 });
2488 });
2489 };
2490 return AuthClass;
2491}());
2492exports.AuthClass = AuthClass;
2493exports.Auth = new AuthClass(null);
2494core_1.Amplify.register(exports.Auth);
2495//# sourceMappingURL=Auth.js.map
\No newline at end of file