現象
下記のコードで NotAuthorizedException: Unable to verify secret hash for client xxx
が発生。
secretHashの生成方法は間違っていないはずなのになぜ...?と若干ハマりました。
const { username, password } = req.body
const cognitoidentityserviceprovider = new AWS.CognitoIdentityServiceProvider()
const secretHash = crypto
.createHmac('SHA256', ClientSecret)
.update(username + ClientId)
.digest('base64')
// ログイン
const data = await cognitoidentityserviceprovider
.adminInitiateAuth({
UserPoolId,
ClientId,
AuthFlow: 'ADMIN_NO_SRP_AUTH',
AuthParameters: {
USERNAME: username,
PASSWORD: password,
SECRET_HASH: secretHash
}
})
.promise()
// ログイン成功
const { AuthenticationResult } = data
// リフレッシュトークンを取得
// => NotAuthorizedException発生
await cognitoidentityserviceprovider
.adminInitiateAuth({
UserPoolId,
ClientId,
AuthFlow: 'REFRESH_TOKEN_AUTH',
AuthParameters: {
REFRESH_TOKEN: AuthenticationResult.RefreshToken,
SECRET_HASH: secretHash
}
})
.promise()
原因
結局、ログイン時のUSERNAMEはユーザーから入力されたEmail等を利用してsecretHashを作成するのですが、ログイン後はCognito User Poolsで割り振られたusername(ユニークなID)を利用しなければならないのでした。これはわかりにくい。
const jwt = require('jsonwebtoken')
const secretHash = crypto
.createHmac('SHA256', ClientSecret)
.update(jwt(AuthenticationResult.AccessToken).username + ClientId) // 本番環境では署名検証が必要です
.digest('base64')