UNPKG

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