Note 1: I'm not using the SDK and instead using direct https requests because the SDK does not currently let you send a secret hash. But I don't think it is relevant other than understanding some of my code formatting.
Note 2: I can not use the Hosted UI instead because of the web page I am working on having certain URL requirements that AWS does not support.
I am trying to determine why my request to verify a user is coming back with "Invalid username or password" from AWS and it seems like I must be generating some of the challenge response data incorrectly. Specifically the PASSWORD_CLAIM_SECRET_BLOCK and PASSWORD_CLAIM_SIGNATURE. being the most likely culprits.
Based on my code does anyone see why it is failing to respond with something other than "Invalid username or password"? They are setup this way based on what I have found online. I don't know SRP Authentication very well.
I have confirmed that the username and password I am generating them from is correct by logging in thru the Hosted UI.
My code to generate the challengeResponseData looks something like:
const SECRET_HASH = Auth.createSecretHash(params['userName'], process.env.AWS_COGNITO_CLIENT_ID);
const PASSWORD_CLAIM_SECRET_BLOCK = Auth.generatePasswordSecretBlock(params['password'], params['salt'], params['srpB']);
const PASSWORD_CLAIM_SIGNATURE = Auth.generatePasswordClaimSignature(params['userName'], PASSWORD_CLAIM_SECRET_BLOCK, params['userIDForSRP']);
const TIME_STAMP = DateTime.now().toFormat("EEE MMM d HH:mm:ss z yyyy").toString();
challengeResponseData['ChallengeResponses'] = {
USERNAME: params['userName'],
PASSWORD_CLAIM_SECRET_BLOCK: PASSWORD_CLAIM_SECRET_BLOCK,
PASSWORD_CLAIM_SIGNATURE: PASSWORD_CLAIM_SIGNATURE,
TIMESTAMP: TIME_STAMP,
SECRET_HASH: SECRET_HASH,
};
The Auth methods referenced looking like:
export default class Auth {
static createSecretHash(username, clientId) {
const HMAC = crypto.createHmac("sha256", process.env.AWS_COGNITO_CLIENT_SECRET);
HMAC.update(username + clientId);
return HMAC.digest("base64");
};
static generatePasswordSecretBlock(password, salt, srpB) {
const passwordHash = crypto.createHash('sha256').update(salt + password).digest('hex');
return crypto.createHash('sha256').update(srpB + passwordHash).digest('hex');
}
static generatePasswordClaimSignature(username, passwordClaimSecretBlock, userIDForSRP) {
const HMAC = crypto.createHmac("sha256", process.env.AWS_COGNITO_CLIENT_SECRET);
const message = username + passwordClaimSecretBlock + userIDForSRP;
return HMAC.update(message).digest('hex');
}
static generateSRP() {
// Generate SRP_A
const srpASizeBits = 256; // Size of SRP_A in bits
const srpA = crypto.randomBytes(srpASizeBits / 8);
// Convert SRP_A to hexadecimal string
return srpA.toString('hex');
};
}