UNPKG

68.6 kBJavaScriptView Raw
1/*!
2 * Copyright 2016 Amazon.com,
3 * Inc. or its affiliates. All Rights Reserved.
4 *
5 * Licensed under the Amazon Software License (the "License").
6 * You may not use this file except in compliance with the
7 * License. A copy of the License is located at
8 *
9 * http://aws.amazon.com/asl/
10 *
11 * or in the "license" file accompanying this file. This file is
12 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
13 * CONDITIONS OF ANY KIND, express or implied. See the License
14 * for the specific language governing permissions and
15 * limitations under the License.
16 */
17import { Buffer } from 'buffer';
18import CryptoJS from 'crypto-js/core';
19import TypedArrays from 'crypto-js/lib-typedarrays'; // necessary for crypto js
20
21import Base64 from 'crypto-js/enc-base64';
22import HmacSHA256 from 'crypto-js/hmac-sha256';
23import BigInteger from './BigInteger';
24import AuthenticationHelper from './AuthenticationHelper';
25import CognitoAccessToken from './CognitoAccessToken';
26import CognitoIdToken from './CognitoIdToken';
27import CognitoRefreshToken from './CognitoRefreshToken';
28import CognitoUserSession from './CognitoUserSession';
29import DateHelper from './DateHelper';
30import CognitoUserAttribute from './CognitoUserAttribute';
31import StorageHelper from './StorageHelper';
32/**
33 * @callback nodeCallback
34 * @template T result
35 * @param {*} err The operation failure reason, or null.
36 * @param {T} result The operation result.
37 */
38
39/**
40 * @callback onFailure
41 * @param {*} err Failure reason.
42 */
43
44/**
45 * @callback onSuccess
46 * @template T result
47 * @param {T} result The operation result.
48 */
49
50/**
51 * @callback mfaRequired
52 * @param {*} details MFA challenge details.
53 */
54
55/**
56 * @callback customChallenge
57 * @param {*} details Custom challenge details.
58 */
59
60/**
61 * @callback inputVerificationCode
62 * @param {*} data Server response.
63 */
64
65/**
66 * @callback authSuccess
67 * @param {CognitoUserSession} session The new session.
68 * @param {bool=} userConfirmationNecessary User must be confirmed.
69 */
70
71var isBrowser = typeof navigator !== 'undefined';
72var userAgent = isBrowser ? navigator.userAgent : 'nodejs';
73/** @class */
74
75var CognitoUser = /*#__PURE__*/function () {
76 /**
77 * Constructs a new CognitoUser object
78 * @param {object} data Creation options
79 * @param {string} data.Username The user's username.
80 * @param {CognitoUserPool} data.Pool Pool containing the user.
81 * @param {object} data.Storage Optional storage object.
82 */
83 function CognitoUser(data) {
84 if (data == null || data.Username == null || data.Pool == null) {
85 throw new Error('Username and pool information are required.');
86 }
87
88 this.username = data.Username || '';
89 this.pool = data.Pool;
90 this.Session = null;
91 this.client = data.Pool.client;
92 this.signInUserSession = null;
93 this.authenticationFlowType = 'USER_SRP_AUTH';
94 this.storage = data.Storage || new StorageHelper().getStorage();
95 this.keyPrefix = "CognitoIdentityServiceProvider." + this.pool.getClientId();
96 this.userDataKey = this.keyPrefix + "." + this.username + ".userData";
97 }
98 /**
99 * Sets the session for this user
100 * @param {CognitoUserSession} signInUserSession the session
101 * @returns {void}
102 */
103
104
105 var _proto = CognitoUser.prototype;
106
107 _proto.setSignInUserSession = function setSignInUserSession(signInUserSession) {
108 this.clearCachedUserData();
109 this.signInUserSession = signInUserSession;
110 this.cacheTokens();
111 }
112 /**
113 * @returns {CognitoUserSession} the current session for this user
114 */
115 ;
116
117 _proto.getSignInUserSession = function getSignInUserSession() {
118 return this.signInUserSession;
119 }
120 /**
121 * @returns {string} the user's username
122 */
123 ;
124
125 _proto.getUsername = function getUsername() {
126 return this.username;
127 }
128 /**
129 * @returns {String} the authentication flow type
130 */
131 ;
132
133 _proto.getAuthenticationFlowType = function getAuthenticationFlowType() {
134 return this.authenticationFlowType;
135 }
136 /**
137 * sets authentication flow type
138 * @param {string} authenticationFlowType New value.
139 * @returns {void}
140 */
141 ;
142
143 _proto.setAuthenticationFlowType = function setAuthenticationFlowType(authenticationFlowType) {
144 this.authenticationFlowType = authenticationFlowType;
145 }
146 /**
147 * This is used for authenticating the user through the custom authentication flow.
148 * @param {AuthenticationDetails} authDetails Contains the authentication data
149 * @param {object} callback Result callback map.
150 * @param {onFailure} callback.onFailure Called on any error.
151 * @param {customChallenge} callback.customChallenge Custom challenge
152 * response required to continue.
153 * @param {authSuccess} callback.onSuccess Called on success with the new session.
154 * @returns {void}
155 */
156 ;
157
158 _proto.initiateAuth = function initiateAuth(authDetails, callback) {
159 var _this = this;
160
161 var authParameters = authDetails.getAuthParameters();
162 authParameters.USERNAME = this.username;
163 var clientMetaData = Object.keys(authDetails.getValidationData()).length !== 0 ? authDetails.getValidationData() : authDetails.getClientMetadata();
164 var jsonReq = {
165 AuthFlow: 'CUSTOM_AUTH',
166 ClientId: this.pool.getClientId(),
167 AuthParameters: authParameters,
168 ClientMetadata: clientMetaData
169 };
170
171 if (this.getUserContextData()) {
172 jsonReq.UserContextData = this.getUserContextData();
173 }
174
175 this.client.request('InitiateAuth', jsonReq, function (err, data) {
176 if (err) {
177 return callback.onFailure(err);
178 }
179
180 var challengeName = data.ChallengeName;
181 var challengeParameters = data.ChallengeParameters;
182
183 if (challengeName === 'CUSTOM_CHALLENGE') {
184 _this.Session = data.Session;
185 return callback.customChallenge(challengeParameters);
186 }
187
188 _this.signInUserSession = _this.getCognitoUserSession(data.AuthenticationResult);
189
190 _this.cacheTokens();
191
192 return callback.onSuccess(_this.signInUserSession);
193 });
194 }
195 /**
196 * This is used for authenticating the user.
197 * stuff
198 * @param {AuthenticationDetails} authDetails Contains the authentication data
199 * @param {object} callback Result callback map.
200 * @param {onFailure} callback.onFailure Called on any error.
201 * @param {newPasswordRequired} callback.newPasswordRequired new
202 * password and any required attributes are required to continue
203 * @param {mfaRequired} callback.mfaRequired MFA code
204 * required to continue.
205 * @param {customChallenge} callback.customChallenge Custom challenge
206 * response required to continue.
207 * @param {authSuccess} callback.onSuccess Called on success with the new session.
208 * @returns {void}
209 */
210 ;
211
212 _proto.authenticateUser = function authenticateUser(authDetails, callback) {
213 if (this.authenticationFlowType === 'USER_PASSWORD_AUTH') {
214 return this.authenticateUserPlainUsernamePassword(authDetails, callback);
215 } else if (this.authenticationFlowType === 'USER_SRP_AUTH' || this.authenticationFlowType === 'CUSTOM_AUTH') {
216 return this.authenticateUserDefaultAuth(authDetails, callback);
217 }
218
219 return callback.onFailure(new Error('Authentication flow type is invalid.'));
220 }
221 /**
222 * PRIVATE ONLY: This is an internal only method and should not
223 * be directly called by the consumers.
224 * It calls the AuthenticationHelper for SRP related
225 * stuff
226 * @param {AuthenticationDetails} authDetails Contains the authentication data
227 * @param {object} callback Result callback map.
228 * @param {onFailure} callback.onFailure Called on any error.
229 * @param {newPasswordRequired} callback.newPasswordRequired new
230 * password and any required attributes are required to continue
231 * @param {mfaRequired} callback.mfaRequired MFA code
232 * required to continue.
233 * @param {customChallenge} callback.customChallenge Custom challenge
234 * response required to continue.
235 * @param {authSuccess} callback.onSuccess Called on success with the new session.
236 * @returns {void}
237 */
238 ;
239
240 _proto.authenticateUserDefaultAuth = function authenticateUserDefaultAuth(authDetails, callback) {
241 var _this2 = this;
242
243 var authenticationHelper = new AuthenticationHelper(this.pool.getUserPoolId().split('_')[1]);
244 var dateHelper = new DateHelper();
245 var serverBValue;
246 var salt;
247 var authParameters = {};
248
249 if (this.deviceKey != null) {
250 authParameters.DEVICE_KEY = this.deviceKey;
251 }
252
253 authParameters.USERNAME = this.username;
254 authenticationHelper.getLargeAValue(function (errOnAValue, aValue) {
255 // getLargeAValue callback start
256 if (errOnAValue) {
257 callback.onFailure(errOnAValue);
258 }
259
260 authParameters.SRP_A = aValue.toString(16);
261
262 if (_this2.authenticationFlowType === 'CUSTOM_AUTH') {
263 authParameters.CHALLENGE_NAME = 'SRP_A';
264 }
265
266 var clientMetaData = Object.keys(authDetails.getValidationData()).length !== 0 ? authDetails.getValidationData() : authDetails.getClientMetadata();
267 var jsonReq = {
268 AuthFlow: _this2.authenticationFlowType,
269 ClientId: _this2.pool.getClientId(),
270 AuthParameters: authParameters,
271 ClientMetadata: clientMetaData
272 };
273
274 if (_this2.getUserContextData(_this2.username)) {
275 jsonReq.UserContextData = _this2.getUserContextData(_this2.username);
276 }
277
278 _this2.client.request('InitiateAuth', jsonReq, function (err, data) {
279 if (err) {
280 return callback.onFailure(err);
281 }
282
283 var challengeParameters = data.ChallengeParameters;
284 _this2.username = challengeParameters.USER_ID_FOR_SRP;
285 serverBValue = new BigInteger(challengeParameters.SRP_B, 16);
286 salt = new BigInteger(challengeParameters.SALT, 16);
287
288 _this2.getCachedDeviceKeyAndPassword();
289
290 authenticationHelper.getPasswordAuthenticationKey(_this2.username, authDetails.getPassword(), serverBValue, salt, function (errOnHkdf, hkdf) {
291 // getPasswordAuthenticationKey callback start
292 if (errOnHkdf) {
293 callback.onFailure(errOnHkdf);
294 }
295
296 var dateNow = dateHelper.getNowString();
297 var message = CryptoJS.lib.WordArray.create(Buffer.concat([Buffer.from(_this2.pool.getUserPoolId().split('_')[1], 'utf8'), Buffer.from(_this2.username, 'utf8'), Buffer.from(challengeParameters.SECRET_BLOCK, 'base64'), Buffer.from(dateNow, 'utf8')]));
298 var key = CryptoJS.lib.WordArray.create(hkdf);
299 var signatureString = Base64.stringify(HmacSHA256(message, key));
300 var challengeResponses = {};
301 challengeResponses.USERNAME = _this2.username;
302 challengeResponses.PASSWORD_CLAIM_SECRET_BLOCK = challengeParameters.SECRET_BLOCK;
303 challengeResponses.TIMESTAMP = dateNow;
304 challengeResponses.PASSWORD_CLAIM_SIGNATURE = signatureString;
305
306 if (_this2.deviceKey != null) {
307 challengeResponses.DEVICE_KEY = _this2.deviceKey;
308 }
309
310 var respondToAuthChallenge = function respondToAuthChallenge(challenge, challengeCallback) {
311 return _this2.client.request('RespondToAuthChallenge', challenge, function (errChallenge, dataChallenge) {
312 if (errChallenge && errChallenge.code === 'ResourceNotFoundException' && errChallenge.message.toLowerCase().indexOf('device') !== -1) {
313 challengeResponses.DEVICE_KEY = null;
314 _this2.deviceKey = null;
315 _this2.randomPassword = null;
316 _this2.deviceGroupKey = null;
317
318 _this2.clearCachedDeviceKeyAndPassword();
319
320 return respondToAuthChallenge(challenge, challengeCallback);
321 }
322
323 return challengeCallback(errChallenge, dataChallenge);
324 });
325 };
326
327 var jsonReqResp = {
328 ChallengeName: 'PASSWORD_VERIFIER',
329 ClientId: _this2.pool.getClientId(),
330 ChallengeResponses: challengeResponses,
331 Session: data.Session,
332 ClientMetadata: clientMetaData
333 };
334
335 if (_this2.getUserContextData()) {
336 jsonReqResp.UserContextData = _this2.getUserContextData();
337 }
338
339 respondToAuthChallenge(jsonReqResp, function (errAuthenticate, dataAuthenticate) {
340 if (errAuthenticate) {
341 return callback.onFailure(errAuthenticate);
342 }
343
344 return _this2.authenticateUserInternal(dataAuthenticate, authenticationHelper, callback);
345 });
346 return undefined; // getPasswordAuthenticationKey callback end
347 });
348 return undefined;
349 }); // getLargeAValue callback end
350
351 });
352 }
353 /**
354 * PRIVATE ONLY: This is an internal only method and should not
355 * be directly called by the consumers.
356 * @param {AuthenticationDetails} authDetails Contains the authentication data.
357 * @param {object} callback Result callback map.
358 * @param {onFailure} callback.onFailure Called on any error.
359 * @param {mfaRequired} callback.mfaRequired MFA code
360 * required to continue.
361 * @param {authSuccess} callback.onSuccess Called on success with the new session.
362 * @returns {void}
363 */
364 ;
365
366 _proto.authenticateUserPlainUsernamePassword = function authenticateUserPlainUsernamePassword(authDetails, callback) {
367 var _this3 = this;
368
369 var authParameters = {};
370 authParameters.USERNAME = this.username;
371 authParameters.PASSWORD = authDetails.getPassword();
372
373 if (!authParameters.PASSWORD) {
374 callback.onFailure(new Error('PASSWORD parameter is required'));
375 return;
376 }
377
378 var authenticationHelper = new AuthenticationHelper(this.pool.getUserPoolId().split('_')[1]);
379 this.getCachedDeviceKeyAndPassword();
380
381 if (this.deviceKey != null) {
382 authParameters.DEVICE_KEY = this.deviceKey;
383 }
384
385 var clientMetaData = Object.keys(authDetails.getValidationData()).length !== 0 ? authDetails.getValidationData() : authDetails.getClientMetadata();
386 var jsonReq = {
387 AuthFlow: 'USER_PASSWORD_AUTH',
388 ClientId: this.pool.getClientId(),
389 AuthParameters: authParameters,
390 ClientMetadata: clientMetaData
391 };
392
393 if (this.getUserContextData(this.username)) {
394 jsonReq.UserContextData = this.getUserContextData(this.username);
395 } // USER_PASSWORD_AUTH happens in a single round-trip: client sends userName and password,
396 // Cognito UserPools verifies password and returns tokens.
397
398
399 this.client.request('InitiateAuth', jsonReq, function (err, authResult) {
400 if (err) {
401 return callback.onFailure(err);
402 }
403
404 return _this3.authenticateUserInternal(authResult, authenticationHelper, callback);
405 });
406 }
407 /**
408 * PRIVATE ONLY: This is an internal only method and should not
409 * be directly called by the consumers.
410 * @param {object} dataAuthenticate authentication data
411 * @param {object} authenticationHelper helper created
412 * @param {callback} callback passed on from caller
413 * @returns {void}
414 */
415 ;
416
417 _proto.authenticateUserInternal = function authenticateUserInternal(dataAuthenticate, authenticationHelper, callback) {
418 var _this4 = this;
419
420 var challengeName = dataAuthenticate.ChallengeName;
421 var challengeParameters = dataAuthenticate.ChallengeParameters;
422
423 if (challengeName === 'SMS_MFA') {
424 this.Session = dataAuthenticate.Session;
425 return callback.mfaRequired(challengeName, challengeParameters);
426 }
427
428 if (challengeName === 'SELECT_MFA_TYPE') {
429 this.Session = dataAuthenticate.Session;
430 return callback.selectMFAType(challengeName, challengeParameters);
431 }
432
433 if (challengeName === 'MFA_SETUP') {
434 this.Session = dataAuthenticate.Session;
435 return callback.mfaSetup(challengeName, challengeParameters);
436 }
437
438 if (challengeName === 'SOFTWARE_TOKEN_MFA') {
439 this.Session = dataAuthenticate.Session;
440 return callback.totpRequired(challengeName, challengeParameters);
441 }
442
443 if (challengeName === 'CUSTOM_CHALLENGE') {
444 this.Session = dataAuthenticate.Session;
445 return callback.customChallenge(challengeParameters);
446 }
447
448 if (challengeName === 'NEW_PASSWORD_REQUIRED') {
449 this.Session = dataAuthenticate.Session;
450 var userAttributes = null;
451 var rawRequiredAttributes = null;
452 var requiredAttributes = [];
453 var userAttributesPrefix = authenticationHelper.getNewPasswordRequiredChallengeUserAttributePrefix();
454
455 if (challengeParameters) {
456 userAttributes = JSON.parse(dataAuthenticate.ChallengeParameters.userAttributes);
457 rawRequiredAttributes = JSON.parse(dataAuthenticate.ChallengeParameters.requiredAttributes);
458 }
459
460 if (rawRequiredAttributes) {
461 for (var i = 0; i < rawRequiredAttributes.length; i++) {
462 requiredAttributes[i] = rawRequiredAttributes[i].substr(userAttributesPrefix.length);
463 }
464 }
465
466 return callback.newPasswordRequired(userAttributes, requiredAttributes);
467 }
468
469 if (challengeName === 'DEVICE_SRP_AUTH') {
470 this.getDeviceResponse(callback);
471 return undefined;
472 }
473
474 this.signInUserSession = this.getCognitoUserSession(dataAuthenticate.AuthenticationResult);
475 this.challengeName = challengeName;
476 this.cacheTokens();
477 var newDeviceMetadata = dataAuthenticate.AuthenticationResult.NewDeviceMetadata;
478
479 if (newDeviceMetadata == null) {
480 return callback.onSuccess(this.signInUserSession);
481 }
482
483 authenticationHelper.generateHashDevice(dataAuthenticate.AuthenticationResult.NewDeviceMetadata.DeviceGroupKey, dataAuthenticate.AuthenticationResult.NewDeviceMetadata.DeviceKey, function (errGenHash) {
484 if (errGenHash) {
485 return callback.onFailure(errGenHash);
486 }
487
488 var deviceSecretVerifierConfig = {
489 Salt: Buffer.from(authenticationHelper.getSaltDevices(), 'hex').toString('base64'),
490 PasswordVerifier: Buffer.from(authenticationHelper.getVerifierDevices(), 'hex').toString('base64')
491 };
492 _this4.verifierDevices = deviceSecretVerifierConfig.PasswordVerifier;
493 _this4.deviceGroupKey = newDeviceMetadata.DeviceGroupKey;
494 _this4.randomPassword = authenticationHelper.getRandomPassword();
495
496 _this4.client.request('ConfirmDevice', {
497 DeviceKey: newDeviceMetadata.DeviceKey,
498 AccessToken: _this4.signInUserSession.getAccessToken().getJwtToken(),
499 DeviceSecretVerifierConfig: deviceSecretVerifierConfig,
500 DeviceName: userAgent
501 }, function (errConfirm, dataConfirm) {
502 if (errConfirm) {
503 return callback.onFailure(errConfirm);
504 }
505
506 _this4.deviceKey = dataAuthenticate.AuthenticationResult.NewDeviceMetadata.DeviceKey;
507
508 _this4.cacheDeviceKeyAndPassword();
509
510 if (dataConfirm.UserConfirmationNecessary === true) {
511 return callback.onSuccess(_this4.signInUserSession, dataConfirm.UserConfirmationNecessary);
512 }
513
514 return callback.onSuccess(_this4.signInUserSession);
515 });
516
517 return undefined;
518 });
519 return undefined;
520 }
521 /**
522 * This method is user to complete the NEW_PASSWORD_REQUIRED challenge.
523 * Pass the new password with any new user attributes to be updated.
524 * User attribute keys must be of format userAttributes.<attribute_name>.
525 * @param {string} newPassword new password for this user
526 * @param {object} requiredAttributeData map with values for all required attributes
527 * @param {object} callback Result callback map.
528 * @param {onFailure} callback.onFailure Called on any error.
529 * @param {mfaRequired} callback.mfaRequired MFA code required to continue.
530 * @param {customChallenge} callback.customChallenge Custom challenge
531 * response required to continue.
532 * @param {authSuccess} callback.onSuccess Called on success with the new session.
533 * @param {ClientMetadata} clientMetadata object which is passed from client to Cognito Lambda trigger
534 * @returns {void}
535 */
536 ;
537
538 _proto.completeNewPasswordChallenge = function completeNewPasswordChallenge(newPassword, requiredAttributeData, callback, clientMetadata) {
539 var _this5 = this;
540
541 if (!newPassword) {
542 return callback.onFailure(new Error('New password is required.'));
543 }
544
545 var authenticationHelper = new AuthenticationHelper(this.pool.getUserPoolId().split('_')[1]);
546 var userAttributesPrefix = authenticationHelper.getNewPasswordRequiredChallengeUserAttributePrefix();
547 var finalUserAttributes = {};
548
549 if (requiredAttributeData) {
550 Object.keys(requiredAttributeData).forEach(function (key) {
551 finalUserAttributes[userAttributesPrefix + key] = requiredAttributeData[key];
552 });
553 }
554
555 finalUserAttributes.NEW_PASSWORD = newPassword;
556 finalUserAttributes.USERNAME = this.username;
557 var jsonReq = {
558 ChallengeName: 'NEW_PASSWORD_REQUIRED',
559 ClientId: this.pool.getClientId(),
560 ChallengeResponses: finalUserAttributes,
561 Session: this.Session,
562 ClientMetadata: clientMetadata
563 };
564
565 if (this.getUserContextData()) {
566 jsonReq.UserContextData = this.getUserContextData();
567 }
568
569 this.client.request('RespondToAuthChallenge', jsonReq, function (errAuthenticate, dataAuthenticate) {
570 if (errAuthenticate) {
571 return callback.onFailure(errAuthenticate);
572 }
573
574 return _this5.authenticateUserInternal(dataAuthenticate, authenticationHelper, callback);
575 });
576 return undefined;
577 }
578 /**
579 * This is used to get a session using device authentication. It is called at the end of user
580 * authentication
581 *
582 * @param {object} callback Result callback map.
583 * @param {onFailure} callback.onFailure Called on any error.
584 * @param {authSuccess} callback.onSuccess Called on success with the new session.
585 * @param {ClientMetadata} clientMetadata object which is passed from client to Cognito Lambda trigger
586 * @returns {void}
587 * @private
588 */
589 ;
590
591 _proto.getDeviceResponse = function getDeviceResponse(callback, clientMetadata) {
592 var _this6 = this;
593
594 var authenticationHelper = new AuthenticationHelper(this.deviceGroupKey);
595 var dateHelper = new DateHelper();
596 var authParameters = {};
597 authParameters.USERNAME = this.username;
598 authParameters.DEVICE_KEY = this.deviceKey;
599 authenticationHelper.getLargeAValue(function (errAValue, aValue) {
600 // getLargeAValue callback start
601 if (errAValue) {
602 callback.onFailure(errAValue);
603 }
604
605 authParameters.SRP_A = aValue.toString(16);
606 var jsonReq = {
607 ChallengeName: 'DEVICE_SRP_AUTH',
608 ClientId: _this6.pool.getClientId(),
609 ChallengeResponses: authParameters,
610 ClientMetadata: clientMetadata
611 };
612
613 if (_this6.getUserContextData()) {
614 jsonReq.UserContextData = _this6.getUserContextData();
615 }
616
617 _this6.client.request('RespondToAuthChallenge', jsonReq, function (err, data) {
618 if (err) {
619 return callback.onFailure(err);
620 }
621
622 var challengeParameters = data.ChallengeParameters;
623 var serverBValue = new BigInteger(challengeParameters.SRP_B, 16);
624 var salt = new BigInteger(challengeParameters.SALT, 16);
625 authenticationHelper.getPasswordAuthenticationKey(_this6.deviceKey, _this6.randomPassword, serverBValue, salt, function (errHkdf, hkdf) {
626 // getPasswordAuthenticationKey callback start
627 if (errHkdf) {
628 return callback.onFailure(errHkdf);
629 }
630
631 var dateNow = dateHelper.getNowString();
632 var message = CryptoJS.lib.WordArray.create(Buffer.concat([Buffer.from(_this6.deviceGroupKey, 'utf8'), Buffer.from(_this6.deviceKey, 'utf8'), Buffer.from(challengeParameters.SECRET_BLOCK, 'base64'), Buffer.from(dateNow, 'utf8')]));
633 var key = CryptoJS.lib.WordArray.create(hkdf);
634 var signatureString = Base64.stringify(HmacSHA256(message, key));
635 var challengeResponses = {};
636 challengeResponses.USERNAME = _this6.username;
637 challengeResponses.PASSWORD_CLAIM_SECRET_BLOCK = challengeParameters.SECRET_BLOCK;
638 challengeResponses.TIMESTAMP = dateNow;
639 challengeResponses.PASSWORD_CLAIM_SIGNATURE = signatureString;
640 challengeResponses.DEVICE_KEY = _this6.deviceKey;
641 var jsonReqResp = {
642 ChallengeName: 'DEVICE_PASSWORD_VERIFIER',
643 ClientId: _this6.pool.getClientId(),
644 ChallengeResponses: challengeResponses,
645 Session: data.Session
646 };
647
648 if (_this6.getUserContextData()) {
649 jsonReqResp.UserContextData = _this6.getUserContextData();
650 }
651
652 _this6.client.request('RespondToAuthChallenge', jsonReqResp, function (errAuthenticate, dataAuthenticate) {
653 if (errAuthenticate) {
654 return callback.onFailure(errAuthenticate);
655 }
656
657 _this6.signInUserSession = _this6.getCognitoUserSession(dataAuthenticate.AuthenticationResult);
658
659 _this6.cacheTokens();
660
661 return callback.onSuccess(_this6.signInUserSession);
662 });
663
664 return undefined; // getPasswordAuthenticationKey callback end
665 });
666 return undefined;
667 }); // getLargeAValue callback end
668
669 });
670 }
671 /**
672 * This is used for a certain user to confirm the registration by using a confirmation code
673 * @param {string} confirmationCode Code entered by user.
674 * @param {bool} forceAliasCreation Allow migrating from an existing email / phone number.
675 * @param {nodeCallback<string>} callback Called on success or error.
676 * @param {ClientMetadata} clientMetadata object which is passed from client to Cognito Lambda trigger
677 * @returns {void}
678 */
679 ;
680
681 _proto.confirmRegistration = function confirmRegistration(confirmationCode, forceAliasCreation, callback, clientMetadata) {
682 var jsonReq = {
683 ClientId: this.pool.getClientId(),
684 ConfirmationCode: confirmationCode,
685 Username: this.username,
686 ForceAliasCreation: forceAliasCreation,
687 ClientMetadata: clientMetadata
688 };
689
690 if (this.getUserContextData()) {
691 jsonReq.UserContextData = this.getUserContextData();
692 }
693
694 this.client.request('ConfirmSignUp', jsonReq, function (err) {
695 if (err) {
696 return callback(err, null);
697 }
698
699 return callback(null, 'SUCCESS');
700 });
701 }
702 /**
703 * This is used by the user once he has the responses to a custom challenge
704 * @param {string} answerChallenge The custom challenge answer.
705 * @param {object} callback Result callback map.
706 * @param {onFailure} callback.onFailure Called on any error.
707 * @param {customChallenge} callback.customChallenge
708 * Custom challenge response required to continue.
709 * @param {authSuccess} callback.onSuccess Called on success with the new session.
710 * @param {ClientMetadata} clientMetadata object which is passed from client to Cognito Lambda trigger
711 * @returns {void}
712 */
713 ;
714
715 _proto.sendCustomChallengeAnswer = function sendCustomChallengeAnswer(answerChallenge, callback, clientMetadata) {
716 var _this7 = this;
717
718 var challengeResponses = {};
719 challengeResponses.USERNAME = this.username;
720 challengeResponses.ANSWER = answerChallenge;
721 var authenticationHelper = new AuthenticationHelper(this.pool.getUserPoolId().split('_')[1]);
722 this.getCachedDeviceKeyAndPassword();
723
724 if (this.deviceKey != null) {
725 challengeResponses.DEVICE_KEY = this.deviceKey;
726 }
727
728 var jsonReq = {
729 ChallengeName: 'CUSTOM_CHALLENGE',
730 ChallengeResponses: challengeResponses,
731 ClientId: this.pool.getClientId(),
732 Session: this.Session,
733 ClientMetadata: clientMetadata
734 };
735
736 if (this.getUserContextData()) {
737 jsonReq.UserContextData = this.getUserContextData();
738 }
739
740 this.client.request('RespondToAuthChallenge', jsonReq, function (err, data) {
741 if (err) {
742 return callback.onFailure(err);
743 }
744
745 return _this7.authenticateUserInternal(data, authenticationHelper, callback);
746 });
747 }
748 /**
749 * This is used by the user once he has an MFA code
750 * @param {string} confirmationCode The MFA code entered by the user.
751 * @param {object} callback Result callback map.
752 * @param {string} mfaType The mfa we are replying to.
753 * @param {onFailure} callback.onFailure Called on any error.
754 * @param {authSuccess} callback.onSuccess Called on success with the new session.
755 * @param {ClientMetadata} clientMetadata object which is passed from client to Cognito Lambda trigger
756 * @returns {void}
757 */
758 ;
759
760 _proto.sendMFACode = function sendMFACode(confirmationCode, callback, mfaType, clientMetadata) {
761 var _this8 = this;
762
763 var challengeResponses = {};
764 challengeResponses.USERNAME = this.username;
765 challengeResponses.SMS_MFA_CODE = confirmationCode;
766 var mfaTypeSelection = mfaType || 'SMS_MFA';
767
768 if (mfaTypeSelection === 'SOFTWARE_TOKEN_MFA') {
769 challengeResponses.SOFTWARE_TOKEN_MFA_CODE = confirmationCode;
770 }
771
772 if (this.deviceKey != null) {
773 challengeResponses.DEVICE_KEY = this.deviceKey;
774 }
775
776 var jsonReq = {
777 ChallengeName: mfaTypeSelection,
778 ChallengeResponses: challengeResponses,
779 ClientId: this.pool.getClientId(),
780 Session: this.Session,
781 ClientMetadata: clientMetadata
782 };
783
784 if (this.getUserContextData()) {
785 jsonReq.UserContextData = this.getUserContextData();
786 }
787
788 this.client.request('RespondToAuthChallenge', jsonReq, function (err, dataAuthenticate) {
789 if (err) {
790 return callback.onFailure(err);
791 }
792
793 var challengeName = dataAuthenticate.ChallengeName;
794
795 if (challengeName === 'DEVICE_SRP_AUTH') {
796 _this8.getDeviceResponse(callback);
797
798 return undefined;
799 }
800
801 _this8.signInUserSession = _this8.getCognitoUserSession(dataAuthenticate.AuthenticationResult);
802
803 _this8.cacheTokens();
804
805 if (dataAuthenticate.AuthenticationResult.NewDeviceMetadata == null) {
806 return callback.onSuccess(_this8.signInUserSession);
807 }
808
809 var authenticationHelper = new AuthenticationHelper(_this8.pool.getUserPoolId().split('_')[1]);
810 authenticationHelper.generateHashDevice(dataAuthenticate.AuthenticationResult.NewDeviceMetadata.DeviceGroupKey, dataAuthenticate.AuthenticationResult.NewDeviceMetadata.DeviceKey, function (errGenHash) {
811 if (errGenHash) {
812 return callback.onFailure(errGenHash);
813 }
814
815 var deviceSecretVerifierConfig = {
816 Salt: Buffer.from(authenticationHelper.getSaltDevices(), 'hex').toString('base64'),
817 PasswordVerifier: Buffer.from(authenticationHelper.getVerifierDevices(), 'hex').toString('base64')
818 };
819 _this8.verifierDevices = deviceSecretVerifierConfig.PasswordVerifier;
820 _this8.deviceGroupKey = dataAuthenticate.AuthenticationResult.NewDeviceMetadata.DeviceGroupKey;
821 _this8.randomPassword = authenticationHelper.getRandomPassword();
822
823 _this8.client.request('ConfirmDevice', {
824 DeviceKey: dataAuthenticate.AuthenticationResult.NewDeviceMetadata.DeviceKey,
825 AccessToken: _this8.signInUserSession.getAccessToken().getJwtToken(),
826 DeviceSecretVerifierConfig: deviceSecretVerifierConfig,
827 DeviceName: userAgent
828 }, function (errConfirm, dataConfirm) {
829 if (errConfirm) {
830 return callback.onFailure(errConfirm);
831 }
832
833 _this8.deviceKey = dataAuthenticate.AuthenticationResult.NewDeviceMetadata.DeviceKey;
834
835 _this8.cacheDeviceKeyAndPassword();
836
837 if (dataConfirm.UserConfirmationNecessary === true) {
838 return callback.onSuccess(_this8.signInUserSession, dataConfirm.UserConfirmationNecessary);
839 }
840
841 return callback.onSuccess(_this8.signInUserSession);
842 });
843
844 return undefined;
845 });
846 return undefined;
847 });
848 }
849 /**
850 * This is used by an authenticated user to change the current password
851 * @param {string} oldUserPassword The current password.
852 * @param {string} newUserPassword The requested new password.
853 * @param {nodeCallback<string>} callback Called on success or error.
854 * @param {ClientMetadata} clientMetadata object which is passed from client to Cognito Lambda trigger
855 * @returns {void}
856 */
857 ;
858
859 _proto.changePassword = function changePassword(oldUserPassword, newUserPassword, callback, clientMetadata) {
860 if (!(this.signInUserSession != null && this.signInUserSession.isValid())) {
861 return callback(new Error('User is not authenticated'), null);
862 }
863
864 this.client.request('ChangePassword', {
865 PreviousPassword: oldUserPassword,
866 ProposedPassword: newUserPassword,
867 AccessToken: this.signInUserSession.getAccessToken().getJwtToken(),
868 ClientMetadata: clientMetadata
869 }, function (err) {
870 if (err) {
871 return callback(err, null);
872 }
873
874 return callback(null, 'SUCCESS');
875 });
876 return undefined;
877 }
878 /**
879 * This is used by an authenticated user to enable MFA for itself
880 * @deprecated
881 * @param {nodeCallback<string>} callback Called on success or error.
882 * @returns {void}
883 */
884 ;
885
886 _proto.enableMFA = function enableMFA(callback) {
887 if (this.signInUserSession == null || !this.signInUserSession.isValid()) {
888 return callback(new Error('User is not authenticated'), null);
889 }
890
891 var mfaOptions = [];
892 var mfaEnabled = {
893 DeliveryMedium: 'SMS',
894 AttributeName: 'phone_number'
895 };
896 mfaOptions.push(mfaEnabled);
897 this.client.request('SetUserSettings', {
898 MFAOptions: mfaOptions,
899 AccessToken: this.signInUserSession.getAccessToken().getJwtToken()
900 }, function (err) {
901 if (err) {
902 return callback(err, null);
903 }
904
905 return callback(null, 'SUCCESS');
906 });
907 return undefined;
908 }
909 /**
910 * This is used by an authenticated user to enable MFA for itself
911 * @param {IMfaSettings} smsMfaSettings the sms mfa settings
912 * @param {IMFASettings} softwareTokenMfaSettings the software token mfa settings
913 * @param {nodeCallback<string>} callback Called on success or error.
914 * @returns {void}
915 */
916 ;
917
918 _proto.setUserMfaPreference = function setUserMfaPreference(smsMfaSettings, softwareTokenMfaSettings, callback) {
919 if (this.signInUserSession == null || !this.signInUserSession.isValid()) {
920 return callback(new Error('User is not authenticated'), null);
921 }
922
923 this.client.request('SetUserMFAPreference', {
924 SMSMfaSettings: smsMfaSettings,
925 SoftwareTokenMfaSettings: softwareTokenMfaSettings,
926 AccessToken: this.signInUserSession.getAccessToken().getJwtToken()
927 }, function (err) {
928 if (err) {
929 return callback(err, null);
930 }
931
932 return callback(null, 'SUCCESS');
933 });
934 return undefined;
935 }
936 /**
937 * This is used by an authenticated user to disable MFA for itself
938 * @deprecated
939 * @param {nodeCallback<string>} callback Called on success or error.
940 * @returns {void}
941 */
942 ;
943
944 _proto.disableMFA = function disableMFA(callback) {
945 if (this.signInUserSession == null || !this.signInUserSession.isValid()) {
946 return callback(new Error('User is not authenticated'), null);
947 }
948
949 var mfaOptions = [];
950 this.client.request('SetUserSettings', {
951 MFAOptions: mfaOptions,
952 AccessToken: this.signInUserSession.getAccessToken().getJwtToken()
953 }, function (err) {
954 if (err) {
955 return callback(err, null);
956 }
957
958 return callback(null, 'SUCCESS');
959 });
960 return undefined;
961 }
962 /**
963 * This is used by an authenticated user to delete itself
964 * @param {nodeCallback<string>} callback Called on success or error.
965 * @param {ClientMetadata} clientMetadata object which is passed from client to Cognito Lambda trigger
966 * @returns {void}
967 */
968 ;
969
970 _proto.deleteUser = function deleteUser(callback, clientMetadata) {
971 var _this9 = this;
972
973 if (this.signInUserSession == null || !this.signInUserSession.isValid()) {
974 return callback(new Error('User is not authenticated'), null);
975 }
976
977 this.client.request('DeleteUser', {
978 AccessToken: this.signInUserSession.getAccessToken().getJwtToken(),
979 ClientMetadata: clientMetadata
980 }, function (err) {
981 if (err) {
982 return callback(err, null);
983 }
984
985 _this9.clearCachedUser();
986
987 return callback(null, 'SUCCESS');
988 });
989 return undefined;
990 }
991 /**
992 * @typedef {CognitoUserAttribute | { Name:string, Value:string }} AttributeArg
993 */
994
995 /**
996 * This is used by an authenticated user to change a list of attributes
997 * @param {AttributeArg[]} attributes A list of the new user attributes.
998 * @param {nodeCallback<string>} callback Called on success or error.
999 * @param {ClientMetadata} clientMetadata object which is passed from client to Cognito Lambda trigger
1000 * @returns {void}
1001 */
1002 ;
1003
1004 _proto.updateAttributes = function updateAttributes(attributes, callback, clientMetadata) {
1005 var _this10 = this;
1006
1007 if (this.signInUserSession == null || !this.signInUserSession.isValid()) {
1008 return callback(new Error('User is not authenticated'), null);
1009 }
1010
1011 this.client.request('UpdateUserAttributes', {
1012 AccessToken: this.signInUserSession.getAccessToken().getJwtToken(),
1013 UserAttributes: attributes,
1014 ClientMetadata: clientMetadata
1015 }, function (err) {
1016 if (err) {
1017 return callback(err, null);
1018 } // update cached user
1019
1020
1021 return _this10.getUserData(function () {
1022 return callback(null, 'SUCCESS');
1023 }, {
1024 bypassCache: true
1025 });
1026 });
1027 return undefined;
1028 }
1029 /**
1030 * This is used by an authenticated user to get a list of attributes
1031 * @param {nodeCallback<CognitoUserAttribute[]>} callback Called on success or error.
1032 * @returns {void}
1033 */
1034 ;
1035
1036 _proto.getUserAttributes = function getUserAttributes(callback) {
1037 if (!(this.signInUserSession != null && this.signInUserSession.isValid())) {
1038 return callback(new Error('User is not authenticated'), null);
1039 }
1040
1041 this.client.request('GetUser', {
1042 AccessToken: this.signInUserSession.getAccessToken().getJwtToken()
1043 }, function (err, userData) {
1044 if (err) {
1045 return callback(err, null);
1046 }
1047
1048 var attributeList = [];
1049
1050 for (var i = 0; i < userData.UserAttributes.length; i++) {
1051 var attribute = {
1052 Name: userData.UserAttributes[i].Name,
1053 Value: userData.UserAttributes[i].Value
1054 };
1055 var userAttribute = new CognitoUserAttribute(attribute);
1056 attributeList.push(userAttribute);
1057 }
1058
1059 return callback(null, attributeList);
1060 });
1061 return undefined;
1062 }
1063 /**
1064 * This is used by an authenticated user to get the MFAOptions
1065 * @param {nodeCallback<MFAOptions>} callback Called on success or error.
1066 * @returns {void}
1067 */
1068 ;
1069
1070 _proto.getMFAOptions = function getMFAOptions(callback) {
1071 if (!(this.signInUserSession != null && this.signInUserSession.isValid())) {
1072 return callback(new Error('User is not authenticated'), null);
1073 }
1074
1075 this.client.request('GetUser', {
1076 AccessToken: this.signInUserSession.getAccessToken().getJwtToken()
1077 }, function (err, userData) {
1078 if (err) {
1079 return callback(err, null);
1080 }
1081
1082 return callback(null, userData.MFAOptions);
1083 });
1084 return undefined;
1085 }
1086 /**
1087 * PRIVATE ONLY: This is an internal only method and should not
1088 * be directly called by the consumers.
1089 */
1090 ;
1091
1092 _proto.createGetUserRequest = function createGetUserRequest() {
1093 return this.client.promisifyRequest('GetUser', {
1094 AccessToken: this.signInUserSession.getAccessToken().getJwtToken()
1095 });
1096 }
1097 /**
1098 * PRIVATE ONLY: This is an internal only method and should not
1099 * be directly called by the consumers.
1100 */
1101 ;
1102
1103 _proto.refreshSessionIfPossible = function refreshSessionIfPossible() {
1104 var _this11 = this;
1105
1106 // best effort, if not possible
1107 return new Promise(function (resolve) {
1108 var refresh = _this11.signInUserSession.getRefreshToken();
1109
1110 if (refresh && refresh.getToken()) {
1111 _this11.refreshSession(refresh, resolve);
1112 } else {
1113 resolve();
1114 }
1115 });
1116 }
1117 /**
1118 * This is used by an authenticated users to get the userData
1119 * @param {nodeCallback<UserData>} callback Called on success or error.
1120 * @param {GetUserDataOptions} params
1121 * @returns {void}
1122 */
1123 ;
1124
1125 _proto.getUserData = function getUserData(callback, params) {
1126 var _this12 = this;
1127
1128 if (!(this.signInUserSession != null && this.signInUserSession.isValid())) {
1129 this.clearCachedUserData();
1130 return callback(new Error('User is not authenticated'), null);
1131 }
1132
1133 var userData = this.getUserDataFromCache();
1134
1135 if (!userData) {
1136 this.fetchUserData().then(function (data) {
1137 callback(null, data);
1138 })["catch"](callback);
1139 return;
1140 }
1141
1142 if (this.isFetchUserDataAndTokenRequired(params)) {
1143 this.fetchUserData().then(function (data) {
1144 return _this12.refreshSessionIfPossible().then(function () {
1145 return data;
1146 });
1147 }).then(function (data) {
1148 return callback(null, data);
1149 })["catch"](callback);
1150 return;
1151 }
1152
1153 try {
1154 callback(null, JSON.parse(userData));
1155 return;
1156 } catch (err) {
1157 this.clearCachedUserData();
1158 callback(err, null);
1159 return;
1160 }
1161 }
1162 /**
1163 *
1164 * PRIVATE ONLY: This is an internal only method and should not
1165 * be directly called by the consumers.
1166 */
1167 ;
1168
1169 _proto.getUserDataFromCache = function getUserDataFromCache() {
1170 var userData = this.storage.getItem(this.userDataKey);
1171 return userData;
1172 }
1173 /**
1174 *
1175 * PRIVATE ONLY: This is an internal only method and should not
1176 * be directly called by the consumers.
1177 */
1178 ;
1179
1180 _proto.isFetchUserDataAndTokenRequired = function isFetchUserDataAndTokenRequired(params) {
1181 var _ref = params || {},
1182 _ref$bypassCache = _ref.bypassCache,
1183 bypassCache = _ref$bypassCache === void 0 ? false : _ref$bypassCache;
1184
1185 return bypassCache;
1186 }
1187 /**
1188 *
1189 * PRIVATE ONLY: This is an internal only method and should not
1190 * be directly called by the consumers.
1191 */
1192 ;
1193
1194 _proto.fetchUserData = function fetchUserData() {
1195 var _this13 = this;
1196
1197 return this.createGetUserRequest().then(function (data) {
1198 _this13.cacheUserData(data);
1199
1200 return data;
1201 });
1202 }
1203 /**
1204 * This is used by an authenticated user to delete a list of attributes
1205 * @param {string[]} attributeList Names of the attributes to delete.
1206 * @param {nodeCallback<string>} callback Called on success or error.
1207 * @returns {void}
1208 */
1209 ;
1210
1211 _proto.deleteAttributes = function deleteAttributes(attributeList, callback) {
1212 if (!(this.signInUserSession != null && this.signInUserSession.isValid())) {
1213 return callback(new Error('User is not authenticated'), null);
1214 }
1215
1216 this.client.request('DeleteUserAttributes', {
1217 UserAttributeNames: attributeList,
1218 AccessToken: this.signInUserSession.getAccessToken().getJwtToken()
1219 }, function (err) {
1220 if (err) {
1221 return callback(err, null);
1222 }
1223
1224 return callback(null, 'SUCCESS');
1225 });
1226 return undefined;
1227 }
1228 /**
1229 * This is used by a user to resend a confirmation code
1230 * @param {nodeCallback<string>} callback Called on success or error.
1231 * @param {ClientMetadata} clientMetadata object which is passed from client to Cognito Lambda trigger
1232 * @returns {void}
1233 */
1234 ;
1235
1236 _proto.resendConfirmationCode = function resendConfirmationCode(callback, clientMetadata) {
1237 var jsonReq = {
1238 ClientId: this.pool.getClientId(),
1239 Username: this.username,
1240 ClientMetadata: clientMetadata
1241 };
1242 this.client.request('ResendConfirmationCode', jsonReq, function (err, result) {
1243 if (err) {
1244 return callback(err, null);
1245 }
1246
1247 return callback(null, result);
1248 });
1249 }
1250 /**
1251 * This is used to get a session, either from the session object
1252 * or from the local storage, or by using a refresh token
1253 *
1254 * @param {nodeCallback<CognitoUserSession>} callback Called on success or error.
1255 * @returns {void}
1256 */
1257 ;
1258
1259 _proto.getSession = function getSession(callback) {
1260 if (this.username == null) {
1261 return callback(new Error('Username is null. Cannot retrieve a new session'), null);
1262 }
1263
1264 if (this.signInUserSession != null && this.signInUserSession.isValid()) {
1265 return callback(null, this.signInUserSession);
1266 }
1267
1268 var keyPrefix = "CognitoIdentityServiceProvider." + this.pool.getClientId() + "." + this.username;
1269 var idTokenKey = keyPrefix + ".idToken";
1270 var accessTokenKey = keyPrefix + ".accessToken";
1271 var refreshTokenKey = keyPrefix + ".refreshToken";
1272 var clockDriftKey = keyPrefix + ".clockDrift";
1273
1274 if (this.storage.getItem(idTokenKey)) {
1275 var idToken = new CognitoIdToken({
1276 IdToken: this.storage.getItem(idTokenKey)
1277 });
1278 var accessToken = new CognitoAccessToken({
1279 AccessToken: this.storage.getItem(accessTokenKey)
1280 });
1281 var refreshToken = new CognitoRefreshToken({
1282 RefreshToken: this.storage.getItem(refreshTokenKey)
1283 });
1284 var clockDrift = parseInt(this.storage.getItem(clockDriftKey), 0) || 0;
1285 var sessionData = {
1286 IdToken: idToken,
1287 AccessToken: accessToken,
1288 RefreshToken: refreshToken,
1289 ClockDrift: clockDrift
1290 };
1291 var cachedSession = new CognitoUserSession(sessionData);
1292
1293 if (cachedSession.isValid()) {
1294 this.signInUserSession = cachedSession;
1295 return callback(null, this.signInUserSession);
1296 }
1297
1298 if (!refreshToken.getToken()) {
1299 return callback(new Error('Cannot retrieve a new session. Please authenticate.'), null);
1300 }
1301
1302 this.refreshSession(refreshToken, callback);
1303 } else {
1304 callback(new Error('Local storage is missing an ID Token, Please authenticate'), null);
1305 }
1306
1307 return undefined;
1308 }
1309 /**
1310 * This uses the refreshToken to retrieve a new session
1311 * @param {CognitoRefreshToken} refreshToken A previous session's refresh token.
1312 * @param {nodeCallback<CognitoUserSession>} callback Called on success or error.
1313 * @param {ClientMetadata} clientMetadata object which is passed from client to Cognito Lambda trigger
1314 * @returns {void}
1315 */
1316 ;
1317
1318 _proto.refreshSession = function refreshSession(refreshToken, callback, clientMetadata) {
1319 var _this14 = this;
1320
1321 var authParameters = {};
1322 authParameters.REFRESH_TOKEN = refreshToken.getToken();
1323 var keyPrefix = "CognitoIdentityServiceProvider." + this.pool.getClientId();
1324 var lastUserKey = keyPrefix + ".LastAuthUser";
1325
1326 if (this.storage.getItem(lastUserKey)) {
1327 this.username = this.storage.getItem(lastUserKey);
1328 var deviceKeyKey = keyPrefix + "." + this.username + ".deviceKey";
1329 this.deviceKey = this.storage.getItem(deviceKeyKey);
1330 authParameters.DEVICE_KEY = this.deviceKey;
1331 }
1332
1333 var jsonReq = {
1334 ClientId: this.pool.getClientId(),
1335 AuthFlow: 'REFRESH_TOKEN_AUTH',
1336 AuthParameters: authParameters,
1337 ClientMetadata: clientMetadata
1338 };
1339
1340 if (this.getUserContextData()) {
1341 jsonReq.UserContextData = this.getUserContextData();
1342 }
1343
1344 this.client.request('InitiateAuth', jsonReq, function (err, authResult) {
1345 if (err) {
1346 if (err.code === 'NotAuthorizedException') {
1347 _this14.clearCachedUser();
1348 }
1349
1350 return callback(err, null);
1351 }
1352
1353 if (authResult) {
1354 var authenticationResult = authResult.AuthenticationResult;
1355
1356 if (!Object.prototype.hasOwnProperty.call(authenticationResult, 'RefreshToken')) {
1357 authenticationResult.RefreshToken = refreshToken.getToken();
1358 }
1359
1360 _this14.signInUserSession = _this14.getCognitoUserSession(authenticationResult);
1361
1362 _this14.cacheTokens();
1363
1364 return callback(null, _this14.signInUserSession);
1365 }
1366
1367 return undefined;
1368 });
1369 }
1370 /**
1371 * This is used to save the session tokens to local storage
1372 * @returns {void}
1373 */
1374 ;
1375
1376 _proto.cacheTokens = function cacheTokens() {
1377 var keyPrefix = "CognitoIdentityServiceProvider." + this.pool.getClientId();
1378 var idTokenKey = keyPrefix + "." + this.username + ".idToken";
1379 var accessTokenKey = keyPrefix + "." + this.username + ".accessToken";
1380 var refreshTokenKey = keyPrefix + "." + this.username + ".refreshToken";
1381 var clockDriftKey = keyPrefix + "." + this.username + ".clockDrift";
1382 var lastUserKey = keyPrefix + ".LastAuthUser";
1383 this.storage.setItem(idTokenKey, this.signInUserSession.getIdToken().getJwtToken());
1384 this.storage.setItem(accessTokenKey, this.signInUserSession.getAccessToken().getJwtToken());
1385 this.storage.setItem(refreshTokenKey, this.signInUserSession.getRefreshToken().getToken());
1386 this.storage.setItem(clockDriftKey, "" + this.signInUserSession.getClockDrift());
1387 this.storage.setItem(lastUserKey, this.username);
1388 }
1389 /**
1390 * This is to cache user data
1391 */
1392 ;
1393
1394 _proto.cacheUserData = function cacheUserData(userData) {
1395 this.storage.setItem(this.userDataKey, JSON.stringify(userData));
1396 }
1397 /**
1398 * This is to remove cached user data
1399 */
1400 ;
1401
1402 _proto.clearCachedUserData = function clearCachedUserData() {
1403 this.storage.removeItem(this.userDataKey);
1404 };
1405
1406 _proto.clearCachedUser = function clearCachedUser() {
1407 this.clearCachedTokens();
1408 this.clearCachedUserData();
1409 }
1410 /**
1411 * This is used to cache the device key and device group and device password
1412 * @returns {void}
1413 */
1414 ;
1415
1416 _proto.cacheDeviceKeyAndPassword = function cacheDeviceKeyAndPassword() {
1417 var keyPrefix = "CognitoIdentityServiceProvider." + this.pool.getClientId() + "." + this.username;
1418 var deviceKeyKey = keyPrefix + ".deviceKey";
1419 var randomPasswordKey = keyPrefix + ".randomPasswordKey";
1420 var deviceGroupKeyKey = keyPrefix + ".deviceGroupKey";
1421 this.storage.setItem(deviceKeyKey, this.deviceKey);
1422 this.storage.setItem(randomPasswordKey, this.randomPassword);
1423 this.storage.setItem(deviceGroupKeyKey, this.deviceGroupKey);
1424 }
1425 /**
1426 * This is used to get current device key and device group and device password
1427 * @returns {void}
1428 */
1429 ;
1430
1431 _proto.getCachedDeviceKeyAndPassword = function getCachedDeviceKeyAndPassword() {
1432 var keyPrefix = "CognitoIdentityServiceProvider." + this.pool.getClientId() + "." + this.username;
1433 var deviceKeyKey = keyPrefix + ".deviceKey";
1434 var randomPasswordKey = keyPrefix + ".randomPasswordKey";
1435 var deviceGroupKeyKey = keyPrefix + ".deviceGroupKey";
1436
1437 if (this.storage.getItem(deviceKeyKey)) {
1438 this.deviceKey = this.storage.getItem(deviceKeyKey);
1439 this.randomPassword = this.storage.getItem(randomPasswordKey);
1440 this.deviceGroupKey = this.storage.getItem(deviceGroupKeyKey);
1441 }
1442 }
1443 /**
1444 * This is used to clear the device key info from local storage
1445 * @returns {void}
1446 */
1447 ;
1448
1449 _proto.clearCachedDeviceKeyAndPassword = function clearCachedDeviceKeyAndPassword() {
1450 var keyPrefix = "CognitoIdentityServiceProvider." + this.pool.getClientId() + "." + this.username;
1451 var deviceKeyKey = keyPrefix + ".deviceKey";
1452 var randomPasswordKey = keyPrefix + ".randomPasswordKey";
1453 var deviceGroupKeyKey = keyPrefix + ".deviceGroupKey";
1454 this.storage.removeItem(deviceKeyKey);
1455 this.storage.removeItem(randomPasswordKey);
1456 this.storage.removeItem(deviceGroupKeyKey);
1457 }
1458 /**
1459 * This is used to clear the session tokens from local storage
1460 * @returns {void}
1461 */
1462 ;
1463
1464 _proto.clearCachedTokens = function clearCachedTokens() {
1465 var keyPrefix = "CognitoIdentityServiceProvider." + this.pool.getClientId();
1466 var idTokenKey = keyPrefix + "." + this.username + ".idToken";
1467 var accessTokenKey = keyPrefix + "." + this.username + ".accessToken";
1468 var refreshTokenKey = keyPrefix + "." + this.username + ".refreshToken";
1469 var lastUserKey = keyPrefix + ".LastAuthUser";
1470 var clockDriftKey = keyPrefix + "." + this.username + ".clockDrift";
1471 this.storage.removeItem(idTokenKey);
1472 this.storage.removeItem(accessTokenKey);
1473 this.storage.removeItem(refreshTokenKey);
1474 this.storage.removeItem(lastUserKey);
1475 this.storage.removeItem(clockDriftKey);
1476 }
1477 /**
1478 * This is used to build a user session from tokens retrieved in the authentication result
1479 * @param {object} authResult Successful auth response from server.
1480 * @returns {CognitoUserSession} The new user session.
1481 * @private
1482 */
1483 ;
1484
1485 _proto.getCognitoUserSession = function getCognitoUserSession(authResult) {
1486 var idToken = new CognitoIdToken(authResult);
1487 var accessToken = new CognitoAccessToken(authResult);
1488 var refreshToken = new CognitoRefreshToken(authResult);
1489 var sessionData = {
1490 IdToken: idToken,
1491 AccessToken: accessToken,
1492 RefreshToken: refreshToken
1493 };
1494 return new CognitoUserSession(sessionData);
1495 }
1496 /**
1497 * This is used to initiate a forgot password request
1498 * @param {object} callback Result callback map.
1499 * @param {onFailure} callback.onFailure Called on any error.
1500 * @param {inputVerificationCode?} callback.inputVerificationCode
1501 * Optional callback raised instead of onSuccess with response data.
1502 * @param {onSuccess} callback.onSuccess Called on success.
1503 * @param {ClientMetadata} clientMetadata object which is passed from client to Cognito Lambda trigger
1504 * @returns {void}
1505 */
1506 ;
1507
1508 _proto.forgotPassword = function forgotPassword(callback, clientMetadata) {
1509 var jsonReq = {
1510 ClientId: this.pool.getClientId(),
1511 Username: this.username,
1512 ClientMetadata: clientMetadata
1513 };
1514
1515 if (this.getUserContextData()) {
1516 jsonReq.UserContextData = this.getUserContextData();
1517 }
1518
1519 this.client.request('ForgotPassword', jsonReq, function (err, data) {
1520 if (err) {
1521 return callback.onFailure(err);
1522 }
1523
1524 if (typeof callback.inputVerificationCode === 'function') {
1525 return callback.inputVerificationCode(data);
1526 }
1527
1528 return callback.onSuccess(data);
1529 });
1530 }
1531 /**
1532 * This is used to confirm a new password using a confirmationCode
1533 * @param {string} confirmationCode Code entered by user.
1534 * @param {string} newPassword Confirm new password.
1535 * @param {object} callback Result callback map.
1536 * @param {onFailure} callback.onFailure Called on any error.
1537 * @param {onSuccess<void>} callback.onSuccess Called on success.
1538 * @param {ClientMetadata} clientMetadata object which is passed from client to Cognito Lambda trigger
1539 * @returns {void}
1540 */
1541 ;
1542
1543 _proto.confirmPassword = function confirmPassword(confirmationCode, newPassword, callback, clientMetadata) {
1544 var jsonReq = {
1545 ClientId: this.pool.getClientId(),
1546 Username: this.username,
1547 ConfirmationCode: confirmationCode,
1548 Password: newPassword,
1549 ClientMetadata: clientMetadata
1550 };
1551
1552 if (this.getUserContextData()) {
1553 jsonReq.UserContextData = this.getUserContextData();
1554 }
1555
1556 this.client.request('ConfirmForgotPassword', jsonReq, function (err) {
1557 if (err) {
1558 return callback.onFailure(err);
1559 }
1560
1561 return callback.onSuccess();
1562 });
1563 }
1564 /**
1565 * This is used to initiate an attribute confirmation request
1566 * @param {string} attributeName User attribute that needs confirmation.
1567 * @param {object} callback Result callback map.
1568 * @param {onFailure} callback.onFailure Called on any error.
1569 * @param {inputVerificationCode} callback.inputVerificationCode Called on success.
1570 * @param {ClientMetadata} clientMetadata object which is passed from client to Cognito Lambda trigger
1571 * @returns {void}
1572 */
1573 ;
1574
1575 _proto.getAttributeVerificationCode = function getAttributeVerificationCode(attributeName, callback, clientMetadata) {
1576 if (this.signInUserSession == null || !this.signInUserSession.isValid()) {
1577 return callback.onFailure(new Error('User is not authenticated'));
1578 }
1579
1580 this.client.request('GetUserAttributeVerificationCode', {
1581 AttributeName: attributeName,
1582 AccessToken: this.signInUserSession.getAccessToken().getJwtToken(),
1583 ClientMetadata: clientMetadata
1584 }, function (err, data) {
1585 if (err) {
1586 return callback.onFailure(err);
1587 }
1588
1589 if (typeof callback.inputVerificationCode === 'function') {
1590 return callback.inputVerificationCode(data);
1591 }
1592
1593 return callback.onSuccess();
1594 });
1595 return undefined;
1596 }
1597 /**
1598 * This is used to confirm an attribute using a confirmation code
1599 * @param {string} attributeName Attribute being confirmed.
1600 * @param {string} confirmationCode Code entered by user.
1601 * @param {object} callback Result callback map.
1602 * @param {onFailure} callback.onFailure Called on any error.
1603 * @param {onSuccess<string>} callback.onSuccess Called on success.
1604 * @returns {void}
1605 */
1606 ;
1607
1608 _proto.verifyAttribute = function verifyAttribute(attributeName, confirmationCode, callback) {
1609 if (this.signInUserSession == null || !this.signInUserSession.isValid()) {
1610 return callback.onFailure(new Error('User is not authenticated'));
1611 }
1612
1613 this.client.request('VerifyUserAttribute', {
1614 AttributeName: attributeName,
1615 Code: confirmationCode,
1616 AccessToken: this.signInUserSession.getAccessToken().getJwtToken()
1617 }, function (err) {
1618 if (err) {
1619 return callback.onFailure(err);
1620 }
1621
1622 return callback.onSuccess('SUCCESS');
1623 });
1624 return undefined;
1625 }
1626 /**
1627 * This is used to get the device information using the current device key
1628 * @param {object} callback Result callback map.
1629 * @param {onFailure} callback.onFailure Called on any error.
1630 * @param {onSuccess<*>} callback.onSuccess Called on success with device data.
1631 * @returns {void}
1632 */
1633 ;
1634
1635 _proto.getDevice = function getDevice(callback) {
1636 if (this.signInUserSession == null || !this.signInUserSession.isValid()) {
1637 return callback.onFailure(new Error('User is not authenticated'));
1638 }
1639
1640 this.client.request('GetDevice', {
1641 AccessToken: this.signInUserSession.getAccessToken().getJwtToken(),
1642 DeviceKey: this.deviceKey
1643 }, function (err, data) {
1644 if (err) {
1645 return callback.onFailure(err);
1646 }
1647
1648 return callback.onSuccess(data);
1649 });
1650 return undefined;
1651 }
1652 /**
1653 * This is used to forget a specific device
1654 * @param {string} deviceKey Device key.
1655 * @param {object} callback Result callback map.
1656 * @param {onFailure} callback.onFailure Called on any error.
1657 * @param {onSuccess<string>} callback.onSuccess Called on success.
1658 * @returns {void}
1659 */
1660 ;
1661
1662 _proto.forgetSpecificDevice = function forgetSpecificDevice(deviceKey, callback) {
1663 if (this.signInUserSession == null || !this.signInUserSession.isValid()) {
1664 return callback.onFailure(new Error('User is not authenticated'));
1665 }
1666
1667 this.client.request('ForgetDevice', {
1668 AccessToken: this.signInUserSession.getAccessToken().getJwtToken(),
1669 DeviceKey: deviceKey
1670 }, function (err) {
1671 if (err) {
1672 return callback.onFailure(err);
1673 }
1674
1675 return callback.onSuccess('SUCCESS');
1676 });
1677 return undefined;
1678 }
1679 /**
1680 * This is used to forget the current device
1681 * @param {object} callback Result callback map.
1682 * @param {onFailure} callback.onFailure Called on any error.
1683 * @param {onSuccess<string>} callback.onSuccess Called on success.
1684 * @returns {void}
1685 */
1686 ;
1687
1688 _proto.forgetDevice = function forgetDevice(callback) {
1689 var _this15 = this;
1690
1691 this.forgetSpecificDevice(this.deviceKey, {
1692 onFailure: callback.onFailure,
1693 onSuccess: function onSuccess(result) {
1694 _this15.deviceKey = null;
1695 _this15.deviceGroupKey = null;
1696 _this15.randomPassword = null;
1697
1698 _this15.clearCachedDeviceKeyAndPassword();
1699
1700 return callback.onSuccess(result);
1701 }
1702 });
1703 }
1704 /**
1705 * This is used to set the device status as remembered
1706 * @param {object} callback Result callback map.
1707 * @param {onFailure} callback.onFailure Called on any error.
1708 * @param {onSuccess<string>} callback.onSuccess Called on success.
1709 * @returns {void}
1710 */
1711 ;
1712
1713 _proto.setDeviceStatusRemembered = function setDeviceStatusRemembered(callback) {
1714 if (this.signInUserSession == null || !this.signInUserSession.isValid()) {
1715 return callback.onFailure(new Error('User is not authenticated'));
1716 }
1717
1718 this.client.request('UpdateDeviceStatus', {
1719 AccessToken: this.signInUserSession.getAccessToken().getJwtToken(),
1720 DeviceKey: this.deviceKey,
1721 DeviceRememberedStatus: 'remembered'
1722 }, function (err) {
1723 if (err) {
1724 return callback.onFailure(err);
1725 }
1726
1727 return callback.onSuccess('SUCCESS');
1728 });
1729 return undefined;
1730 }
1731 /**
1732 * This is used to set the device status as not remembered
1733 * @param {object} callback Result callback map.
1734 * @param {onFailure} callback.onFailure Called on any error.
1735 * @param {onSuccess<string>} callback.onSuccess Called on success.
1736 * @returns {void}
1737 */
1738 ;
1739
1740 _proto.setDeviceStatusNotRemembered = function setDeviceStatusNotRemembered(callback) {
1741 if (this.signInUserSession == null || !this.signInUserSession.isValid()) {
1742 return callback.onFailure(new Error('User is not authenticated'));
1743 }
1744
1745 this.client.request('UpdateDeviceStatus', {
1746 AccessToken: this.signInUserSession.getAccessToken().getJwtToken(),
1747 DeviceKey: this.deviceKey,
1748 DeviceRememberedStatus: 'not_remembered'
1749 }, function (err) {
1750 if (err) {
1751 return callback.onFailure(err);
1752 }
1753
1754 return callback.onSuccess('SUCCESS');
1755 });
1756 return undefined;
1757 }
1758 /**
1759 * This is used to list all devices for a user
1760 *
1761 * @param {int} limit the number of devices returned in a call
1762 * @param {string | null} paginationToken the pagination token in case any was returned before
1763 * @param {object} callback Result callback map.
1764 * @param {onFailure} callback.onFailure Called on any error.
1765 * @param {onSuccess<*>} callback.onSuccess Called on success with device list.
1766 * @returns {void}
1767 */
1768 ;
1769
1770 _proto.listDevices = function listDevices(limit, paginationToken, callback) {
1771 if (this.signInUserSession == null || !this.signInUserSession.isValid()) {
1772 return callback.onFailure(new Error('User is not authenticated'));
1773 }
1774
1775 var requestParams = {
1776 AccessToken: this.signInUserSession.getAccessToken().getJwtToken(),
1777 Limit: limit
1778 };
1779
1780 if (paginationToken) {
1781 requestParams.PaginationToken = paginationToken;
1782 }
1783
1784 this.client.request('ListDevices', requestParams, function (err, data) {
1785 if (err) {
1786 return callback.onFailure(err);
1787 }
1788
1789 return callback.onSuccess(data);
1790 });
1791 return undefined;
1792 }
1793 /**
1794 * This is used to globally revoke all tokens issued to a user
1795 * @param {object} callback Result callback map.
1796 * @param {onFailure} callback.onFailure Called on any error.
1797 * @param {onSuccess<string>} callback.onSuccess Called on success.
1798 * @returns {void}
1799 */
1800 ;
1801
1802 _proto.globalSignOut = function globalSignOut(callback) {
1803 var _this16 = this;
1804
1805 if (this.signInUserSession == null || !this.signInUserSession.isValid()) {
1806 return callback.onFailure(new Error('User is not authenticated'));
1807 }
1808
1809 this.client.request('GlobalSignOut', {
1810 AccessToken: this.signInUserSession.getAccessToken().getJwtToken()
1811 }, function (err) {
1812 if (err) {
1813 return callback.onFailure(err);
1814 }
1815
1816 _this16.clearCachedUser();
1817
1818 return callback.onSuccess('SUCCESS');
1819 });
1820 return undefined;
1821 }
1822 /**
1823 * This is used for the user to signOut of the application and clear the cached tokens.
1824 * @returns {void}
1825 */
1826 ;
1827
1828 _proto.signOut = function signOut() {
1829 this.signInUserSession = null;
1830 this.clearCachedUser();
1831 }
1832 /**
1833 * This is used by a user trying to select a given MFA
1834 * @param {string} answerChallenge the mfa the user wants
1835 * @param {nodeCallback<string>} callback Called on success or error.
1836 * @returns {void}
1837 */
1838 ;
1839
1840 _proto.sendMFASelectionAnswer = function sendMFASelectionAnswer(answerChallenge, callback) {
1841 var _this17 = this;
1842
1843 var challengeResponses = {};
1844 challengeResponses.USERNAME = this.username;
1845 challengeResponses.ANSWER = answerChallenge;
1846 var jsonReq = {
1847 ChallengeName: 'SELECT_MFA_TYPE',
1848 ChallengeResponses: challengeResponses,
1849 ClientId: this.pool.getClientId(),
1850 Session: this.Session
1851 };
1852
1853 if (this.getUserContextData()) {
1854 jsonReq.UserContextData = this.getUserContextData();
1855 }
1856
1857 this.client.request('RespondToAuthChallenge', jsonReq, function (err, data) {
1858 if (err) {
1859 return callback.onFailure(err);
1860 }
1861
1862 _this17.Session = data.Session;
1863
1864 if (answerChallenge === 'SMS_MFA') {
1865 return callback.mfaRequired(data.ChallengeName, data.ChallengeParameters);
1866 }
1867
1868 if (answerChallenge === 'SOFTWARE_TOKEN_MFA') {
1869 return callback.totpRequired(data.ChallengeName, data.ChallengeParameters);
1870 }
1871
1872 return undefined;
1873 });
1874 }
1875 /**
1876 * This returns the user context data for advanced security feature.
1877 * @returns {void}
1878 */
1879 ;
1880
1881 _proto.getUserContextData = function getUserContextData() {
1882 var pool = this.pool;
1883 return pool.getUserContextData(this.username);
1884 }
1885 /**
1886 * This is used by an authenticated or a user trying to authenticate to associate a TOTP MFA
1887 * @param {nodeCallback<string>} callback Called on success or error.
1888 * @returns {void}
1889 */
1890 ;
1891
1892 _proto.associateSoftwareToken = function associateSoftwareToken(callback) {
1893 var _this18 = this;
1894
1895 if (!(this.signInUserSession != null && this.signInUserSession.isValid())) {
1896 this.client.request('AssociateSoftwareToken', {
1897 Session: this.Session
1898 }, function (err, data) {
1899 if (err) {
1900 return callback.onFailure(err);
1901 }
1902
1903 _this18.Session = data.Session;
1904 return callback.associateSecretCode(data.SecretCode);
1905 });
1906 } else {
1907 this.client.request('AssociateSoftwareToken', {
1908 AccessToken: this.signInUserSession.getAccessToken().getJwtToken()
1909 }, function (err, data) {
1910 if (err) {
1911 return callback.onFailure(err);
1912 }
1913
1914 return callback.associateSecretCode(data.SecretCode);
1915 });
1916 }
1917 }
1918 /**
1919 * This is used by an authenticated or a user trying to authenticate to verify a TOTP MFA
1920 * @param {string} totpCode The MFA code entered by the user.
1921 * @param {string} friendlyDeviceName The device name we are assigning to the device.
1922 * @param {nodeCallback<string>} callback Called on success or error.
1923 * @returns {void}
1924 */
1925 ;
1926
1927 _proto.verifySoftwareToken = function verifySoftwareToken(totpCode, friendlyDeviceName, callback) {
1928 var _this19 = this;
1929
1930 if (!(this.signInUserSession != null && this.signInUserSession.isValid())) {
1931 this.client.request('VerifySoftwareToken', {
1932 Session: this.Session,
1933 UserCode: totpCode,
1934 FriendlyDeviceName: friendlyDeviceName
1935 }, function (err, data) {
1936 if (err) {
1937 return callback.onFailure(err);
1938 }
1939
1940 _this19.Session = data.Session;
1941 var challengeResponses = {};
1942 challengeResponses.USERNAME = _this19.username;
1943 var jsonReq = {
1944 ChallengeName: 'MFA_SETUP',
1945 ClientId: _this19.pool.getClientId(),
1946 ChallengeResponses: challengeResponses,
1947 Session: _this19.Session
1948 };
1949
1950 if (_this19.getUserContextData()) {
1951 jsonReq.UserContextData = _this19.getUserContextData();
1952 }
1953
1954 _this19.client.request('RespondToAuthChallenge', jsonReq, function (errRespond, dataRespond) {
1955 if (errRespond) {
1956 return callback.onFailure(errRespond);
1957 }
1958
1959 _this19.signInUserSession = _this19.getCognitoUserSession(dataRespond.AuthenticationResult);
1960
1961 _this19.cacheTokens();
1962
1963 return callback.onSuccess(_this19.signInUserSession);
1964 });
1965
1966 return undefined;
1967 });
1968 } else {
1969 this.client.request('VerifySoftwareToken', {
1970 AccessToken: this.signInUserSession.getAccessToken().getJwtToken(),
1971 UserCode: totpCode,
1972 FriendlyDeviceName: friendlyDeviceName
1973 }, function (err, data) {
1974 if (err) {
1975 return callback.onFailure(err);
1976 }
1977
1978 return callback.onSuccess(data);
1979 });
1980 }
1981 };
1982
1983 return CognitoUser;
1984}();
1985
1986export { CognitoUser as default };
\No newline at end of file