Skip to content
This repository has been archived by the owner on Feb 24, 2018. It is now read-only.

Commit

Permalink
Stashing changes
Browse files Browse the repository at this point in the history
  • Loading branch information
Ionut Trestian committed Nov 24, 2017
1 parent 77c39bd commit f661903
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 52 deletions.
50 changes: 50 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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"
Expand Down
77 changes: 38 additions & 39 deletions src/CognitoUser.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand All @@ -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,
Expand Down Expand Up @@ -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<string>} 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) {
Expand Down Expand Up @@ -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<string>} callback Called on success or error.
* @returns {void}
*/
Expand All @@ -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);
}

Expand All @@ -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);
Expand All @@ -1528,74 +1525,76 @@ 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<string>} 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<string>} callback Called on success or error.
* @returns {void}
*/
verifySoftwareToken(totpCode, friendlyDeviceName, callback) {
if (!(this.signInUserSession != null && this.signInUserSession.isValid())) {
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;
});
}
}
Expand Down
32 changes: 19 additions & 13 deletions src/CognitoUserPool.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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) {
Expand Down Expand Up @@ -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 {};
Expand Down

0 comments on commit f661903

Please sign in to comment.