Impossible de vérifier le hachage secret pour le client dans les pools d’utilisateurs Amazon Cognito

Je suis coincé au processus des “pools d’utilisateurs Amazon Cognito Identity”.

J’ai essayé tous les codes possibles pour authentifier l’utilisateur dans les pools d’utilisateurs cognito. Mais j’ai toujours une erreur en disant “Erreur: Impossible de vérifier le hachage secret pour le client 4b ******* fd”.

Voici le code:

AWS.config.region = 'us-east-1'; // Region AWS.config.credentials = new AWS.CognitoIdentityCredentials({ IdentityPoolId: 'us-east-1:b64bb629-ec73-4569-91eb-0d950f854f4f' }); AWSCognito.config.region = 'us-east-1'; AWSCognito.config.credentials = new AWS.CognitoIdentityCredentials({ IdentityPoolId: 'us-east-1:b6b629-er73-9969-91eb-0dfffff445d' }); AWSCognito.config.update({accessKeyId: 'AKIAJNYLRONAKTKBXGMWA', secretAccessKey: 'PITHVAS5/UBADLU/dHITesd7ilsBCm'}) var poolData = { UserPoolId : 'us-east-1_l2arPB10', ClientId : '4bmsrr65ah3oas5d4sd54st11k' }; var userPool = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserPool(poolData); var userData = { Username : 'ronakpatel@gmail.com', Pool : userPool }; var cognitoUser = new AWSCognito.CognitoIdentityServiceProvider.CognitoUser(userData); cognitoUser.confirmRegistration('123456', true,function(err, result) { if (err) { alert(err); return; } console.log('call result: ' + result); }); 

Il semble que AWS Cognito ne gère pas parfaitement le secret client. Il fonctionnera dans un futur proche mais pour le moment c’est toujours une version bêta.

Pour moi, cela fonctionne très bien pour une application sans secret client mais échoue pour une application avec un secret client.

Donc, dans votre pool d’utilisateurs, essayez de créer une nouvelle application sans générer de secret client. Ensuite, utilisez cette application pour inscrire un nouvel utilisateur ou pour confirmer votre inscription.

Selon les documents: http://docs.aws.amazon.com/cognito/latest/developerguide/setting-up-the-javascript-sdk.html

Le SDK Javascript ne prend pas en charge les applications avec un secret client.

Les instructions indiquent maintenant que vous devez décocher l’option “Générer le secret du client” lors de la création de l’application pour le pool d’utilisateurs.

Pour toute personne intéressée par l’utilisation d’AWS Lambda pour inscrire un utilisateur à l’aide du kit SDK AWS JS, voici les étapes que j’ai effectuées:

Créez une autre fonction lambda en python pour générer la clé:

 import hashlib import hmac import base64 secretKey = "key" clientId = "clientid" digest = hmac.new(secretKey, msg=username + clientId, digestmod=hashlib.sha256 ).digest() signature = base64.b64encode(digest).decode() 

Appelez la fonction via la fonction nodeJS dans AWS. La signature a agi comme le hash secret pour Cognito

Note: La réponse est largement basée sur la réponse de George Campbell dans le lien suivant: Calcul d’un hachage SHA avec une chaîne + clé secrète en python

Solution pour le golang . Cela semble être ajouté au SDK.

 import ( "crypto/hmac" "crypto/sha256" "encoding/base64" ) func SecretHash(username, clientID, clientSecret ssortingng) ssortingng { mac := hmac.New(sha256.New, []byte(clientSecret)) mac.Write([]byte(username + ClientID)) return base64.StdEncoding.EncodeToSsortingng(mac.Sum(nil)) } 

J’ai eu le même problème dans le kit de développement .net.

Voici comment j’ai résolu le problème, au cas où quelqu’un en aurait besoin:

 public static class CognitoHashCalculator { public static ssortingng GetSecretHash(ssortingng username, ssortingng appClientId, ssortingng appSecretKey) { var dataSsortingng = username + appClientId; var data = Encoding.UTF8.GetBytes(dataSsortingng); var key = Encoding.UTF8.GetBytes(appSecretKey); return Convert.ToBase64Ssortingng(HmacSHA256(data, key)); } public static byte[] HmacSHA256(byte[] data, byte[] key) { using (var shaAlgorithm = new System.Security.Cryptography.HMACSHA256(key)) { var result = shaAlgorithm.ComputeHash(data); return result; } } } 

L’inscription ressemble alors à ceci:

 public class CognitoSignUpController { private readonly IAmazonCognitoIdentityProvider _amazonCognitoIdentityProvider; public CognitoSignUpController(IAmazonCognitoIdentityProvider amazonCognitoIdentityProvider) { _amazonCognitoIdentityProvider = amazonCognitoIdentityProvider; } public async Task SignUpAsync(ssortingng userName, ssortingng password, ssortingng email) { try { var request = CreateSignUpRequest(userName, password, email); var authResp = await _amazonCognitoIdentityProvider.SignUpAsync(request); return true; } catch { return false; } } private static SignUpRequest CreateSignUpRequest(ssortingng userName, ssortingng password, ssortingng email) { var clientId = ConfigurationManager.AppSettings["ClientId"]; var clientSecretId = ConfigurationManager.AppSettings["ClientSecretId"]; var request = new SignUpRequest { ClientId = clientId, SecretHash = CognitoHashCalculator.GetSecretHash(userName, clientId, clientSecretId), Username = userName, Password = password, }; request.UserAtsortingbutes.Add("email", email); return request; } } 

En Java, vous pouvez utiliser ce code:

 private Ssortingng getSecretHash(Ssortingng email, Ssortingng appClientId, Ssortingng appSecretKey) throws Exception { byte[] data = (email + appClientId).getBytes("UTF-8"); byte[] key = appSecretKey.getBytes("UTF-8"); return Base64.encodeAsSsortingng(HmacSHA256(data, key)); } static byte[] HmacSHA256(byte[] data, byte[] key) throws Exception { Ssortingng algorithm = "HmacSHA256"; Mac mac = Mac.getInstance(algorithm); mac.init(new SecretKeySpec(key, algorithm)); return mac.doFinal(data); } 

Comme tout le monde a posté sa langue, voici node (et cela fonctionne dans le navigateur avec browserify-crypto , automatiquement utilisé si vous utilisez webpack ou browserify):

 const crypto = require('crypto'); ... crypto.createHmac('SHA256', clientSecret) .update(username + clientId) .digest('base64') 

Cela peut prendre quelques années, mais décochez l’option “Générer un secret client” et cela fonctionnera pour vos clients Web.

générer une option client d'application

c’est un exemple de code php que j’utilise pour générer le hash secret

  

dans ce cas le résultat est: DdSuILDJ2V84zfOChcn6TfgmlfnHsUYq0J6c01QV43I =

pour JAVA et .NET, vous devez transmettre le secret dans les parameters d’authentification sous le nom SECRET_HASH .

 AdminInitiateAuthRequest request = new AdminInitiateAuthRequest { ClientId = this.authorizationSettings.AppClientId, AuthFlow = AuthFlowType.ADMIN_NO_SRP_AUTH, AuthParameters = new Dictionary { {"USERNAME", username}, {"PASSWORD", password}, { "SECRET_HASH", EncryptionHelper.GetSecretHash(username, AppClientId, AppClientSecret) } }, UserPoolId = this.authorizationSettings.UserPoolId }; 

Et ça devrait marcher.

C ++ avec le framework Qt

 QByteArray MyObject::secretHash( const QByteArray& email, const QByteArray& appClientId, const QByteArray& appSecretKey) { QMessageAuthenticationCode code(QCryptographicHash::Sha256); code.setKey(appSecretKey); code.addData(email); code.addData(appClientId); return code.result().toBase64(); }; 

Solution pour NodeJS avec SecretHash

Il semble idiot qu’AWS ait supprimé la clé secrète du SDK car elle ne sera pas exposée dans NodeJS.

Je l ‘ai fait fonctionner dans NodeJS en interceptant l’ extraction et en ajoutant la clé hachée en utilisant la réponse de @Simon Buchan .

cognito.js

 import { CognitoUserPool, CognitoUserAtsortingbute, 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.ssortingngify({ ...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 atsortingbuteList = [ new CognitoUserAtsortingbute(dataEmail), new CognitoUserAtsortingbute(dataPhoneNumber), ] return userPool.signUp(email, password, atsortingbuteList, null, (err, result) => { if (err) { console.log((err.message || JSON.ssortingngify(err))) return } const cognitoUser = result.user console.log(`user name is ${cognitoUser.getUsername()}`) }) } export { register, } 

fetch-inceptor.js ( Fourré et édité pour NodeJS de Fork of 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, }