Best JavaScript code snippet using testcafe
CognitoUser.js
Source:CognitoUser.js  
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 the7 * License. A copy of the License is located at8 *9 *     http://aws.amazon.com/asl/10 *11 * or in the "license" file accompanying this file. This file is12 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR13 * CONDITIONS OF ANY KIND, express or implied. See the License14 * for the specific language governing permissions and15 * limitations under the License.16 */17'use strict'18var sjcl = require('sjcl');19var BigInteger = require('jsbn').BigInteger;20var AuthenticationHelper= require('./AuthenticationHelper');21var CognitoAccessToken= require('./CognitoAccessToken');22var CognitoIdToken= require('./CognitoIdToken');23var CognitoRefreshToken= require('./CognitoRefreshToken');24var CognitoUserSession= require('./CognitoUserSession');25var DateHelper = require('./DateHelper');26var CognitoUserAttribute = require('./CognitoUserAttribute');27var LocalStorage = require('node-localstorage').LocalStorage;28var os = require('os');29/**30 * @callback nodeCallback31 * @template T result32 * @param {*} err The operation failure reason, or null.33 * @param {T} result The operation result.34 */35/**36 * @callback onFailure37 * @param {*} err Failure reason.38 */39/**40 * @callback onSuccess41 * @template T result42 * @param {T} result The operation result.43 */44/**45 * @callback mfaRequired46 * @param {*} details MFA challenge details.47 */48/**49 * @callback customChallenge50 * @param {*} details Custom challenge details.51 */52/**53 * @callback inputVerificationCode54 * @param {*} data Server response.55 */56/**57 * @callback authSuccess58 * @param {CognitoUserSession} session The new session.59 * @param {bool=} userConfirmationNecessary User must be confirmed.60 */61/** @class */62module.exports = class CognitoUser {63  /**64   * Constructs a new CognitoUser object65   * @param {object} data Creation options66   * @param {string} data.Username The user's username.67   * @param {CognitoUserPool} data.Pool Pool containing the user.68   */69  constructor(data) {70    if (data == null || data.Username == null || data.Pool == null) {71      throw new Error('Username and pool information are required.');72    }73    this.username = data.Username || '';74    this.pool = data.Pool;75    this.Session = null;76    this.client = data.Pool.client;77    this.signInUserSession = null;78    this.authenticationFlowType = 'USER_SRP_AUTH';79  }80  /**81   * @returns {CognitoUserSession} the current session for this user82   */83  getSignInUserSession() {84    return this.signInUserSession;85  }86  /**87   * @returns {string} the user's username88   */89  getUsername() {90    return this.username;91  }92  /**93   * @returns {String} the authentication flow type94   */95  getAuthenticationFlowType() {96    return this.authenticationFlowType;97  }98  /**99   * sets authentication flow type100   * @param {string} authenticationFlowType New value.101   * @returns {void}102   */103  setAuthenticationFlowType(authenticationFlowType) {104    this.authenticationFlowType = authenticationFlowType;105  }106  /**107   * This is used for authenticating the user. it calls the AuthenticationHelper for SRP related108   * stuff109   * @param {AuthenticationDetails} authDetails Contains the authentication data110   * @param {object} callback Result callback map.111   * @param {onFailure} callback.onFailure Called on any error.112   * @param {newPasswordRequired} callback.newPasswordRequired new113   *        password and any required attributes are required to continue114   * @param {mfaRequired} callback.mfaRequired MFA code115   *        required to continue.116   * @param {customChallenge} callback.customChallenge Custom challenge117   *        response required to continue.118   * @param {authSuccess} callback.onSuccess Called on success with the new session.119   * @returns {void}120   */121  authenticateUser(authDetails, callback) {122    const authenticationHelper = new AuthenticationHelper(123      this.pool.getUserPoolId().split('_')[1],124      this.pool.getParanoia());125    const dateHelper = new DateHelper();126    let serverBValue;127    let salt;128    const authParameters = {};129    if (this.deviceKey != null) {130      authParameters.DEVICE_KEY = this.deviceKey;131    }132    authParameters.USERNAME = this.username;133    authParameters.SRP_A = authenticationHelper.getLargeAValue().toString(16);134    if (this.authenticationFlowType === 'CUSTOM_AUTH') {135      authParameters.CHALLENGE_NAME = 'SRP_A';136    }137    this.client.makeUnauthenticatedRequest('initiateAuth', {138      AuthFlow: this.authenticationFlowType,139      ClientId: this.pool.getClientId(),140      AuthParameters: authParameters,141      ClientMetadata: authDetails.getValidationData(),142    }, (err, data) => {143      if (err) {144        return callback.onFailure(err);145      }146      const challengeParameters = data.ChallengeParameters;147      this.username = challengeParameters.USER_ID_FOR_SRP;148      serverBValue = new BigInteger(challengeParameters.SRP_B, 16);149      salt = new BigInteger(challengeParameters.SALT, 16);150      this.getCachedDeviceKeyAndPassword();151      const hkdf = authenticationHelper.getPasswordAuthenticationKey(152        this.username,153        authDetails.getPassword(),154        serverBValue,155        salt);156      const secretBlockBits = sjcl.codec.base64.toBits(challengeParameters.SECRET_BLOCK);157      const mac = new sjcl.misc.hmac(hkdf, sjcl.hash.sha256);158      mac.update(sjcl.codec.utf8String.toBits(this.pool.getUserPoolId().split('_')[1]));159      mac.update(sjcl.codec.utf8String.toBits(this.username));160      mac.update(secretBlockBits);161      const dateNow = dateHelper.getNowString();162      mac.update(sjcl.codec.utf8String.toBits(dateNow));163      const signature = mac.digest();164      const signatureString = sjcl.codec.base64.fromBits(signature);165      const challengeResponses = {};166      challengeResponses.USERNAME = this.username;167      challengeResponses.PASSWORD_CLAIM_SECRET_BLOCK = challengeParameters.SECRET_BLOCK;168      challengeResponses.TIMESTAMP = dateNow;169      challengeResponses.PASSWORD_CLAIM_SIGNATURE = signatureString;170      if (this.deviceKey != null) {171        challengeResponses.DEVICE_KEY = this.deviceKey;172      }173      this.client.makeUnauthenticatedRequest('respondToAuthChallenge', {174        ChallengeName: 'PASSWORD_VERIFIER',175        ClientId: this.pool.getClientId(),176        ChallengeResponses: challengeResponses,177        Session: data.Session,178      }, (errAuthenticate, dataAuthenticate) => {179        if (errAuthenticate) {180          return callback.onFailure(errAuthenticate);181        }182        const challengeName = dataAuthenticate.ChallengeName;183        if (challengeName === 'NEW_PASSWORD_REQUIRED') {184          this.Session = dataAuthenticate.Session;185          let userAttributes = null;186          let rawRequiredAttributes = null;187          const requiredAttributes = [];188          const userAttributesPrefix = authenticationHelper189            .getNewPasswordRequiredChallengeUserAttributePrefix();190          if (dataAuthenticate.ChallengeParameters) {191            userAttributes = JSON.parse(192              dataAuthenticate.ChallengeParameters.userAttributes);193            rawRequiredAttributes = JSON.parse(194              dataAuthenticate.ChallengeParameters.requiredAttributes);195          }196          if (rawRequiredAttributes) {197            for (let i = 0; i < rawRequiredAttributes.length; i++) {198              requiredAttributes[i] = rawRequiredAttributes[i].substr(userAttributesPrefix.length);199            }200          }201          return callback.newPasswordRequired(userAttributes, requiredAttributes);202        }203        return this.authenticateUserInternal(dataAuthenticate, authenticationHelper, callback);204      });205      return undefined;206    });207  }208  /**209  * PRIVATE ONLY: This is an internal only method and should not210  * be directly called by the consumers.211  * @param {object} dataAuthenticate authentication data212  * @param {object} authenticationHelper helper created213  * @param {callback} callback passed on from caller214  * @returns {void}215  */216  authenticateUserInternal(dataAuthenticate, authenticationHelper, callback) {217    const challengeName = dataAuthenticate.ChallengeName;218    if (challengeName === 'SMS_MFA') {219      this.Session = dataAuthenticate.Session;220      return callback.mfaRequired(challengeName);221    }222    if (challengeName === 'CUSTOM_CHALLENGE') {223      this.Session = dataAuthenticate.Session;224      return callback.customChallenge(dataAuthenticate.ChallengeParameters);225    }226    if (challengeName === 'DEVICE_SRP_AUTH') {227      this.getDeviceResponse(callback);228      return undefined;229    }230    this.signInUserSession = this.getCognitoUserSession(dataAuthenticate.AuthenticationResult);231    this.cacheTokens();232    const newDeviceMetadata = dataAuthenticate.AuthenticationResult.NewDeviceMetadata;233    if (newDeviceMetadata == null) {234      return callback.onSuccess(this.signInUserSession);235    }236    authenticationHelper.generateHashDevice(237      dataAuthenticate.AuthenticationResult.NewDeviceMetadata.DeviceGroupKey,238      dataAuthenticate.AuthenticationResult.NewDeviceMetadata.DeviceKey);239    const deviceSecretVerifierConfig = {240      Salt: sjcl.codec.base64.fromBits(sjcl.codec.hex.toBits(241              authenticationHelper.getSaltDevices().toString(16))),242      PasswordVerifier: sjcl.codec.base64.fromBits(sjcl.codec.hex.toBits(243              authenticationHelper.getVerifierDevices().toString(16))),244    };245    this.verifierDevices = sjcl.codec.base64.fromBits(246      authenticationHelper.getVerifierDevices());247    this.deviceGroupKey = newDeviceMetadata.DeviceGroupKey;248    this.randomPassword = authenticationHelper.getRandomPassword();249    this.client.makeUnauthenticatedRequest('confirmDevice', {250      DeviceKey: newDeviceMetadata.DeviceKey,251      AccessToken: this.signInUserSession.getAccessToken().getJwtToken(),252      DeviceSecretVerifierConfig: deviceSecretVerifierConfig,253      DeviceName: navigator.userAgent,254    }, (errConfirm, dataConfirm) => {255      if (errConfirm) {256        return callback.onFailure(errConfirm);257      }258      this.deviceKey = dataAuthenticate.AuthenticationResult.NewDeviceMetadata.DeviceKey;259      this.cacheDeviceKeyAndPassword();260      if (dataConfirm.UserConfirmationNecessary === true) {261        return callback.onSuccess(262          this.signInUserSession, dataConfirm.UserConfirmationNecessary);263      }264      return callback.onSuccess(this.signInUserSession);265    });266    return undefined;267  }268  /**269  * This method is user to complete the NEW_PASSWORD_REQUIRED challenge.270  * Pass the new password with any new user attributes to be updated.271  * User attribute keys must be of format userAttributes.<attribute_name>.272  * @param {string} newPassword new password for this user273  * @param {object} requiredAttributeData map with values for all required attributes274  * @param {object} callback Result callback map.275  * @param {onFailure} callback.onFailure Called on any error.276  * @param {mfaRequired} callback.mfaRequired MFA code required to continue.277  * @param {customChallenge} callback.customChallenge Custom challenge278  *         response required to continue.279  * @param {authSuccess} callback.onSuccess Called on success with the new session.280  * @returns {void}281  */282  completeNewPasswordChallenge(newPassword, requiredAttributeData, callback) {283    if (!newPassword) {284      return callback.onFailure('New password is required.');285    }286    const authenticationHelper = new AuthenticationHelper(287      this.pool.getUserPoolId().split('_')[1], this.pool.getParanoia());288    const userAttributesPrefix = authenticationHelper289      .getNewPasswordRequiredChallengeUserAttributePrefix();290    const finalUserAttributes = {};291    if (requiredAttributeData) {292      Object.keys(requiredAttributeData).forEach((key) => {293        finalUserAttributes[userAttributesPrefix + key] = requiredAttributeData[key];294      });295    }296    finalUserAttributes.NEW_PASSWORD = newPassword;297    finalUserAttributes.USERNAME = this.username;298    this.client.makeUnauthenticatedRequest('respondToAuthChallenge', {299      ChallengeName: 'NEW_PASSWORD_REQUIRED',300      ClientId: this.pool.getClientId(),301      ChallengeResponses: finalUserAttributes,302      Session: this.Session,303    }, (errAuthenticate, dataAuthenticate) => {304      if (errAuthenticate) {305        return callback.onFailure(errAuthenticate);306      }307      return this.authenticateUserInternal(dataAuthenticate, authenticationHelper, callback);308    });309    return undefined;310  }311  /**312   * This is used to get a session using device authentication. It is called at the end of user313   * authentication314   *315   * @param {object} callback Result callback map.316   * @param {onFailure} callback.onFailure Called on any error.317   * @param {authSuccess} callback.onSuccess Called on success with the new session.318   * @returns {void}319   * @private320   */321  getDeviceResponse(callback) {322    const authenticationHelper = new AuthenticationHelper(323      this.deviceGroupKey,324      this.pool.getParanoia());325    const dateHelper = new DateHelper();326    const authParameters = {};327    authParameters.USERNAME = this.username;328    authParameters.DEVICE_KEY = this.deviceKey;329    authParameters.SRP_A = authenticationHelper.getLargeAValue().toString(16);330    this.client.makeUnauthenticatedRequest('respondToAuthChallenge', {331      ChallengeName: 'DEVICE_SRP_AUTH',332      ClientId: this.pool.getClientId(),333      ChallengeResponses: authParameters,334    }, (err, data) => {335      if (err) {336        return callback.onFailure(err);337      }338      const challengeParameters = data.ChallengeParameters;339      const serverBValue = new BigInteger(challengeParameters.SRP_B, 16);340      const salt = new BigInteger(challengeParameters.SALT, 16);341      const hkdf = authenticationHelper.getPasswordAuthenticationKey(342        this.deviceKey,343        this.randomPassword,344        serverBValue,345        salt);346      const secretBlockBits = sjcl.codec.base64.toBits(challengeParameters.SECRET_BLOCK);347      const mac = new sjcl.misc.hmac(hkdf, sjcl.hash.sha256);348      mac.update(sjcl.codec.utf8String.toBits(this.deviceGroupKey));349      mac.update(sjcl.codec.utf8String.toBits(this.deviceKey));350      mac.update(secretBlockBits);351      const dateNow = dateHelper.getNowString();352      mac.update(sjcl.codec.utf8String.toBits(dateNow));353      const signature = mac.digest();354      const signatureString = sjcl.codec.base64.fromBits(signature);355      const challengeResponses = {};356      challengeResponses.USERNAME = this.username;357      challengeResponses.PASSWORD_CLAIM_SECRET_BLOCK = challengeParameters.SECRET_BLOCK;358      challengeResponses.TIMESTAMP = dateNow;359      challengeResponses.PASSWORD_CLAIM_SIGNATURE = signatureString;360      challengeResponses.DEVICE_KEY = this.deviceKey;361      this.client.makeUnauthenticatedRequest('respondToAuthChallenge', {362        ChallengeName: 'DEVICE_PASSWORD_VERIFIER',363        ClientId: this.pool.getClientId(),364        ChallengeResponses: challengeResponses,365        Session: data.Session,366      }, (errAuthenticate, dataAuthenticate) => {367        if (errAuthenticate) {368          return callback.onFailure(errAuthenticate);369        }370        this.signInUserSession = this.getCognitoUserSession(dataAuthenticate.AuthenticationResult);371        this.cacheTokens();372        return callback.onSuccess(this.signInUserSession);373      });374      return undefined;375    });376  }377  /**378   * This is used for a certain user to confirm the registration by using a confirmation code379   * @param {string} confirmationCode Code entered by user.380   * @param {bool} forceAliasCreation Allow migrating from an existing email / phone number.381   * @param {nodeCallback<string>} callback Called on success or error.382   * @returns {void}383   */384  confirmRegistration(confirmationCode, forceAliasCreation, callback) {385    this.client.makeUnauthenticatedRequest('confirmSignUp', {386      ClientId: this.pool.getClientId(),387      ConfirmationCode: confirmationCode,388      Username: this.username,389      ForceAliasCreation: forceAliasCreation,390    }, err => {391      if (err) {392        return callback(err, null);393      }394      return callback(null, 'SUCCESS');395    });396  }397  /**398   * This is used by the user once he has the responses to a custom challenge399   * @param {string} answerChallenge The custom challange answer.400   * @param {object} callback Result callback map.401   * @param {onFailure} callback.onFailure Called on any error.402   * @param {customChallenge} callback.customChallenge403   *    Custom challenge response required to continue.404   * @param {authSuccess} callback.onSuccess Called on success with the new session.405   * @returns {void}406   */407  sendCustomChallengeAnswer(answerChallenge, callback) {408    const challengeResponses = {};409    challengeResponses.USERNAME = this.username;410    challengeResponses.ANSWER = answerChallenge;411    this.client.makeUnauthenticatedRequest('respondToAuthChallenge', {412      ChallengeName: 'CUSTOM_CHALLENGE',413      ChallengeResponses: challengeResponses,414      ClientId: this.pool.getClientId(),415      Session: this.Session,416    }, (err, data) => {417      if (err) {418        return callback.onFailure(err);419      }420      const challengeName = data.ChallengeName;421      if (challengeName === 'CUSTOM_CHALLENGE') {422        this.Session = data.Session;423        return callback.customChallenge(data.challengeParameters);424      }425      this.signInUserSession = this.getCognitoUserSession(data.AuthenticationResult);426      this.cacheTokens();427      return callback.onSuccess(this.signInUserSession);428    });429  }430  /**431   * This is used by the user once he has an MFA code432   * @param {string} confirmationCode The MFA code entered by the user.433   * @param {object} callback Result callback map.434   * @param {onFailure} callback.onFailure Called on any error.435   * @param {authSuccess} callback.onSuccess Called on success with the new session.436   * @returns {void}437   */438  sendMFACode(confirmationCode, callback) {439    const challengeResponses = {};440    challengeResponses.USERNAME = this.username;441    challengeResponses.SMS_MFA_CODE = confirmationCode;442    if (this.deviceKey != null) {443      challengeResponses.DEVICE_KEY = this.deviceKey;444    }445    this.client.makeUnauthenticatedRequest('respondToAuthChallenge', {446      ChallengeName: 'SMS_MFA',447      ChallengeResponses: challengeResponses,448      ClientId: this.pool.getClientId(),449      Session: this.Session,450    }, (err, dataAuthenticate) => {451      if (err) {452        return callback.onFailure(err);453      }454      this.signInUserSession = this.getCognitoUserSession(dataAuthenticate.AuthenticationResult);455      this.cacheTokens();456      if (dataAuthenticate.AuthenticationResult.NewDeviceMetadata == null) {457        return callback.onSuccess(this.signInUserSession);458      }459      const authenticationHelper = new AuthenticationHelper(460        this.pool.getUserPoolId().split('_')[1],461        this.pool.getParanoia());462      authenticationHelper.generateHashDevice(463        dataAuthenticate.AuthenticationResult.NewDeviceMetadata.DeviceGroupKey,464        dataAuthenticate.AuthenticationResult.NewDeviceMetadata.DeviceKey);465      const deviceSecretVerifierConfig = {466        Salt: sjcl.codec.base64.fromBits(sjcl.codec.hex.toBits(467          authenticationHelper.getSaltDevices().toString(16))),468        PasswordVerifier: sjcl.codec.base64.fromBits(sjcl.codec.hex.toBits(469          authenticationHelper.getVerifierDevices().toString(16))),470      };471      this.verifierDevices = sjcl.codec.base64.fromBits(472        authenticationHelper.getVerifierDevices());473      this.deviceGroupKey = dataAuthenticate.AuthenticationResult474        .NewDeviceMetadata.DeviceGroupKey;475      this.randomPassword = authenticationHelper.getRandomPassword();476      this.client.makeUnauthenticatedRequest('confirmDevice', {477        DeviceKey: dataAuthenticate.AuthenticationResult.NewDeviceMetadata.DeviceKey,478        AccessToken: this.signInUserSession.getAccessToken().getJwtToken(),479        DeviceSecretVerifierConfig: deviceSecretVerifierConfig,480        DeviceName: navigator.userAgent,481      }, (errConfirm, dataConfirm) => {482        if (errConfirm) {483          return callback.onFailure(errConfirm);484        }485        this.deviceKey = dataAuthenticate.AuthenticationResult.NewDeviceMetadata.DeviceKey;486        this.cacheDeviceKeyAndPassword();487        if (dataConfirm.UserConfirmationNecessary === true) {488          return callback.onSuccess(489            this.signInUserSession,490            dataConfirm.UserConfirmationNecessary);491        }492        return callback.onSuccess(this.signInUserSession);493      });494      return undefined;495    });496  }497  /**498   * This is used by an authenticated user to change the current password499   * @param {string} oldUserPassword The current password.500   * @param {string} newUserPassword The requested new password.501   * @param {nodeCallback<string>} callback Called on success or error.502   * @returns {void}503   */504  changePassword(oldUserPassword, newUserPassword, callback) {505    if (!(this.signInUserSession != null && this.signInUserSession.isValid())) {506      return callback(new Error('User is not authenticated'), null);507    }508    this.client.makeUnauthenticatedRequest('changePassword', {509      PreviousPassword: oldUserPassword,510      ProposedPassword: newUserPassword,511      AccessToken: this.signInUserSession.getAccessToken().getJwtToken(),512    }, err => {513      if (err) {514        return callback(err, null);515      }516      return callback(null, 'SUCCESS');517    });518    return undefined;519  }520  /**521   * This is used by an authenticated user to enable MFA for himself522   * @param {nodeCallback<string>} callback Called on success or error.523   * @returns {void}524   */525  enableMFA(callback) {526    if (this.signInUserSession == null || !this.signInUserSession.isValid()) {527      return callback(new Error('User is not authenticated'), null);528    }529    const mfaOptions = [];530    const mfaEnabled = {531      DeliveryMedium: 'SMS',532      AttributeName: 'phone_number',533    };534    mfaOptions.push(mfaEnabled);535    this.client.makeUnauthenticatedRequest('setUserSettings', {536      MFAOptions: mfaOptions,537      AccessToken: this.signInUserSession.getAccessToken().getJwtToken(),538    }, err => {539      if (err) {540        return callback(err, null);541      }542      return callback(null, 'SUCCESS');543    });544    return undefined;545  }546  /**547   * This is used by an authenticated user to disable MFA for himself548   * @param {nodeCallback<string>} callback Called on success or error.549   * @returns {void}550   */551  disableMFA(callback) {552    if (this.signInUserSession == null || !this.signInUserSession.isValid()) {553      return callback(new Error('User is not authenticated'), null);554    }555    const mfaOptions = [];556    this.client.makeUnauthenticatedRequest('setUserSettings', {557      MFAOptions: mfaOptions,558      AccessToken: this.signInUserSession.getAccessToken().getJwtToken(),559    }, err => {560      if (err) {561        return callback(err, null);562      }563      return callback(null, 'SUCCESS');564    });565    return undefined;566  }567  /**568   * This is used by an authenticated user to delete himself569   * @param {nodeCallback<string>} callback Called on success or error.570   * @returns {void}571   */572  deleteUser(callback) {573    if (this.signInUserSession == null || !this.signInUserSession.isValid()) {574      return callback(new Error('User is not authenticated'), null);575    }576    this.client.makeUnauthenticatedRequest('deleteUser', {577      AccessToken: this.signInUserSession.getAccessToken().getJwtToken(),578    }, err => {579      if (err) {580        return callback(err, null);581      }582      return callback(null, 'SUCCESS');583    });584    return undefined;585  }586  /**587   * @typedef {CognitoUserAttribute | { Name:string, Value:string }} AttributeArg588   */589  /**590   * This is used by an authenticated user to change a list of attributes591   * @param {AttributeArg[]} attributes A list of the new user attributes.592   * @param {nodeCallback<string>} callback Called on success or error.593   * @returns {void}594   */595  updateAttributes(attributes, callback) {596    if (this.signInUserSession == null || !this.signInUserSession.isValid()) {597      return callback(new Error('User is not authenticated'), null);598    }599    this.client.makeUnauthenticatedRequest('updateUserAttributes', {600      AccessToken: this.signInUserSession.getAccessToken().getJwtToken(),601      UserAttributes: attributes,602    }, err => {603      if (err) {604        return callback(err, null);605      }606      return callback(null, 'SUCCESS');607    });608    return undefined;609  }610  /**611   * This is used by an authenticated user to get a list of attributes612   * @param {nodeCallback<CognitoUserAttribute[]>} callback Called on success or error.613   * @returns {void}614   */615  getUserAttributes(callback) {616    if (!(this.signInUserSession != null && this.signInUserSession.isValid())) {617      return callback(new Error('User is not authenticated'), null);618    }619    this.client.makeUnauthenticatedRequest('getUser', {620      AccessToken: this.signInUserSession.getAccessToken().getJwtToken(),621    }, (err, userData) => {622      if (err) {623        return callback(err, null);624      }625      const attributeList = [];626      for (let i = 0; i < userData.UserAttributes.length; i++) {627        const attribute = {628          Name: userData.UserAttributes[i].Name,629          Value: userData.UserAttributes[i].Value,630        };631        const userAttribute = new CognitoUserAttribute(attribute);632        attributeList.push(userAttribute);633      }634      return callback(null, attributeList);635    });636    return undefined;637  }638  /**639   * This is used by an authenticated user to delete a list of attributes640   * @param {string[]} attributeList Names of the attributes to delete.641   * @param {nodeCallback<string>} callback Called on success or error.642   * @returns {void}643   */644  deleteAttributes(attributeList, callback) {645    if (!(this.signInUserSession != null && this.signInUserSession.isValid())) {646      return callback(new Error('User is not authenticated'), null);647    }648    this.client.makeUnauthenticatedRequest('deleteUserAttributes', {649      UserAttributeNames: attributeList,650      AccessToken: this.signInUserSession.getAccessToken().getJwtToken(),651    }, err => {652      if (err) {653        return callback(err, null);654      }655      return callback(null, 'SUCCESS');656    });657    return undefined;658  }659  /**660   * This is used by a user to resend a confirmation code661   * @param {nodeCallback<string>} callback Called on success or error.662   * @returns {void}663   */664  resendConfirmationCode(callback) {665    this.client.makeUnauthenticatedRequest('resendConfirmationCode', {666      ClientId: this.pool.getClientId(),667      Username: this.username,668    }, err => {669      if (err) {670        return callback(err, null);671      }672      return callback(null, 'SUCCESS');673    });674  }675  /**676   * This is used to get a session, either from the session object677   * or from  the local storage, or by using a refresh token678   *679   * @param {nodeCallback<CognitoUserSession>} callback Called on success or error.680   * @returns {void}681   */682  getSession(callback) {683    if (this.username == null) {684      return callback(new Error('Username is null. Cannot retrieve a new session'), null);685    }686    if (this.signInUserSession != null && this.signInUserSession.isValid()) {687      return callback(null, this.signInUserSession);688    }689    const keyPrefix = `CognitoIdentityServiceProvider.${this.pool.getClientId()}.${this.username}`;690    const idTokenKey = `${keyPrefix}.idToken`;691    const accessTokenKey = `${keyPrefix}.accessToken`;692    const refreshTokenKey = `${keyPrefix}.refreshToken`;693//    const storage = window.localStorage;694    const storage = new LocalStorage(os.tmpdir() + '/storage');695    if (storage.getItem(idTokenKey)) {696      const idToken = new CognitoIdToken({697        IdToken: storage.getItem(idTokenKey),698      });699      const accessToken = new CognitoAccessToken({700        AccessToken: storage.getItem(accessTokenKey),701      });702      const refreshToken = new CognitoRefreshToken({703        RefreshToken: storage.getItem(refreshTokenKey),704      });705      const sessionData = {706        IdToken: idToken,707        AccessToken: accessToken,708        RefreshToken: refreshToken,709      };710      const cachedSession = new CognitoUserSession(sessionData);711      if (cachedSession.isValid()) {712        this.signInUserSession = cachedSession;713        return callback(null, this.signInUserSession);714      }715      if (refreshToken.getToken() == null) {716        return callback(new Error('Cannot retrieve a new session. Please authenticate.'), null);717      }718      this.refreshSession(refreshToken, callback);719    }720    return undefined;721  }722  /**723   * This uses the refreshToken to retrieve a new session724   * @param {CognitoRefreshToken} refreshToken A previous session's refresh token.725   * @param {nodeCallback<CognitoUserSession>} callback Called on success or error.726   * @returns {void}727   */728  refreshSession(refreshToken, callback) {729    const authParameters = {};730    authParameters.REFRESH_TOKEN = refreshToken.getToken();731    const keyPrefix = `CognitoIdentityServiceProvider.${this.pool.getClientId()}`;732    const lastUserKey = `${keyPrefix}.LastAuthUser`;733//    const storage = window.localStorage;734    const storage = new LocalStorage(os.tmpdir() + '/storage');735    if (storage.getItem(lastUserKey)) {736//  Should set username directly like:737//  cognitoUser.username = 'hoge@hoge.com'738//      this.username = storage.getItem(lastUserKey);739      const deviceKeyKey = `${keyPrefix}.${this.username}.deviceKey`;740      this.deviceKey = storage.getItem(deviceKeyKey);741      authParameters.DEVICE_KEY = this.deviceKey;742    }743    this.client.makeUnauthenticatedRequest('initiateAuth', {744      ClientId: this.pool.getClientId(),745      AuthFlow: 'REFRESH_TOKEN_AUTH',746      AuthParameters: authParameters,747    }, (err, authResult) => {748      if (err) {749        return callback(err, null);750      }751      if (authResult) {752        const authenticationResult = authResult.AuthenticationResult;753        if (!Object.prototype.hasOwnProperty.call(authenticationResult, 'RefreshToken')) {754          authenticationResult.RefreshToken = refreshToken.getToken();755        }756        this.signInUserSession = this.getCognitoUserSession(authenticationResult);757        this.cacheTokens();758        return callback(null, this.signInUserSession);759      }760      return undefined;761    });762  }763  /**764   * This is used to save the session tokens to local storage765   * @returns {void}766   */767  cacheTokens() {768    const keyPrefix = `CognitoIdentityServiceProvider.${this.pool.getClientId()}`;769    const idTokenKey = `${keyPrefix}.${this.username}.idToken`;770    const accessTokenKey = `${keyPrefix}.${this.username}.accessToken`;771    const refreshTokenKey = `${keyPrefix}.${this.username}.refreshToken`;772    const lastUserKey = `${keyPrefix}.LastAuthUser`;773//    const storage = window.localStorage;774    const storage = new LocalStorage(os.tmpdir() + '/storage');775    storage.setItem(idTokenKey, this.signInUserSession.getIdToken().getJwtToken());776    storage.setItem(accessTokenKey, this.signInUserSession.getAccessToken().getJwtToken());777    storage.setItem(refreshTokenKey, this.signInUserSession.getRefreshToken().getToken());778    storage.setItem(lastUserKey, this.username);779  }780  /**781   * This is used to cache the device key and device group and device password782   * @returns {void}783   */784  cacheDeviceKeyAndPassword() {785    const keyPrefix = `CognitoIdentityServiceProvider.${this.pool.getClientId()}.${this.username}`;786    const deviceKeyKey = `${keyPrefix}.deviceKey`;787    const randomPasswordKey = `${keyPrefix}.randomPasswordKey`;788    const deviceGroupKeyKey = `${keyPrefix}.deviceGroupKey`;789//    const storage = window.localStorage;790    const storage = new LocalStorage(os.tmpdir() + '/storage');791    storage.setItem(deviceKeyKey, this.deviceKey);792    storage.setItem(randomPasswordKey, this.randomPassword);793    storage.setItem(deviceGroupKeyKey, this.deviceGroupKey);794  }795  /**796   * This is used to get current device key and device group and device password797   * @returns {void}798   */799  getCachedDeviceKeyAndPassword() {800    const keyPrefix = `CognitoIdentityServiceProvider.${this.pool.getClientId()}.${this.username}`;801    const deviceKeyKey = `${keyPrefix}.deviceKey`;802    const randomPasswordKey = `${keyPrefix}.randomPasswordKey`;803    const deviceGroupKeyKey = `${keyPrefix}.deviceGroupKey`;804//    const storage = window.localStorage;805    const storage = new LocalStorage(os.tmpdir() + '/storage');806    if (storage.getItem(deviceKeyKey)) {807      this.deviceKey = storage.getItem(deviceKeyKey);808      this.randomPassword = storage.getItem(randomPasswordKey);809      this.deviceGroupKey = storage.getItem(deviceGroupKeyKey);810    }811  }812  /**813   * This is used to clear the device key info from local storage814   * @returns {void}815   */816  clearCachedDeviceKeyAndPassword() {817    const keyPrefix = `CognitoIdentityServiceProvider.${this.pool.getClientId()}.${this.username}`;818    const deviceKeyKey = `${keyPrefix}.deviceKey`;819    const randomPasswordKey = `${keyPrefix}.randomPasswordKey`;820    const deviceGroupKeyKey = `${keyPrefix}.deviceGroupKey`;821//    const storage = window.localStorage;822    const storage = new LocalStorage(os.tmpdir() + '/storage');823    storage.removeItem(deviceKeyKey);824    storage.removeItem(randomPasswordKey);825    storage.removeItem(deviceGroupKeyKey);826  }827  /**828   * This is used to clear the session tokens from local storage829   * @returns {void}830   */831  clearCachedTokens() {832    const keyPrefix = `CognitoIdentityServiceProvider.${this.pool.getClientId()}`;833    const idTokenKey = `${keyPrefix}.${this.username}.idToken`;834    const accessTokenKey = `${keyPrefix}.${this.username}.accessToken`;835    const refreshTokenKey = `${keyPrefix}.${this.username}.refreshToken`;836    const lastUserKey = `${keyPrefix}.LastAuthUser`;837//    const storage = window.localStorage;838    const storage = new LocalStorage(os.tmpdir() + '/storage');839    storage.removeItem(idTokenKey);840    storage.removeItem(accessTokenKey);841    storage.removeItem(refreshTokenKey);842    storage.removeItem(lastUserKey);843  }844  /**845   * This is used to build a user session from tokens retrieved in the authentication result846   * @param {object} authResult Successful auth response from server.847   * @returns {CognitoUserSession} The new user session.848   * @private849   */850  getCognitoUserSession(authResult) {851    const idToken = new CognitoIdToken(authResult);852    const accessToken = new CognitoAccessToken(authResult);853    const refreshToken = new CognitoRefreshToken(authResult);854    const sessionData = {855      IdToken: idToken,856      AccessToken: accessToken,857      RefreshToken: refreshToken,858    };859    return new CognitoUserSession(sessionData);860  }861  /**862   * This is used to initiate a forgot password request863   * @param {object} callback Result callback map.864   * @param {onFailure} callback.onFailure Called on any error.865   * @param {inputVerificationCode?} callback.inputVerificationCode866   *    Optional callback raised instead of onSuccess with response data.867   * @param {onSuccess<void>?} callback.onSuccess Called on success.868   * @returns {void}869   */870  forgotPassword(callback) {871    this.client.makeUnauthenticatedRequest('forgotPassword', {872      ClientId: this.pool.getClientId(),873      Username: this.username,874    }, (err, data) => {875      if (err) {876        return callback.onFailure(err);877      }878      if (typeof callback.inputVerificationCode === 'function') {879        return callback.inputVerificationCode(data);880      }881      return callback.onSuccess();882    });883  }884  /**885   * This is used to confirm a new password using a confirmationCode886   * @param {string} confirmationCode Code entered by user.887   * @param {string} newPassword Confirm new password.888   * @param {object} callback Result callback map.889   * @param {onFailure} callback.onFailure Called on any error.890   * @param {onSuccess<void>} callback.onSuccess Called on success.891   * @returns {void}892   */893  confirmPassword(confirmationCode, newPassword, callback) {894    this.client.makeUnauthenticatedRequest('confirmForgotPassword', {895      ClientId: this.pool.getClientId(),896      Username: this.username,897      ConfirmationCode: confirmationCode,898      Password: newPassword,899    }, err => {900      if (err) {901        return callback.onFailure(err);902      }903      return callback.onSuccess();904    });905  }906  /**907   * This is used to initiate an attribute confirmation request908   * @param {string} attributeName User attribute that needs confirmation.909   * @param {object} callback Result callback map.910   * @param {onFailure} callback.onFailure Called on any error.911   * @param {inputVerificationCode} callback.inputVerificationCode Called on success.912   * @returns {void}913   */914  getAttributeVerificationCode(attributeName, callback) {915    if (this.signInUserSession == null || !this.signInUserSession.isValid()) {916      return callback(new Error('User is not authenticated'), null);917    }918    this.client.makeUnauthenticatedRequest('getUserAttributeVerificationCode', {919      AttributeName: attributeName,920      AccessToken: this.signInUserSession.getAccessToken().getJwtToken(),921    }, (err, data) => {922      if (err) {923        return callback.onFailure(err);924      }925      return callback.inputVerificationCode(data);926    });927    return undefined;928  }929  /**930   * This is used to confirm an attribute using a confirmation code931   * @param {string} attributeName Attribute being confirmed.932   * @param {string} confirmationCode Code entered by user.933   * @param {object} callback Result callback map.934   * @param {onFailure} callback.onFailure Called on any error.935   * @param {onSuccess<string>} callback.onSuccess Called on success.936   * @returns {void}937   */938  verifyAttribute(attributeName, confirmationCode, callback) {939    if (this.signInUserSession == null || !this.signInUserSession.isValid()) {940      return callback(new Error('User is not authenticated'), null);941    }942    this.client.makeUnauthenticatedRequest('verifyUserAttribute', {943      AttributeName: attributeName,944      Code: confirmationCode,945      AccessToken: this.signInUserSession.getAccessToken().getJwtToken(),946    }, err => {947      if (err) {948        return callback.onFailure(err);949      }950      return callback.onSuccess('SUCCESS');951    });952    return undefined;953  }954  /**955   * This is used to get the device information using the current device key956   * @param {object} callback Result callback map.957   * @param {onFailure} callback.onFailure Called on any error.958   * @param {onSuccess<*>} callback.onSuccess Called on success with device data.959   * @returns {void}960   */961  getDevice(callback) {962    if (this.signInUserSession == null || !this.signInUserSession.isValid()) {963      return callback(new Error('User is not authenticated'), null);964    }965    this.client.makeUnauthenticatedRequest('getDevice', {966      AccessToken: this.signInUserSession.getAccessToken().getJwtToken(),967      DeviceKey: this.deviceKey,968    }, (err, data) => {969      if (err) {970        return callback.onFailure(err);971      }972      return callback.onSuccess(data);973    });974    return undefined;975  }976  /**977   * This is used to forget the current device978   * @param {object} callback Result callback map.979   * @param {onFailure} callback.onFailure Called on any error.980   * @param {onSuccess<string>} callback.onSuccess Called on success.981   * @returns {void}982   */983  forgetDevice(callback) {984    if (this.signInUserSession == null || !this.signInUserSession.isValid()) {985      return callback(new Error('User is not authenticated'), null);986    }987    this.client.makeUnauthenticatedRequest('forgetDevice', {988      AccessToken: this.signInUserSession.getAccessToken().getJwtToken(),989      DeviceKey: this.deviceKey,990    }, err => {991      if (err) {992        return callback.onFailure(err);993      }994      this.deviceKey = null;995      this.deviceGroupkey = null;996      this.randomPassword = null;997      this.clearCachedDeviceKeyAndPassword();998      return callback.onSuccess('SUCCESS');999    });1000    return undefined;1001  }1002  /**1003   * This is used to set the device status as remembered1004   * @param {object} callback Result callback map.1005   * @param {onFailure} callback.onFailure Called on any error.1006   * @param {onSuccess<string>} callback.onSuccess Called on success.1007   * @returns {void}1008   */1009  setDeviceStatusRemembered(callback) {1010    if (this.signInUserSession == null || !this.signInUserSession.isValid()) {1011      return callback(new Error('User is not authenticated'), null);1012    }1013    this.client.makeUnauthenticatedRequest('updateDeviceStatus', {1014      AccessToken: this.signInUserSession.getAccessToken().getJwtToken(),1015      DeviceKey: this.deviceKey,1016      DeviceRememberedStatus: 'remembered',1017    }, err => {1018      if (err) {1019        return callback.onFailure(err);1020      }1021      return callback.onSuccess('SUCCESS');1022    });1023    return undefined;1024  }1025  /**1026   * This is used to set the device status as not remembered1027   * @param {object} callback Result callback map.1028   * @param {onFailure} callback.onFailure Called on any error.1029   * @param {onSuccess<string>} callback.onSuccess Called on success.1030   * @returns {void}1031   */1032  setDeviceStatusNotRemembered(callback) {1033    if (this.signInUserSession == null || !this.signInUserSession.isValid()) {1034      return callback(new Error('User is not authenticated'), null);1035    }1036    this.client.makeUnauthenticatedRequest('updateDeviceStatus', {1037      AccessToken: this.signInUserSession.getAccessToken().getJwtToken(),1038      DeviceKey: this.deviceKey,1039      DeviceRememberedStatus: 'not_remembered',1040    }, err => {1041      if (err) {1042        return callback.onFailure(err);1043      }1044      return callback.onSuccess('SUCCESS');1045    });1046    return undefined;1047  }1048  /**1049   * This is used to list all devices for a user1050   *1051   * @param {int} limit the number of devices returned in a call1052   * @param {string} paginationToken the pagination token in case any was returned before1053   * @param {object} callback Result callback map.1054   * @param {onFailure} callback.onFailure Called on any error.1055   * @param {onSuccess<*>} callback.onSuccess Called on success with device list.1056   * @returns {void}1057   */1058  listDevices(limit, paginationToken, callback) {1059    if (this.signInUserSession == null || !this.signInUserSession.isValid()) {1060      return callback(new Error('User is not authenticated'), null);1061    }1062    this.client.makeUnauthenticatedRequest('listDevices', {1063      AccessToken: this.signInUserSession.getAccessToken().getJwtToken(),1064      Limit: limit,1065      PaginationToken: paginationToken,1066    }, (err, data) => {1067      if (err) {1068        return callback.onFailure(err);1069      }1070      return callback.onSuccess(data);1071    });1072    return undefined;1073  }1074  /**1075   * This is used to globally revoke all tokens issued to a user1076   * @param {object} callback Result callback map.1077   * @param {onFailure} callback.onFailure Called on any error.1078   * @param {onSuccess<string>} callback.onSuccess Called on success.1079   * @returns {void}1080   */1081  globalSignOut(callback) {1082    if (this.signInUserSession == null || !this.signInUserSession.isValid()) {1083      return callback(new Error('User is not authenticated'), null);1084    }1085    this.client.makeUnauthenticatedRequest('globalSignOut', {1086      AccessToken: this.signInUserSession.getAccessToken().getJwtToken(),1087    }, err => {1088      if (err) {1089        return callback.onFailure(err);1090      }1091      this.clearCachedTokens();1092      return callback.onSuccess('SUCCESS');1093    });1094    return undefined;1095  }1096  /**1097   * This is used for the user to signOut of the application and clear the cached tokens.1098   * @returns {void}1099   */1100  signOut() {1101    this.signInUserSession = null;1102    this.clearCachedTokens();1103  }...AuthenticationHelper.js
Source:AuthenticationHelper.js  
1function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }2/*!3 * Copyright 2016 Amazon.com,4 * Inc. or its affiliates. All Rights Reserved.5 *6 * Licensed under the Amazon Software License (the "License").7 * You may not use this file except in compliance with the8 * License. A copy of the License is located at9 *10 *     http://aws.amazon.com/asl/11 *12 * or in the "license" file accompanying this file. This file is13 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR14 * CONDITIONS OF ANY KIND, express or implied. See the License15 * for the specific language governing permissions and16 * limitations under the License.17 */18import { util } from 'aws-sdk/global';19import BigInteger from './BigInteger';20var initN = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1' + '29024E088A67CC74020BBEA63B139B22514A08798E3404DD' + 'EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245' + 'E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' + 'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D' + 'C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F' + '83655D23DCA3AD961C62F356208552BB9ED529077096966D' + '670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B' + 'E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9' + 'DE2BCBF6955817183995497CEA956AE515D2261898FA0510' + '15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64' + 'ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7' + 'ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B' + 'F12FFA06D98A0864D87602733EC86A64521F2B18177B200C' + 'BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31' + '43DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF';21var newPasswordRequiredChallengeUserAttributePrefix = 'userAttributes.';22/** @class */23var AuthenticationHelper = function () {24  /**25   * Constructs a new AuthenticationHelper object26   * @param {string} PoolName Cognito user pool name.27   */28  function AuthenticationHelper(PoolName) {29    _classCallCheck(this, AuthenticationHelper);30    this.N = new BigInteger(initN, 16);31    this.g = new BigInteger('2', 16);32    this.k = new BigInteger(this.hexHash('00' + this.N.toString(16) + '0' + this.g.toString(16)), 16);33    this.smallAValue = this.generateRandomSmallA();34    this.getLargeAValue(function () {});35    this.infoBits = new util.Buffer('Caldera Derived Key', 'utf8');36    this.poolName = PoolName;37  }38  /**39   * @returns {BigInteger} small A, a random number40   */41  AuthenticationHelper.prototype.getSmallAValue = function getSmallAValue() {42    return this.smallAValue;43  };44  /**45   * @param {nodeCallback<BigInteger>} callback Called with (err, largeAValue)46   * @returns {void}47   */48  AuthenticationHelper.prototype.getLargeAValue = function getLargeAValue(callback) {49    var _this = this;50    if (this.largeAValue) {51      callback(null, this.largeAValue);52    } else {53      this.calculateA(this.smallAValue, function (err, largeAValue) {54        if (err) {55          callback(err, null);56        }57        _this.largeAValue = largeAValue;58        callback(null, _this.largeAValue);59      });60    }61  };62  /**63   * helper function to generate a random big integer64   * @returns {BigInteger} a random value.65   * @private66   */67  AuthenticationHelper.prototype.generateRandomSmallA = function generateRandomSmallA() {68    var hexRandom = util.crypto.lib.randomBytes(128).toString('hex');69    var randomBigInt = new BigInteger(hexRandom, 16);70    var smallABigInt = randomBigInt.mod(this.N);71    return smallABigInt;72  };73  /**74   * helper function to generate a random string75   * @returns {string} a random value.76   * @private77   */78  AuthenticationHelper.prototype.generateRandomString = function generateRandomString() {79    return util.crypto.lib.randomBytes(40).toString('base64');80  };81  /**82   * @returns {string} Generated random value included in password hash.83   */84  AuthenticationHelper.prototype.getRandomPassword = function getRandomPassword() {85    return this.randomPassword;86  };87  /**88   * @returns {string} Generated random value included in devices hash.89   */90  AuthenticationHelper.prototype.getSaltDevices = function getSaltDevices() {91    return this.SaltToHashDevices;92  };93  /**94   * @returns {string} Value used to verify devices.95   */96  AuthenticationHelper.prototype.getVerifierDevices = function getVerifierDevices() {97    return this.verifierDevices;98  };99  /**100   * Generate salts and compute verifier.101   * @param {string} deviceGroupKey Devices to generate verifier for.102   * @param {string} username User to generate verifier for.103   * @param {nodeCallback<null>} callback Called with (err, null)104   * @returns {void}105   */106  AuthenticationHelper.prototype.generateHashDevice = function generateHashDevice(deviceGroupKey, username, callback) {107    var _this2 = this;108    this.randomPassword = this.generateRandomString();109    var combinedString = '' + deviceGroupKey + username + ':' + this.randomPassword;110    var hashedString = this.hash(combinedString);111    var hexRandom = util.crypto.lib.randomBytes(16).toString('hex');112    this.SaltToHashDevices = this.padHex(new BigInteger(hexRandom, 16));113    this.g.modPow(new BigInteger(this.hexHash(this.SaltToHashDevices + hashedString), 16), this.N, function (err, verifierDevicesNotPadded) {114      if (err) {115        callback(err, null);116      }117      _this2.verifierDevices = _this2.padHex(verifierDevicesNotPadded);118      callback(null, null);119    });120  };121  /**122   * Calculate the client's public value A = g^a%N123   * with the generated random number a124   * @param {BigInteger} a Randomly generated small A.125   * @param {nodeCallback<BigInteger>} callback Called with (err, largeAValue)126   * @returns {void}127   * @private128   */129  AuthenticationHelper.prototype.calculateA = function calculateA(a, callback) {130    var _this3 = this;131    this.g.modPow(a, this.N, function (err, A) {132      if (err) {133        callback(err, null);134      }135      if (A.mod(_this3.N).equals(BigInteger.ZERO)) {136        callback(new Error('Illegal paramater. A mod N cannot be 0.'), null);137      }138      callback(null, A);139    });140  };141  /**142   * Calculate the client's value U which is the hash of A and B143   * @param {BigInteger} A Large A value.144   * @param {BigInteger} B Server B value.145   * @returns {BigInteger} Computed U value.146   * @private147   */148  AuthenticationHelper.prototype.calculateU = function calculateU(A, B) {149    this.UHexHash = this.hexHash(this.padHex(A) + this.padHex(B));150    var finalU = new BigInteger(this.UHexHash, 16);151    return finalU;152  };153  /**154   * Calculate a hash from a bitArray155   * @param {Buffer} buf Value to hash.156   * @returns {String} Hex-encoded hash.157   * @private158   */159  AuthenticationHelper.prototype.hash = function hash(buf) {160    var hashHex = util.crypto.sha256(buf, 'hex');161    return new Array(64 - hashHex.length).join('0') + hashHex;162  };163  /**164   * Calculate a hash from a hex string165   * @param {String} hexStr Value to hash.166   * @returns {String} Hex-encoded hash.167   * @private168   */169  AuthenticationHelper.prototype.hexHash = function hexHash(hexStr) {170    return this.hash(new util.Buffer(hexStr, 'hex'));171  };172  /**173   * Standard hkdf algorithm174   * @param {Buffer} ikm Input key material.175   * @param {Buffer} salt Salt value.176   * @returns {Buffer} Strong key material.177   * @private178   */179  AuthenticationHelper.prototype.computehkdf = function computehkdf(ikm, salt) {180    var prk = util.crypto.hmac(salt, ikm, 'buffer', 'sha256');181    var infoBitsUpdate = util.buffer.concat([this.infoBits, new util.Buffer(String.fromCharCode(1), 'utf8')]);182    var hmac = util.crypto.hmac(prk, infoBitsUpdate, 'buffer', 'sha256');183    return hmac.slice(0, 16);184  };185  /**186   * Calculates the final hkdf based on computed S value, and computed U value and the key187   * @param {String} username Username.188   * @param {String} password Password.189   * @param {BigInteger} serverBValue Server B value.190   * @param {BigInteger} salt Generated salt.191   * @param {nodeCallback<Buffer>} callback Called with (err, hkdfValue)192   * @returns {void}193   */194  AuthenticationHelper.prototype.getPasswordAuthenticationKey = function getPasswordAuthenticationKey(username, password, serverBValue, salt, callback) {195    var _this4 = this;196    if (serverBValue.mod(this.N).equals(BigInteger.ZERO)) {197      throw new Error('B cannot be zero.');198    }199    this.UValue = this.calculateU(this.largeAValue, serverBValue);200    if (this.UValue.equals(BigInteger.ZERO)) {201      throw new Error('U cannot be zero.');202    }203    var usernamePassword = '' + this.poolName + username + ':' + password;204    var usernamePasswordHash = this.hash(usernamePassword);205    var xValue = new BigInteger(this.hexHash(this.padHex(salt) + usernamePasswordHash), 16);206    this.calculateS(xValue, serverBValue, function (err, sValue) {207      if (err) {208        callback(err, null);209      }210      var hkdf = _this4.computehkdf(new util.Buffer(_this4.padHex(sValue), 'hex'), new util.Buffer(_this4.padHex(_this4.UValue.toString(16)), 'hex'));211      callback(null, hkdf);212    });213  };214  /**215   * Calculates the S value used in getPasswordAuthenticationKey216   * @param {BigInteger} xValue Salted password hash value.217   * @param {BigInteger} serverBValue Server B value.218   * @param {nodeCallback<string>} callback Called on success or error.219   * @returns {void}220   */221  AuthenticationHelper.prototype.calculateS = function calculateS(xValue, serverBValue, callback) {222    var _this5 = this;223    this.g.modPow(xValue, this.N, function (err, gModPowXN) {224      if (err) {225        callback(err, null);226      }227      var intValue2 = serverBValue.subtract(_this5.k.multiply(gModPowXN));228      intValue2.modPow(_this5.smallAValue.add(_this5.UValue.multiply(xValue)), _this5.N, function (err2, result) {229        if (err2) {230          callback(err2, null);231        }232        callback(null, result.mod(_this5.N));233      });234    });235  };236  /**237  * Return constant newPasswordRequiredChallengeUserAttributePrefix238  * @return {newPasswordRequiredChallengeUserAttributePrefix} constant prefix value239  */240  AuthenticationHelper.prototype.getNewPasswordRequiredChallengeUserAttributePrefix = function getNewPasswordRequiredChallengeUserAttributePrefix() {241    return newPasswordRequiredChallengeUserAttributePrefix;242  };243  /**244   * Converts a BigInteger (or hex string) to hex format padded with zeroes for hashing245   * @param {BigInteger|String} bigInt Number or string to pad.246   * @returns {String} Padded hex string.247   */248  AuthenticationHelper.prototype.padHex = function padHex(bigInt) {249    var hashStr = bigInt.toString(16);250    if (hashStr.length % 2 === 1) {251      hashStr = '0' + hashStr;252    } else if ('89ABCDEFabcdef'.indexOf(hashStr[0]) !== -1) {253      hashStr = '00' + hashStr;254    }255    return hashStr;256  };257  return AuthenticationHelper;258}();...cli-authentication-helper-test.js
Source:cli-authentication-helper-test.js  
...22                './log':                log,23                '../utils/timer':       TimerConstructor,24                '../utils/get-any-key': getAnyKey25            });26            const { result, error } = await authenticationHelper(authFunction, Error);27            expect(error).be.undefined;28            expect(result).equal('OK');29            expect(getAnyKey.callCount).equal(2);30            expect(log.write.callCount).equal(2);31            expect(32                log.write.alwaysCalledWith(33                    'TestCafe requires permission to record the screen. ' +34                    'Open \'System Preferences > Security & Privacy > Privacy > Screen Recording\' and check ' +35                    '\'TestCafe Browser Tools\' in the application list.\n' +36                    '\n' +37                    'Press any key to retry.'38                ),39                log.write.args40            ).be.true;41        });42        it('Should retry until the timeout expires until permissions granted', async () => {43            const getAnyKey        = sinon.stub();44            const TimerConstructor = sinon.stub();45            const log              = { write: sinon.stub() };46            const authFunction = sinon.stub();47            const fakeTimer = new Timer(0);48            TimerConstructor.returns(fakeTimer);49            getAnyKey.resolves(new Promise(noop));50            authFunction51                .onCall(0).rejects(Error('Call 0'))52                .onCall(1).resolves('OK');53            const authenticationHelper = proxyquire('../../lib/cli/authentication-helper', {54                './log':                log,55                '../utils/timer':       TimerConstructor,56                '../utils/get-any-key': getAnyKey57            });58            const { result, error } = await authenticationHelper(authFunction, Error);59            expect(error).be.undefined;60            expect(result).equal('OK');61            expect(TimerConstructor.callCount).equal(1);62            expect(TimerConstructor.args[0]).deep.equal([30000]);63            expect(log.write.callCount).equal(1);64            expect(log.write.args[0]).deep.equal([65                'TestCafe requires permission to record the screen. ' +66                'Open \'System Preferences > Security & Privacy > Privacy > Screen Recording\' and check ' +67                '\'TestCafe Browser Tools\' in the application list.\n' +68                '\n' +69                'Press any key to retry.'70            ]);71        });72        it('Should return an error if the timeout expires and no permissions granted', async () => {73            const getAnyKey        = sinon.stub();74            const TimerConstructor = sinon.stub();75            const log              = { write: sinon.stub() };76            const authFunction = sinon.stub();77            const fakeTimer = new Timer(0);78            TimerConstructor.returns(fakeTimer);79            getAnyKey.resolves(new Promise(noop));80            authFunction.rejects(Error('Call'));81            const authenticationHelper = proxyquire('../../lib/cli/authentication-helper', {82                './log':                log,83                '../utils/timer':       TimerConstructor,84                '../utils/get-any-key': getAnyKey85            });86            const { result, error } = await authenticationHelper(authFunction, Error);87            expect(error.message).equal('Call');88            expect(result).be.undefined;89            expect(authFunction.callCount).equal(2);90            expect(TimerConstructor.callCount).equal(1);91            expect(TimerConstructor.args[0]).deep.equal([30000]);92            expect(getAnyKey.callCount).equal(1);93            expect(log.write.callCount).equal(1);94            expect(log.write.args[0]).deep.equal([95                'TestCafe requires permission to record the screen. ' +96                'Open \'System Preferences > Security & Privacy > Privacy > Screen Recording\' and check ' +97                '\'TestCafe Browser Tools\' in the application list.\n' +98                '\n' +99                'Press any key to retry.'100            ]);101        });102        it('Should throw if an unexpected error occurs', async () => {103            class CustomError extends Error {104            }105            const getAnyKey        = sinon.stub();106            const TimerConstructor = sinon.stub();107            const log              = { write: sinon.stub() };108            const authFunction = sinon.stub();109            const fakeTimer = new Timer(0);110            TimerConstructor.returns(fakeTimer);111            getAnyKey.resolves(new Promise(noop));112            authFunction.rejects(Error('Unexpected'));113            const authenticationHelper = proxyquire('../../lib/cli/authentication-helper', {114                './log':                log,115                '../utils/timer':       TimerConstructor,116                '../utils/get-any-key': getAnyKey117            });118            let unexpectedError = null;119            let result          = null;120            let error           = null;121            try {122                ({ result, error } = await authenticationHelper(authFunction, CustomError));123            }124            catch (e) {125                unexpectedError = e;126            }127            expect(unexpectedError.message).equal('Unexpected');128            expect(result).be.null;129            expect(error).be.null;130            expect(authFunction.callCount).equal(1);131            expect(TimerConstructor.callCount).equal(0);132            expect(getAnyKey.callCount).equal(0);133            expect(log.write.callCount).equal(0);134        });135    });136});login_steps.js
Source:login_steps.js  
1/* global module expect require client process */2module.exports = function () {3  'use strict';4  var helper = require('../_support/test-helper.js');5  var goHome = helper.goHome;6  var appName = helper.appName;7  var randomUsername = helper.randomUsername;8  var randomEmail = helper.randomEmail;9  var randomPassword = helper.randomPassword;10  var username;11  var email;12  var passwd;13  var dni;14  // https://gist.github.com/THuRStoN/946832415  function formatNumberLength(num, length) {16    var r = "" + num;17    while ( r.length < length ) {18      r = "0" + r;19    }20    return r;21  }22  function charDNI(dni) {23    var chain = "TRWAGMYFPDXBNJZSQVHLCKET";24    var pos = dni % 23;25    var letter = chain.substring( pos, pos + 1 );26    return letter;27  }28  function rand_dni() {29    var num = Math.floor( ( Math.random() * 100000000 ) );30    var sNum = formatNumberLength( num, 8 );31    return sNum + charDNI( sNum );32  }33  var generateUserData = function () {34    username = randomUsername();35    email = randomEmail();36    passwd = randomPassword();37    dni = rand_dni();38  };39  var createAccountAndLogin = function (callback, auth) {40    goHome(client);41    auth.logout(client);42    generateUserData();43    auth.createAccount(username, email, passwd, dni);44    auth.checkCurrentUser(username);45    callback();46  };47  this.Given(/^que me logeo con el usuario de pruebas$/, function (callback) {48    goHome(client);49    this.AuthenticationHelper.logout();50    this.AuthenticationHelper.loginUsername("test", email, "testtest");51    this.AuthenticationHelper.checkCurrentUser("test");52    callback();53  });54  this.Given(/^que tengo una cuenta y estoy logeado con ella$/, function (callback) {55    createAccountAndLogin(callback, this.AuthenticationHelper);56  });57  this.Given(/^I have an account and I logged in$/, function (callback) {58    createAccountAndLogin(callback, this.AuthenticationHelper);59  });60  this.Given(/^I am signed out$/, function (callback) {61    goHome(client);62    this.AuthenticationHelper.logout();63    callback();64  });65  this.Given(/^que no estoy logeado$/, function (callback) {66    goHome(client);67    this.AuthenticationHelper.logout();68    callback();69  });70  this.Given(/^que estoy en la página inicial$/, function (callback) {71    goHome(client);72    expect(client.getTitle()).toBe(appName);73    callback();74  });75  this.Given(/^I am on the home page$/, function (callback) {76    goHome(client);77    expect(client.getTitle()).toBe(appName);78    callback();79  });80  this.When(/^I click on sign in link$/, function (callback) {81    var doesExist = client.waitForExist('li#login-dropdown-list a');82    expect(doesExist).toBe(true);83    client.click('li#login-dropdown-list a');84    callback();85  });86  this.When(/^I enter my name and password$/, function (callback) {87    this.AuthenticationHelper.loginUsername(username, email, passwd);88    callback();89  });90  this.When(/^I enter my email and password$/, function (callback) {91    this.AuthenticationHelper.loginEmail(username, email, passwd);92    callback();93  });94  this.Then(/^I should be logged in$/, function (callback) {95    this.AuthenticationHelper.checkCurrentUser(username);96    // this.AuthenticationHelper.logout();97    callback();98  });99  this.Given(/^I register with some name, password and email$/, function (callback) {100    generateUserData();101    this.AuthenticationHelper.logout();102    this.AuthenticationHelper.registerUsername(username, email, passwd, dni, true);103    callback();104  });105  this.Given(/^que me registro con cierto nombre de usuario, contraseña y correo$/, function (callback) {106    generateUserData();107    this.AuthenticationHelper.logout();108    this.AuthenticationHelper.registerUsername(username, email, passwd, dni, true);109    callback();110  });111  this.Given(/^debo estar registrado$/, function (callback) {112    this.AuthenticationHelper.checkCurrentUser(username);113    callback();114  });115  this.Given(/^debo estar autenticado$/, function (callback) {116    this.AuthenticationHelper.checkCurrentUser(username);117    callback();118  });119  this.When(/^I enter incorrect authentication information$/, function (callback) {120    this.AuthenticationHelper.loginUsername("foo", "foo", "foo", true);121    callback();122  });123  this.Then(/^I should see a user not found error$/, function (callback) {124    client.waitForVisible('#login-dropdown-list > div > div.alert.alert-danger');125    // close dialog126    client.click("li#login-dropdown-list a");127    callback();128  });129  this.Then(/^I can edit my profile$/, function (callback) {130    // pending();131    client.url(process.env.ROOT_URL + "/yo");132    client.waitUntil(() => client.isVisible('.pg-loading-center-middle') === false, 10000);133    // Close alert134    if (client.isVisible('.bert-content')) {135      client.click('.bert-content');136    }137    // goHome(client);138    // this.AuthenticationHelper.loginEmail(username, email, passwd);139    // client.waitForExist('li#login-dropdown-list');140    // expect(client.isVisible('li#login-dropdown-list')).toBe(true);141    // client.click('li#login-dropdown-list');142    // client.waitForVisible('#login-buttons-open-change-settings');143    // client.click('#login-buttons-open-change-settings');144    client.waitForVisible('.UserUpdate');145    client.waitForExist('input[name="profile.dni"]');146    client.setValue('input[name="profile.dni"]', "70133390L");147    client.waitForVisible('.btn-form-submit', 5000);148    client.click(".btn-form-submit");149    callback();150  });151  this.Then(/^I should be registered$/, function (callback) {152    this.AuthenticationHelper.checkCurrentUser(username);153    callback();154  });155  this.Given(/^I register with some name, password and email but without accept conditions$/, function (callback) {156    generateUserData();157    this.AuthenticationHelper.logout();158    this.AuthenticationHelper.registerUsername(username, email, passwd, dni, false);159    callback();160  });161  this.Then(/^I shouldn't be registered$/, function (callback) {162    this.AuthenticationHelper.logout();163    expect(this.AuthenticationHelper.isNotLogged(client)).toBe(true);164    callback();165  });...get-books-and-related-tasks.test.js
Source:get-books-and-related-tasks.test.js  
1const ROUTE = '/user/:userId/book';2const request = require('supertest');3const app = require('../../../src/main/confing/app');4const { AuthenticationHelper, DataFakerHelper } = require('../../helpers');5const getRoute = ({ userId } = { userId: ':userId' }) => ROUTE.replace(':userId', userId);6const authenticationHelper = new AuthenticationHelper();7jest.unmock('jsonwebtoken');8jest.unmock('bcryptjs');9describe(`Given the ${getRoute()} route`, () => {10  describe('And a GET request is performed', () => {11    describe('And no authorization header is provided', () => {12      let response;13      beforeAll(async () => {14        response = await request(app)15          .get(getRoute({ userId: 'any_userId' }))16          .send({});17      });18      test('Then I expect it returns status code 401', () => {19        expect(response.status).toBe(401);20      });21    });22    describe('And an invalid authorization header is provided', () => {23      let response;24      beforeAll(async () => {25        response = await request(app)26          .get(getRoute({ userId: 'any_userId' }))27          .set({ authorization: 'Bearer' })28          .send({});29      });30      test('Then I expect it returns status code 401', () => {31        expect(response.status).toBe(401);32      });33    });34    describe('And an invalid userId is provided', () => {35      let response;36      beforeAll(async () => {37        const token = await authenticationHelper.getAccessToken();38        const authorization = `Bearer ${token}`;39        response = await request(app)40          .get(getRoute({ userId: 'any_userId' }))41          .set({ authorization })42          .send({});43      });44      test('Then I expect it returns status code 400', () => {45        expect(response.status).toBe(400);46      });47    });48    describe('And a non-existing userId is provided', () => {49      let response;50      beforeAll(async () => {51        const token = await authenticationHelper.getAccessToken();52        const authorization = `Bearer ${token}`;53        response = await request(app)54          .get(getRoute({ userId: DataFakerHelper.getUUID() }))55          .set({ authorization })56          .send({});57      });58      test('Then I expect it returns status code 404', () => {59        expect(response.status).toBe(404);60      });61    });62    describe('And an existing userId is provided', () => {63      describe('And a not allowed request is performed', () => {64        let response;65        beforeAll(async () => {66          const token = await authenticationHelper.getAccessToken();67          const authorization = `Bearer ${token}`;68          await authenticationHelper.createNewUser();69          const userFake = await authenticationHelper.getUser();70          response = await request(app)71            .get(getRoute({ userId: userFake.profile.PK.replace('USER#', '') }))72            .set({ authorization })73            .send({});74        });75        test('Then I expect it returns status code 403', () => {76          expect(response.status).toBe(403);77        });78      });79      describe('And an allowed request is performed', () => {80        describe('And the provided user has no book or task', () => {81          let response;82          beforeAll(async () => {83            await authenticationHelper.createNewUser({ hasBook: false, hasTask: false });84            const token = await authenticationHelper.getAccessToken();85            const authorization = `Bearer ${token}`;86            const userFake = await authenticationHelper.getUser();87            response = await request(app)88              .get(getRoute({ userId: userFake.profile.PK.replace('USER#', '') }))89              .set({ authorization })90              .send({});91          });92          test('Then I expect it returns status code 200', () => {93            expect(response.status).toBe(200);94          });95          test('Then I expect it returns the body with an empty array', () => {96            expect(response.body).toEqual([]);97          });98        });99        describe('And the provided user has at least one book and task', () => {100          let response;101          beforeAll(async () => {102            await authenticationHelper.createNewUser();103            const token = await authenticationHelper.getAccessToken();104            const authorization = `Bearer ${token}`;105            const userFake = await authenticationHelper.getUser();106            response = await request(app)107              .get(getRoute({ userId: userFake.profile.PK.replace('USER#', '') }))108              .set({ authorization })109              .send({});110          });111          test('Then I expect it returns status code 200', () => {112            expect(response.status).toBe(200);113          });114          test('Then I expect it returns the body with expected fields and types', () => {115            expect(response.body).toEqual(116              expect.arrayContaining([117                expect.objectContaining({118                  id: expect.any(String),119                  title: expect.any(String),120                  description: expect.any(String),121                  createdAt: expect.any(String),122                  tasks: expect.arrayContaining([123                    expect.objectContaining({124                      id: expect.any(String),125                      description: expect.any(String),126                      isDone: expect.any(Boolean),127                      createdAt: expect.any(String)128                    })129                  ])130                })131              ])132            );133          });134        });135      });136    });137  });...authenticationController.js
Source:authenticationController.js  
1const Boom = require('@hapi/boom');2const get = require('lodash/get');3const translate = require('../helpers/translate');4const AuthenticationHelper = require('../helpers/authentication');5const { language } = translate;6const authenticate = async (req, h) => {7  try {8    const authentication = await AuthenticationHelper.authenticate(req.payload);9    req.log('info', `${req.payload.email} connected`);10    return h.response({ message: translate[language].userAuthentified, data: { ...authentication } })11      .state('alenvi_token', authentication.token)12      .state('refresh_token', authentication.refreshToken);13  } catch (e) {14    req.log('error', e);15    return Boom.isBoom(e) ? e : Boom.badImplementation(e);16  }17};18/**19 * From MOBILE, refreshToken is in the payload20 * From WEBAPP, refresh_token is in the state21 */22const refreshToken = async (req, h) => {23  try {24    const userRefreshToken = get(req, 'payload.refreshToken') || get(req, 'state.refresh_token');25    const token = await AuthenticationHelper.refreshToken(userRefreshToken);26    return h.response({ message: translate[language].userAuthentified, data: { ...token } })27      .state('alenvi_token', token.token)28      .state('refresh_token', token.refreshToken);29  } catch (e) {30    req.log('error', e);31    return Boom.isBoom(e) ? e : Boom.badImplementation(e);32  }33};34const logout = async (req, h) => {35  try {36    return h.response({ message: translate[language].userLogout })37      .unstate('alenvi_token')38      .unstate('refresh_token');39  } catch (e) {40    req.log('error', e);41    return Boom.isBoom(e) ? e : Boom.badImplementation(e);42  }43};44const createPasswordToken = async (req) => {45  try {46    const passwordToken = await AuthenticationHelper.createPasswordToken(req.payload.email);47    return {48      message: translate[language].resetPasswordTokenFound,49      data: { passwordToken },50    };51  } catch (e) {52    req.log('error', e);53    return Boom.isBoom(e) ? e : Boom.badImplementation(e);54  }55};56const forgotPassword = async (req) => {57  try {58    const mailInfo = await AuthenticationHelper.forgotPassword(req.payload);59    return { message: translate[language].emailSent, data: { mailInfo } };60  } catch (e) {61    req.log('error', e);62    return Boom.isBoom(e) ? e : Boom.badImplementation(e);63  }64};65const checkPasswordToken = async (req, h) => {66  try {67    const token = await AuthenticationHelper.checkPasswordToken(req.params.token, req.query.email);68    return h.response({ message: translate[language].resetPasswordTokenFound, data: { ...token } })69      .state('alenvi_token', token.token);70  } catch (e) {71    req.log('error', e);72    return Boom.isBoom(e) ? e : Boom.badImplementation(e);73  }74};75const updatePassword = async (req) => {76  try {77    const updatedUser = await AuthenticationHelper.updatePassword(req.params._id, req.payload);78    return { message: translate[language].userUpdated, data: { updatedUser } };79  } catch (e) {80    req.log('error', e);81    return Boom.isBoom(e) ? e : Boom.badImplementation(e);82  }83};84module.exports = {85  authenticate,86  logout,87  createPasswordToken,88  refreshToken,89  forgotPassword,90  checkPasswordToken,91  updatePassword,...restifyClient.js
Source:restifyClient.js  
1const restify      = require('restify');2const paginate       = require('restify-paginate');3function RestifyClient() {4    this.server = "";5};6RestifyClient.prototype.createClient = function(databaseHelper, authenticationHelper)7{8    this.server = restify.createServer({9        name: 'AZ Games - Testing server'10    });11    this.server.use(restify.authorizationParser());12    this.server.use(restify.queryParser());13    this.server.use(restify.bodyParser());14    this.server.use(paginate(this.server, {hostname: false, numbersOnly: true, defaults:{page: 1,per_page: 10},}));15    var products        = require('../../endpoints/products')(this.server, databaseHelper, authenticationHelper);16    var user            = require('../../endpoints/user')(this.server, databaseHelper, authenticationHelper);17    var wishlist        = require('../../endpoints/wishlist')(this.server, databaseHelper, authenticationHelper);18    var order           = require('../../endpoints/order')(this.server, databaseHelper, authenticationHelper);19    var admin           = require('../../endpoints/admin')(this.server, databaseHelper, authenticationHelper);20    var public_wishlist = require('../../endpoints/public_wishlist')(this.server, databaseHelper, authenticationHelper);21    var favoritelist    = require('../../endpoints/favoritelist')(this.server, databaseHelper, authenticationHelper);22    var stats           = require('../../endpoints/stats')(this.server, databaseHelper, authenticationHelper);23    // Start server and listen to port 808324    this.server.listen(8083);25    // Start client to Tests26    return restify.createJsonClient({27        version: '*',28        url: 'http://127.0.0.1:8083',29    });30}31RestifyClient.prototype.destroyClient = function()32{33    this.server.close();34}...auth.js
Source:auth.js  
1import axios from 'axios';2import AuthenticationHelper from '~/services/authenticationHelper';3import { AUTHENTICATION_REQUEST } from '~/actions/BusinessActionTypes';4const authenticationMiddleware = store => next => (action) => {5  axios.defaults.headers.common.Authorization = `Bearer ${AuthenticationHelper.getToken()}`;6  const result = next(action);7  if (result) {8    const { payload } = result;9    if (payload && payload.response && payload.response.status === 401) {10      store.dispatch({11        type: AUTHENTICATION_REQUEST,12        payload: null,13      });14    }15  }16  return result;17};...Using AI Code Generation
1import { authenticationHelper } from './authenticationHelper';2import { Selector } from 'testcafe';3test('Login', async t => {4    await authenticationHelper(t, 'user', 'pass');5    const title = Selector('h1').innerText;6    await t.expect(title).eql('Hello World!');7});8import { RequestLogger } from 'testcafe';9export async function authenticationHelper(t, user, pass) {10        .typeText('input[name="username"]', user)11        .typeText('input[name="password"]', pass)12        .click('button[type="submit"]')13        .expect(loginPage.contains(r => r.response.statusCode === 302)).ok();14}Using AI Code Generation
1import { ClientFunction } from 'testcafe';2import { authenticationHelper } from './authenticationHelper';3import { Selector } from 'testcafe';4test('Authentication', async t => {5    await authenticationHelper(t, 'username', 'password');6        .typeText(Selector('input[name="q"]'), 'TestCafe')7        .click(Selector('input[value="Google Search"]'))8        .wait(1000);9});10import { ClientFunction } from 'testcafe';11import { Selector } from 'testcafe';12export async function authenticationHelper(t, username, password) {13        .setNativeDialogHandler(() => true)14        .click(Selector('a[href*="accounts.google.com"]'))15        .typeText(Selector('#identifierId'), username)16        .click(Selector('#identifierNext'))17        .typeText(Selector('input[type="password"]'), password)18        .click(Selector('#passwordNext'));19    await t.eval(() => location.reload(true));20}21await authenticationHelper(t, 'username', 'password');Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!
