AWS Cognito SRP Client
This library provides a client-side implementation for the Secure Remote Password (SRP) authentication flow specifically designed for AWS Cognito User Pools. It abstracts away the complex cryptographic calculations required for SRP_A generation and signature verification, enabling developers to integrate SRP authentication into both browser and Node.js environments. The current stable version is 1.0.0, indicating a relatively new, but stable, initial release. Its primary function is to work in conjunction with the AWS SDK's `initiateAuth` and `respondToAuthChallenge` APIs for the `USER_SRP_AUTH` and `PASSWORD_VERIFIER` flows, respectively, handling the core SRP computations rather than the network requests themselves. It is differentiated by its focused scope on SRP, providing a streamlined experience for this specific Cognito authentication method.
Common errors
-
AuthFlow is not supported for this user pool.
cause The Cognito User Pool App Client is not configured to allow the USER_SRP_AUTH flow.fixIn your AWS Cognito console, navigate to your User Pool, then App Clients, and ensure the 'Enable SRP' checkbox is selected for the relevant App Client. -
Invalid parameter: SECRET_HASH
cause This error often occurs when your Cognito App Client is configured with a client secret, but you're not providing `SECRET_HASH` in the `AuthParameters` of `initiateAuth` or `respondToAuthChallenge`.fixIf your App Client has a client secret, you must generate and include a `SECRET_HASH` in your Cognito API calls. Alternatively, configure your App Client *without* a client secret if it's a public client (e.g., mobile or web app). -
User does not exist.
cause The username provided to `initiateAuth` does not correspond to an existing user in the Cognito User Pool.fixEnsure the username is correct and the user has been created and confirmed in the Cognito User Pool. -
TypeScript error: Module 'aws-cognito-srp-client' has no default export.
cause You are attempting to import `Srp` as a named import (e.g., `import { Srp } from '...'`) when it is exported as a default.fixChange your import statement to use a default import: `import Srp from 'aws-cognito-srp-client';`
Warnings
- gotcha This library exclusively handles the cryptographic SRP calculations. It does *not* make API calls to AWS Cognito itself. You must use the AWS SDK (e.g., `@aws-sdk/client-cognito-identity-service-provider`) to perform `initiateAuth` and `respondToAuthChallenge`.
- gotcha The `secret` parameter in `srp.getSignature()` corresponds to the `SECRET_BLOCK` value received from Cognito's `initiateAuth` response, not a user-defined secret.
- gotcha Cognito User Pools must be configured to allow `USER_SRP_AUTH` as an authentication flow for the App Client. If not enabled, the `initiateAuth` call will fail.
- gotcha Securely handling user passwords and the SRP process client-side requires careful attention to security best practices. Avoid logging sensitive data and ensure your environment (browser/Node.js) is secure against common client-side attacks.
Install
-
npm install aws-cognito-srp-client -
yarn add aws-cognito-srp-client -
pnpm add aws-cognito-srp-client
Imports
- Srp
import { Srp } from 'aws-cognito-srp-client';import Srp from 'aws-cognito-srp-client';
- Srp (CommonJS)
const { Srp } = require('aws-cognito-srp-client');const Srp = require('aws-cognito-srp-client'); - Type (Srp instance)
import Srp from 'aws-cognito-srp-client'; const mySrp: Srp = new Srp('us-east-1_XXXXX');
Quickstart
import Srp from 'aws-cognito-srp-client';
import { CognitoIdentityServiceProvider } from '@aws-sdk/client-cognito-identity-service-provider';
const userPoolId = 'us-east-1_XXXXX'; // Replace with your Cognito User Pool ID
const clientId = 'YYYYYYYYYYYYYYYYYYYYYYYYY'; // Replace with your Cognito App Client ID
const username = 'testuser'; // The user's username
const password = 'StrongPassword123!'; // The user's password
const cognitoClient = new CognitoIdentityServiceProvider({
region: 'us-east-1' // Replace with your AWS Region
});
async function authenticateUser() {
const srp = new Srp(userPoolId);
const srpA = srp.getA();
console.log('Step 1: Generated SRP_A');
// Step 2: Initiate Auth with Cognito
const initiateAuthResponse = await cognitoClient.initiateAuth({
AuthFlow: 'USER_SRP_AUTH',
AuthParameters: {
USERNAME: username,
SRP_A: srpA
},
ClientId: clientId
});
console.log('Step 2: Initiate Auth response received');
const challengeParameters = initiateAuthResponse.ChallengeParameters;
if (!challengeParameters) {
throw new Error('No challenge parameters received.');
}
const srpB = challengeParameters.SRP_B;
const salt = challengeParameters.SALT;
const secretBlock = challengeParameters.SECRET_BLOCK;
// Step 3: Calculate signature and timestamp
const { signature, timestamp } = srp.getSignature(
username,
srpB,
salt,
secretBlock,
password
);
console.log('Step 3: Calculated signature and timestamp');
// Step 4: Respond to Auth Challenge
const respondToChallengeResponse = await cognitoClient.respondToAuthChallenge({
ChallengeName: 'PASSWORD_VERIFIER',
ChallengeResponses: {
USERNAME: username,
PASSWORD_CLAIM_SECRET_BLOCK: secretBlock,
PASSWORD_CLAIM_SIGNATURE: signature,
TIMESTAMP: timestamp
},
ClientId: clientId,
Session: initiateAuthResponse.Session // Pass the session token
});
console.log('Authentication successful! Token:', respondToChallengeResponse.AuthenticationResult?.AccessToken);
return respondToChallengeResponse.AuthenticationResult;
}
authenticateUser().catch(console.error);