I trying to imlement the device tracking login but confirmDevice command is giving ingative salt or password verifire always.Some time it also show invalid device key.
error is error: InvalidParameterException: Found negative value for salt or password verifier.
export async function authenticateUser(
email: string,
password: string,
code?: string
): Promise<IResponseSignIn> {
try {
const cognitoClient = new CognitoIdentityProvider({
region: process.env.POOL_REGION,
credentials: {
accessKeyId: process.env.AWSAccessKeyId,
secretAccessKey: process.env.AWSSecretAccessKey,
},
});
//calculate srp
const userPoolId = process.env.USER_POOL_ID.split("_")[1];
const srp = new SRPClient(userPoolId);
const SRP_A = srp.calculateA();
const device = new DeviceHelper("", "");
// const srp_A = device.srpa();
const secret_hash = calculateSecretHash(process.env.CLIENT_ID, email);
const params: InitiateAuthCommandInput = {
AuthFlow: AuthFlowType.USER_SRP_AUTH,
AuthParameters: {
USERNAME: email,
SRP_A: SRP_A,
},
ClientId: process.env.CLIENT_ID,
};
const authCommand = new InitiateAuthCommand(params);
const authResponse = await cognitoClient.send(authCommand);
if (authResponse.ChallengeName === "NEW_PASSWORD_REQUIRED") {
const challengeParams: RespondToAuthChallengeCommandInput = {
ChallengeName: "NEW_PASSWORD_REQUIRED",
ClientId: process.env.CLIENT_ID,
ChallengeResponses: {
USERNAME: email,
NEW_PASSWORD: password,
},
Session: authResponse.Session,
};
const challengeCommand = new RespondToAuthChallengeCommand(
challengeParams
);
const challengeResponse = await cognitoClient.send(challengeCommand);
return {
access_token: challengeResponse.AuthenticationResult.AccessToken,
refresh_token: authResponse.AuthenticationResult.RefreshToken,
};
}
else if (authResponse.ChallengeName === "SOFTWARE_TOKEN_MFA") {
const challengeResponse = await handleSoftwareTokenMfa(
code,
email,
authResponse.Session,
secret_hash
);
return {
access_token: challengeResponse.AuthenticationResult.AccessToken,
refresh_token: challengeResponse.AuthenticationResult.RefreshToken,
};
} else if (authResponse.ChallengeName === "PASSWORD_VERIFIER") {
const salt = authResponse.ChallengeParameters.SALT;
const userIdForSrp = authResponse.ChallengeParameters.USER_ID_FOR_SRP;
const srp_b = authResponse.ChallengeParameters.SRP_B;
const secretBlock = authResponse.ChallengeParameters.SECRET_BLOCK;
const username = authResponse.ChallengeParameters.USERNAME;
const hkdf = srp.getPasswordAuthenticationKey(
userIdForSrp,
password,
srp_b,
salt
);
const dateNow = getNowString();
const signatureString = calculateSignature(
hkdf,
userPoolId,
userIdForSrp,
secretBlock,
dateNow
);
const challengeParams: RespondToAuthChallengeCommandInput = {
ChallengeName: "PASSWORD_VERIFIER",
ClientId: process.env.CLIENT_ID,
ChallengeResponses: {
PASSWORD_CLAIM_SIGNATURE: signatureString,
PASSWORD_CLAIM_SECRET_BLOCK: secretBlock,
TIMESTAMP: dateNow,
USERNAME: username,
SECRET_HASH: secret_hash,
},
Session: authResponse.Session,
};
const challengeCommand = new RespondToAuthChallengeCommand(
challengeParams
);
const challengeResponsePasswordVerifier = await cognitoClient.send(
challengeCommand
);
let challengeResponse;
if (
challengeResponsePasswordVerifier.ChallengeName === "SOFTWARE_TOKEN_MFA"
) {
challengeResponse = await handleSoftwareTokenMfa(
code,
email,
challengeResponsePasswordVerifier.Session,
secret_hash
);
}
const device_key =
challengeResponse.AuthenticationResult.NewDeviceMetadata.DeviceKey;
const access_token = challengeResponse.AuthenticationResult.AccessToken;
const device_group_key =
challengeResponse.AuthenticationResult.NewDeviceMetadata.DeviceGroupKey;
const deviceHelper = new DeviceHelper(device_key, device_group_key);
const verifierConfig = deviceHelper.passwordVerifierConfig(username);
// register a device
const isDevice = await handleConfirmDevice(
access_token,
device_key,
`${username}${device_key}`,
verifierConfig.salt,
verifierConfig.passwordVerifier
);
if (isDevice) {
await handleUpdateDeviceStatus(access_token, device_key, "remembered");
}
return {
access_token: challengeResponse.AuthenticationResult.AccessToken,
refresh_token: challengeResponse.AuthenticationResult.RefreshToken,
};
}
}
I am expecting it should return true and then updateDeviceStatus will run with device_key set to “remembered”
Pankaj Singh Parihar is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.