Open7
JavaScript V3 srp login cognito
Email でもログインできるが、内部的なユーザー名は Email でない、というセットアップだったのでハマった
import {
createPasswordHash,
createSrpSession,
signSrpSession,
wrapAuthChallenge,
wrapInitiateAuth,
} from "cognito-srp-helper";
import {
CognitoIdentityProviderClient,
InitiateAuthCommand,
RespondToAuthChallengeCommand,
} from "@aws-sdk/client-cognito-identity-provider";
interface CognitoSrpSecrets {
userPoolId: string;
clientId: string;
username: string;
password: string;
}
export const userPoolSrpSignIn = async ({userPoolId, clientId, username, password}: CognitoSrpSecrets) => {
const passwordHash = createPasswordHash(username, password, userPoolId);
const initialSrpSession = createSrpSession(username, passwordHash, userPoolId);
const client = new CognitoIdentityProviderClient();
const initiateAuthRes = await client.send(
new InitiateAuthCommand(
wrapInitiateAuth(initialSrpSession, {
ClientId: clientId,
AuthFlow: "USER_SRP_AUTH",
AuthParameters: {
CHALLENGE_NAME: "SRP_A",
USERNAME: username,
},
}),
),
);
const srpSession = (() => {
const userId = initiateAuthRes.ChallengeParameters!.USER_ID_FOR_SRP;
const passwordHash = createPasswordHash(userId, password, userPoolId);
return {
...initialSrpSession,
username: userId,
passwordHash,
}
})()
const signedSrpSession = signSrpSession(srpSession, initiateAuthRes);
const respondToAuthChallengeRes = await client.send(
new RespondToAuthChallengeCommand(
wrapAuthChallenge(signedSrpSession, {
ClientId: clientId,
ChallengeName: initiateAuthRes.ChallengeName,
ChallengeResponses: {
USERNAME: initiateAuthRes.ChallengeParameters!.USERNAME,
},
}),
),
)
return respondToAuthChallengeRes.AuthenticationResult!
}
library に PR だして修正してもらうまでは↑のやり方で。
メモ: client secret がない場合はなくすだけで OK
メモ: type がないので使えないが README はとても参考になる
type がないので使えない。参考にはなるかも
interface は最高! ただし AWS SDK V2 依存なので利用はやめた。GitHub が消えている。
cognito-srp-helper は crypto-js に依存しており、arm ではエラーが起きてしまう。
amazon-cognito-identity-js を使うのがよさそう。
amazon-cognito-identity-js の authenticateUser を async/await で利用する:
const asyncAuthenticateUser = async (cognitoUser: CognitoUser, cognitoAuthenticationDetails: AuthenticationDetails) => {
const result = await new Promise(function(resolve, reject) {
cognitoUser.authenticateUser(cognitoAuthenticationDetails, {
onSuccess: resolve,
onFailure: reject,
newPasswordRequired: resolve
})
});
if (!(result instanceof CognitoUserSession)) {
throw new Error('Failed to authenticate user');
}
return result;
}