From f6619033ed8dbe6e5e8f85a1fadb2bcf3555eb65 Mon Sep 17 00:00:00 2001 From: Ionut Trestian Date: Fri, 24 Nov 2017 23:13:18 +0000 Subject: [PATCH] Stashing changes --- README.md | 50 +++++++++++++++++++++++++++ src/CognitoUser.js | 77 +++++++++++++++++++++--------------------- src/CognitoUserPool.js | 32 +++++++++++------- 3 files changed, 107 insertions(+), 52 deletions(-) diff --git a/README.md b/README.md index 9aa7370e..67620f6c 100644 --- a/README.md +++ b/README.md @@ -704,6 +704,9 @@ Note that the inputVerificationCode method needs to be defined but does not need **Use case 26.** Using cookies to store cognito tokens +```javascript +``` + To use the CookieStorage you have to pass it in the constructor map of CognitoUserPool and CognitoUser (when constructed directly): ```js @@ -727,6 +730,53 @@ The CookieStorage object receives a map (data) in its constructor that may have * data.expires Cookie expiration (in days, default: 365) * data.secure Cookie secure flag (default: true) +**Use case 27.** Selecting the MFA method and authenticating using TOTP. + + var authenticationData = { + Username : 'username', + Password : 'password', + }; + var authenticationDetails = new AWSCognito.CognitoIdentityServiceProvider.AuthenticationDetails(authenticationData); + var poolData = { + UserPoolId : '...', // Your user pool id here + ClientId : '...' // Your client id here + }; + var userPool = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserPool(poolData); + var userData = { + Username : 'username', + Pool : userPool + }; + var cognitoUser = new AWSCognito.CognitoIdentityServiceProvider.CognitoUser(userData); + + cognitoUser.authenticateUser(authenticationDetails, { + onSuccess: function (result) { + console.log('access token + ' + result.getAccessToken().getJwtToken()); + }, + + onFailure: function(err) { + alert(err); + }, + + mfaSetup: function(challengeName, challengeParameters) { + cognitoUser.associateSoftwareToken(this); + }, + + associateSecretCode : function(secretCode) { + var challengeAnswer = prompt('Please input the TOTP code.' ,''); + cognitoUser.verifySoftwareToken(challengeAnswer, 'My TOTP device', this); + }, + + selectMFAType : function(challengeName, challengeParameters) { + var mfaType = prompt('Please select the MFA method.', ''); + cognitoUser.sendMFASelectionAnswer(mfaType, this); + }, + + totpRequired : function(secretCode) { + var challengeAnswer = prompt('Please input the TOTP code.' ,''); + cognitoUser.sendMFACode(challengeAnswer, this, 'SOFTWARE_TOKEN_MFA'); + } + }); + ## Network Configuration The Amazon Cognito Identity JavaScript SDK will make requests to the following endpoints * For Amazon Cognito Identity request handling: "https://cognito-idp.us-east-1.amazonaws.com" diff --git a/src/CognitoUser.js b/src/CognitoUser.js index f8131416..e8ee4479 100644 --- a/src/CognitoUser.js +++ b/src/CognitoUser.js @@ -640,8 +640,8 @@ export default class CognitoUser { const challengeResponses = {}; challengeResponses.USERNAME = this.username; challengeResponses.SMS_MFA_CODE = confirmationCode; - mfaType = mfaType || 'SMS_MFA'; - if (mfaType === 'SOFTWARE_TOKEN_MFA') { + const mfaTypeSelection = mfaType || 'SMS_MFA'; + if (mfaTypeSelection === 'SOFTWARE_TOKEN_MFA') { challengeResponses.SOFTWARE_TOKEN_MFA_CODE = confirmationCode; } @@ -650,7 +650,7 @@ export default class CognitoUser { } this.client.makeUnauthenticatedRequest('respondToAuthChallenge', { - ChallengeName: mfaType, + ChallengeName: mfaTypeSelection, ChallengeResponses: challengeResponses, ClientId: this.pool.getClientId(), Session: this.Session, @@ -779,23 +779,19 @@ export default class CognitoUser { /** * This is used by an authenticated user to enable MFA for himself + * @param {string[]} smsMfaSettings the sms mfa settings + * @param {string[]} softwareTokenMfaSettings the software token mfa settings * @param {nodeCallback} callback Called on success or error. * @returns {void} */ - setUserMfaPreference(callback) { + setUserMfaPreference(smsMfaSettings, softwareTokenMfaSettings, callback) { if (this.signInUserSession == null || !this.signInUserSession.isValid()) { return callback(new Error('User is not authenticated'), null); } - const mfaOptions = []; - const mfaEnabled = { - DeliveryMedium: 'SMS', - AttributeName: 'phone_number', - }; - mfaOptions.push(mfaEnabled); - - this.client.makeUnauthenticatedRequest('setUserSettings', { - MFAOptions: mfaOptions, + this.client.makeUnauthenticatedRequest('setUserMfaPreference', { + SMSMfaSettings: smsMfaSettings, + SoftwareTokenMfaSettings: softwareTokenMfaSettings, AccessToken: this.signInUserSession.getAccessToken().getJwtToken(), }, err => { if (err) { @@ -1467,7 +1463,7 @@ export default class CognitoUser { /** * This is used by a user trying to select a given MFA - * @param {string} the mfa the user wants + * @param {string} answerChallenge the mfa the user wants * @param {nodeCallback} callback Called on success or error. * @returns {void} */ @@ -1487,20 +1483,22 @@ export default class CognitoUser { return callback.onFailure(err); } this.Session = data.Session; - if (ANSWER === 'SMS_MFA') { - return callback.mfaRequired(challengeName, challengeParameters); + if (answerChallenge === 'SMS_MFA') { + return callback.mfaRequired(data.challengeName, data.challengeParameters); } - if (ANSWER === 'SOFTWARE_TOKEN_MFA') { - return callback.totpRequired(challengeName, challengeParameters); + if (answerChallenge === 'SOFTWARE_TOKEN_MFA') { + return callback.totpRequired(data.challengeName, data.challengeParameters); } + return undefined; }); } /** * This returns the user context data for advanced security feature. + * @returns {void} */ getUserContextData() { - var pool = this.pool; + const pool = this.pool; return pool.getUserContextData(this.username); } @@ -1511,9 +1509,8 @@ export default class CognitoUser { */ associateSoftwareToken(callback) { if (!(this.signInUserSession != null && this.signInUserSession.isValid())) { - console.log('calling associate software token') this.client.makeUnauthenticatedRequest('associateSoftwareToken', { - Session: this.Session + Session: this.Session, }, (err, data) => { if (err) { return callback.onFailure(err); @@ -1528,16 +1525,16 @@ export default class CognitoUser { if (err) { return callback.onFailure(err); } - return callback.associateSecretCode(data.SecretCode); + return callback.associateSecretCode(data.SecretCode); }); } } /** - * This is used by an authenticated or a user trying to authenticate to associate a TOTP MFA - * @param {nodeCallback} callback Called on success or error. + * This is used by an authenticated or a user trying to authenticate to associate a TOTP MFA * @param {string} totpCode The MFA code entered by the user. * @param {string} friendlyDeviceName The device name we are assigning to the device. + * @param {nodeCallback} callback Called on success or error. * @returns {void} */ verifySoftwareToken(totpCode, friendlyDeviceName, callback) { @@ -1545,57 +1542,59 @@ export default class CognitoUser { this.client.makeUnauthenticatedRequest('verifySoftwareToken', { Session: this.Session, UserCode: totpCode, - FriendlyDeviceName : friendlyDeviceName + FriendlyDeviceName: friendlyDeviceName, }, (err, data) => { if (err) { return callback.onFailure(err); } - this.Session = data.Session; + this.Session = data.Session; const challengeResponses = {}; challengeResponses.USERNAME = this.username; this.client.makeUnauthenticatedRequest('respondToAuthChallenge', { ChallengeName: 'MFA_SETUP', ClientId: this.pool.getClientId(), - ChallengeResponses : challengeResponses, + ChallengeResponses: challengeResponses, Session: this.Session, UserContextData: this.getUserContextData(), - }, (err, data) => { - if (err) { - return callback.onFailure(err); + }, (errRespond, dataRespond) => { + if (errRespond) { + return callback.onFailure(errRespond); } - this.signInUserSession = this.getCognitoUserSession(data.AuthenticationResult); + this.signInUserSession = this.getCognitoUserSession(dataRespond.AuthenticationResult); this.cacheTokens(); return callback.onSuccess(this.signInUserSession); }); + return undefined; }); } else { this.client.makeUnauthenticatedRequest('verifySoftwareToken', { AccessToken: this.signInUserSession.getAccessToken().getJwtToken(), - UserCode: totpCode, - FriendlyDeviceName : friendlyDeviceName + UserCode: totpCode, + FriendlyDeviceName: friendlyDeviceName, }, (err, data) => { if (err) { return callback.onFailure(err); } - this.Session = data.Session; + this.Session = data.Session; const challengeResponses = {}; challengeResponses.USERNAME = this.username; this.client.makeUnauthenticatedRequest('respondToAuthChallenge', { ChallengeName: 'MFA_SETUP', ClientId: this.pool.getClientId(), - ChallengeResponses : challengeResponses, + ChallengeResponses: challengeResponses, Session: this.Session, UserContextData: this.getUserContextData(), - }, (err, data) => { - if (err) { - return callback.onFailure(err); + }, (errRespond, dataRespond) => { + if (errRespond) { + return callback.onFailure(errRespond); } - this.signInUserSession = this.getCognitoUserSession(data.AuthenticationResult); + this.signInUserSession = this.getCognitoUserSession(dataRespond.AuthenticationResult); this.cacheTokens(); return callback.onSuccess(this.signInUserSession); }); + return undefined; }); } } diff --git a/src/CognitoUserPool.js b/src/CognitoUserPool.js index 1f34c838..12ebeef2 100644 --- a/src/CognitoUserPool.js +++ b/src/CognitoUserPool.js @@ -28,8 +28,9 @@ export default class CognitoUserPool { * @param {string} data.UserPoolId Cognito user pool id. * @param {string} data.ClientId User pool application client id. * @param {object} data.Storage Optional storage object. - * @param {boolean} data.AdvancedSecurityDataCollectionFlag Optional: boolean flag indicating if the - * data collection is enabled to support cognito advanced security features. By default, this + * @param {boolean} data.AdvancedSecurityDataCollectionFlag Optional: + * boolean flag indicating if the data collection is enabled + * to support cognito advanced security features. By default, this * flag is set to true. */ constructor(data) { @@ -50,9 +51,10 @@ export default class CognitoUserPool { region, endpoint, }); - + /** - * By default, AdvancedSecurityDataCollectionFlag is set to true, if no input value is provided. + * By default, AdvancedSecurityDataCollectionFlag is set to true, + * if no input value is provided. */ this.advancedSecurityDataCollectionFlag = true; if (AdvancedSecurityDataCollectionFlag) { @@ -143,22 +145,26 @@ export default class CognitoUserPool { /** * This method returns the encoded data string used for cognito advanced security feature. - * This would be generated only when developer has included the JS used for collecting the + * This would be generated only when developer has included the JS used for collecting the * data on their client. Please refer to documentation to know more about using AdvancedSecurity - * features + * features + * @param {string} username the username for the context data + * @returns {string} the user context data **/ getUserContextData(username) { - if (typeof AmazonCognitoAdvancedSecurityData === "undefined") { + if (typeof AmazonCognitoAdvancedSecurityData === 'undefined') { return {}; } + const amazonCognitoAdvancedSecurityDataConst = AmazonCognitoAdvancedSecurityData; if (this.advancedSecurityDataCollectionFlag) { - var advancedSecurityData = AmazonCognitoAdvancedSecurityData.getData(username, this.userPoolId, this.clientId); - if (advancedSecurityData){ - var userContextData = { - EncodedData: advancedSecurityData - }; - return userContextData; + const advancedSecurityData = amazonCognitoAdvancedSecurityDataConst.getData(username, + this.userPoolId, this.clientId); + if (advancedSecurityData) { + const userContextData = { + EncodedData: advancedSecurityData, + }; + return userContextData; } } return {};