verificar sha256sum revisar que puede integridad comprobar amazon-web-services amazon-cognito

amazon web services - sha256sum - No se puede verificar el hash secreto para el cliente en Amazon Cognito Userpools



sha256sum que es (14)

Estoy atascado en el proceso "Grupos de usuarios de Amazon Cognito Identity".

Intenté todos los códigos posibles para autenticar usuarios en grupos de usuarios cognito. Pero siempre recibo un error que dice "Error: no se puede verificar el hash secreto para el cliente 4b ******* fd".

Aquí está el código:

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 : ''[email protected]'', 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); });


C ++ con el marco 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(); };


Como todos los demás han publicado su idioma, aquí está el nodo (y funciona en el navegador con browserify-crypto , que se usa automáticamente si usa webpack o browserify):

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



En Java podrías usar este código:

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


Esto podría demorar algunos años, pero simplemente desmarque la opción "Generar secreto de cliente" y funcionará para sus clientes web.


Para cualquiera que esté interesado en usar AWS Lambda para inscribir a un usuario con AWS JS SDK, estos son los pasos que hice:

Cree otra función lambda en python para generar la clave:

public static class CognitoHashCalculator { public static string GetSecretHash(string username, string appClientId, string appSecretKey) { var dataString = username + appClientId; var data = Encoding.UTF8.GetBytes(dataString); var key = Encoding.UTF8.GetBytes(appSecretKey); return Convert.ToBase64String(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; } } }

Llame a la función a través de la función nodeJS en AWS. La firma actuó como el hash secreto para Cognito

Nota: La respuesta se basa en gran medida en la respuesta de George Campbell en el siguiente enlace: Cálculo de un hash SHA con una cadena + clave secreta en python


Parece que actualmente AWS Cognito no maneja el secreto del cliente a la perfección. Funcionará en el futuro cercano, pero por ahora sigue siendo una versión beta.

Para mí está funcionando bien para una aplicación sin un secreto de cliente, pero falla para una aplicación con un secreto de cliente.

Entonces, en su grupo de usuarios, intente crear una nueva aplicación sin generar un secreto de cliente. Luego use esa aplicación para registrar un nuevo usuario o para confirmar el registro.


Puede haber una versión más compacta, pero esto funciona para Ruby, específicamente en Ruby on Rails sin tener que requerir nada:

key = ENV[''COGNITO_SECRET_HASH''] data = username + ENV[''COGNITO_CLIENT_ID''] digest = OpenSSL::Digest.new(''sha256'') hmac = Base64.strict_encode64(OpenSSL::HMAC.digest(digest, key, data))


Solución para golang . Parece que esto debería agregarse al SDK.

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


Tuve el mismo problema en el SDK de .net.

Así es como lo resolví, en caso de que alguien más lo necesite:

public class CognitoSignUpController { private readonly IAmazonCognitoIdentityProvider _amazonCognitoIdentityProvider; public CognitoSignUpController(IAmazonCognitoIdentityProvider amazonCognitoIdentityProvider) { _amazonCognitoIdentityProvider = amazonCognitoIdentityProvider; } public async Task<bool> SignUpAsync(string userName, string password, string email) { try { var request = CreateSignUpRequest(userName, password, email); var authResp = await _amazonCognitoIdentityProvider.SignUpAsync(request); return true; } catch { return false; } } private static SignUpRequest CreateSignUpRequest(string userName, string password, string 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.UserAttributes.Add("email", email); return request; } }

Registrarse se ve así:

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()


este es un código php de muestra que uso para generar el hash secreto

<?php $userId = "aaa"; $clientId = "bbb"; $clientSecret = "ccc"; $s = hash_hmac(''sha256'', $userId.$clientId, $clientSecret, true); echo base64_encode($s); ?>

en este caso el resultado es:

DdSuILDJ2V84zfOChcn6TfgmlfnHsUYq0J6c01QV43I=


para JAVA y .NET necesita pasar el secreto que tiene en los parámetros de autenticación con el nombre SECRET_HASH .

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

Y debería funcionar.


Amazon menciona cómo Computing SecretHash Values para Amazon Cognito en su documentación con el código de la aplicación Java. Aquí este código funciona con boto 3 Python SDK .

Puede encontrar sus App clients en el menú del lado izquierdo en General settings . Obtenga la App client id y el App client secret para crear SECRET_HASH . Para su mejor comprensión, comenté todos los resultados de cada línea.

import hashlib import hmac import base64 app_client_secret = ''u8f323eb3itbr3731014d25spqtv5r6pu01olpp5tm8ebicb8qa'' app_client_id = ''396u9ekukfo77nhcfbmqnrec8p'' username = ''wasdkiller'' # convert str to bytes key = bytes(app_client_secret, ''latin-1'') # b''u8f323eb3itbr3731014d25spqtv5r6pu01olpp5tm8ebicb8qa'' msg = bytes(username + app_client_id, ''latin-1'') # b''wasdkiller396u9ekukfo77nhcfbmqnrec8p'' new_digest = hmac.new(key, msg, hashlib.sha256).digest() # b''P$#/xd6/xc1/xc0U/xce/xc1$/x17/xa1=/x18L/xc5/x1b/xa4/xc8/xea,/x92/xf5/xb9/xcdM/xe4/x084/xf5/x03~'' SECRET_HASH = base64.b64encode(new_digest).decode() # UCQj1sHAVc7BJBehPRhMxRukyOoskvW5zU3kCDT1A34=

En la documentación del boto 3 , podemos ver mucho tiempo preguntando sobre SECRET_HASH . Entonces, las líneas de código anteriores lo ayudan a crear este SECRET_HASH .

Si no desea utilizar SECRET_HASH simplemente desactive Generate client secret al crear una aplicación.


Solución para NodeJS con SecretHash

Parece una tontería que AWS haya eliminado la clave secreta del SDK, ya que no estará expuesta en NodeJS.

Lo hice funcionar en NodeJS interceptando fetch y agregando la clave hash usando la respuesta de @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 ( Bifurcado y editado para NodeJS de Fork de 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, }