Giải pháp cho NodeJS với SecretHash
Có vẻ ngớ ngẩn khi AWS đã xóa khóa bí mật khỏi SDK vì nó sẽ không bị lộ trong NodeJS.
Tôi đã làm cho nó hoạt động trong NodeJS bằng cách chặn tìm nạp và thêm vào khóa băm bằng câu trả lời của @Simon Buchan .
cognito.js
import { CognitoUserPool, CognitoUserAttribute, CognitoUser } from 'amazon-cognito-identity-js'
import crypto from 'crypto'
import * as fetchIntercept from './fetch-intercept'
const COGNITO_SECRET_HASH_API = [
'AWSCognitoIdentityProviderService.ConfirmForgotPassword',
'AWSCognitoIdentityProviderService.ConfirmSignUp',
'AWSCognitoIdentityProviderService.ForgotPassword',
'AWSCognitoIdentityProviderService.ResendConfirmationCode',
'AWSCognitoIdentityProviderService.SignUp',
]
const CLIENT_ID = 'xxx'
const CLIENT_SECRET = 'xxx'
const USER_POOL_ID = 'xxx'
const hashSecret = (clientSecret, username, clientId) => crypto.createHmac('SHA256', clientSecret)
.update(username + clientId)
.digest('base64')
fetchIntercept.register({
request(url, config) {
const { headers } = config
if (headers && COGNITO_SECRET_HASH_API.includes(headers['X-Amz-Target'])) {
const body = JSON.parse(config.body)
const { ClientId: clientId, Username: username } = body
// eslint-disable-next-line no-param-reassign
config.body = JSON.stringify({
...body,
SecretHash: hashSecret(CLIENT_SECRET, username, clientId),
})
}
return [url, config]
},
})
const userPool = new CognitoUserPool({
UserPoolId: USER_POOL_ID,
ClientId: CLIENT_ID,
})
const register = ({ email, password, mobileNumber }) => {
const dataEmail = { Name: 'email', Value: email }
const dataPhoneNumber = { Name: 'phone_number', Value: mobileNumber }
const attributeList = [
new CognitoUserAttribute(dataEmail),
new CognitoUserAttribute(dataPhoneNumber),
]
return userPool.signUp(email, password, attributeList, null, (err, result) => {
if (err) {
console.log((err.message || JSON.stringify(err)))
return
}
const cognitoUser = result.user
console.log(`user name is ${cognitoUser.getUsername()}`)
})
}
export {
register,
}
fetch-inceptor.js ( Được chia và chỉnh sửa cho NodeJS từ Fork của https://github.com/werk85/fetch-intercept/blob/develop/src/index.js )
let interceptors = []
if (!global.fetch) {
try {
// eslint-disable-next-line global-require
global.fetch = require('node-fetch')
} catch (err) {
throw Error('No fetch available. Unable to register fetch-intercept')
}
}
global.fetch = (function (fetch) {
return (...args) => interceptor(fetch, ...args)
}(global.fetch))
const interceptor = (fetch, ...args) => {
const reversedInterceptors = interceptors.reduce((array, _interceptor) => [_interceptor].concat(array), [])
let promise = Promise.resolve(args)
// Register request interceptors
reversedInterceptors.forEach(({ request, requestError }) => {
if (request || requestError) {
promise = promise.then(_args => request(..._args), requestError)
}
})
// Register fetch call
promise = promise.then(_args => fetch(..._args))
// Register response interceptors
reversedInterceptors.forEach(({ response, responseError }) => {
if (response || responseError) {
promise = promise.then(response, responseError)
}
})
return promise
}
const register = (_interceptor) => {
interceptors.push(_interceptor)
return () => {
const index = interceptors.indexOf(_interceptor)
if (index >= 0) {
interceptors.splice(index, 1)
}
}
}
const clear = () => {
interceptors = []
}
export {
register,
clear,
}