Amazon Cognito Kullanıcı Havuzlarında istemci için gizli karma doğrulanamıyor


132

"Amazon Cognito Identity kullanıcı havuzları" sürecine takılı kaldım.

Cognito kullanıcı havuzlarında kullanıcının kimliğini doğrulamak için olası tüm kodları denedim. Ama her zaman "Hata: İstemci 4b ******* fd için gizli karma doğrulanamıyor" diyerek hata alıyorum .

İşte kod:

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);
});

9
Kabul edilen cevap artık geçerli DEĞİLDİR. Gizli hash oluşturma talimatları burada verilmiştir docs.aws.amazon.com/cognito/latest/developerguide/…
jasiustasiu

Evet, JavaScript uygulaması için aşağıdaki @ Simon Buchan yanıtına bakın. Mükemmel çalışıyor.
guzmonne

Yanıtlar:


183

Görünüşe göre şu anda AWS Cognito istemci sırrını mükemmel şekilde ele almıyor. Yakın gelecekte çalışacak ama şimdilik hala beta sürümü.

Benim için istemci sırrı olmayan bir uygulama için iyi çalışıyor, ancak istemci sırrı olan bir uygulama için başarısız oluyor.

Dolayısıyla, kullanıcı havuzunuzda bir istemci sırrı oluşturmadan yeni bir uygulama oluşturmaya çalışın. Ardından yeni bir kullanıcı kaydetmek veya kaydı onaylamak için bu uygulamayı kullanın.


14
Bilginize: Bu şimdi başıma geldi. Hala bu şekilde çalışıyor, Ocak 2017. client_secret içermeyen bir uygulama oluşturduğumda JS SDK'yı kullanabildim. Client_secret ile bir uygulama oluşturduğumda, orijinal soru ile aynı başarısızlık elde ettim.
Cheeso

5
21 Nisan 2017 itibarıyla, gizli anahtar Uygulama İstemcisi için etkinleştirildiğinde AWS CLI kullanılarak hala çalışmamaktadır. aws cognito-idp admin-startup-auth \ --region ap-kuzeydoğu-1 \ --kullanıcı havuzu-kimliği MY_POOL_ID \ --client-id MY_CLIENT_ID \ --auth-flow ADMIN_NO_SRP_AUTH \ --auth-parameters USERNAME = kullanıcı adı @ gmail.com, ŞİFRE = som3PassW0rd
Stanley Yong

26
Ocak 2018 itibarıyla bu hala desteklenmemektedir. Github repo github.com/aws/amazon-cognito-identity-js üzerindeki dokümantasyon bundan bahsediyor:"When creating the App, the generate client secret box must be unchecked because the JavaScript SDK doesn't support apps that have a client secret."
kakoma

5
Mayıs19 2018, aynı hata, istemci sırrı olmadan uygulama oluşturmamız gerekiyor.
Dileep

4
12 Eylül 2018 - Aynı sorun. Sır üreten bir istemci kullanmadığımda bile, kullanıcının kimliği doğrulanmış olsun ya da olmasın bir 400 alıyorum. Ancak buna rağmen uygulama beklendiği gibi çalışıyor.
foxtrotuniform6969


37

Bu birkaç yıl geç olabilir, ancak "İstemci sırrı oluştur" seçeneğinin işaretini kaldırın ve web istemcileriniz için çalışacaktır.

uygulama istemcisi oluştur seçeneği


8
İstemci oluşturduktan sonra düzenleyemeyeceğinizi unutmayın, bu nedenle gerekirse yeni bir tane oluşturun.
URL87

Yeni bir uygulama istemcisi oluşturursanız ve bir Cognito kimlik doğrulama sağlayıcısı kullanan bir kimlik havuzunuz ("Birleşik Kimlikler" üzerinde) varsa, uygulama istemcisi kimliği alanını yeni uygulama istemcisinin kimliğiyle güncellemeyi unutmayın.
AMS777

21

Diğer herkes kendi dilini yayınladığından, işte düğüm (ve tarayıcıda çalışır, web browserify-cryptopaketi veya browsererify kullanıyorsanız otomatik olarak kullanılır):

const crypto = require('crypto');

...

crypto.createHmac('SHA256', clientSecret)
  .update(username + clientId)
  .digest('base64')

4
bu basit ve en iyi yerleşik çözüm Node.js, teşekkürler @simon
Engineer

19

.Net SDK'da da aynı sorunu yaşadım.

Başkasının ihtiyaç duyması durumunda, şu şekilde çözdüm:

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;
        }
    }
}

Kaydolmak şu şekilde görünür:

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;
    }
}

Bunun hala gerekli olduğunu ve v3.5 AWS .NET SDK'da (önizleme) çalıştığını onaylama.
pastaSquared

13

AWS JS SDK kullanarak bir kullanıcıyı kaydettirmek için AWS Lambda'yı kullanmak isteyenler için yaptığım adımlar şunlar:

Anahtarı oluşturmak için python'da başka bir lambda işlevi oluşturun:

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

AWS'deki nodeJS işlevi aracılığıyla işlevi çağırın. İmza, Cognito için gizli hash görevi gördü

Not: Cevap, büyük ölçüde George Campbell'ın aşağıdaki bağlantıdaki cevabına dayanmaktadır: python'da bir dize + gizli anahtar ile bir SHA karmasının hesaplanması


12

Çözüm golang. Bunun SDK'ya eklenmesi gerekiyor gibi görünüyor.

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

8

SecretHash ile NodeJS için Çözüm

AWS'nin NodeJS'de açığa çıkmayacağı için gizli anahtarı SDK'dan kaldırması aptalca görünüyor.

Getirmeyi durdurarak ve @ Simon Buchan'ın cevabını kullanarak karma anahtarı ekleyerek NodeJS'de çalışmasını sağladım .

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 ( https://github.com/werk85/fetch-intercept/blob/develop/src/index.js adresinden Fork'tan NodeJS için çatallanmış ve düzenlenmiştir )

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,
}

Prosedürünüzün ardından kaydolabildim, ancak bu işlemi kullanarak oturum açamıyorum. Oturum açmak için yapılması gereken herhangi bir değişiklik var mı? Buraya ekleyebilirseniz çok yardımcı olacaktır. Şimdiden teşekkürler.
Vinay Wadagavi

8

Amazon , Java uygulama kodu içeren belgelerinde Amazon Cognito için Hesaplama SecretHash Değerlerinin nasıl olduğundan bahsediyor . İşte bu kod boto 3 Python SDK ile çalışır .

uygulama istemcisi ayrıntıları

Eğer bulabilirsiniz App clientsaltındaki sol taraftaki menüde General settings. Bunları alın App client idve App client secretyaratın SECRET_HASH. Daha iyi anlayabilmeniz için her satırın tüm çıktılarını yorumladım.

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=

Gelen boto 3 dokümantasyon, zaman çok sormak görebilirsiniz SECRET_HASH. Yani yukarıdaki kod satırları bunu oluşturmanıza yardımcı olur SECRET_HASH.

SECRET_HASHKullanmak istemiyorsanız, Generate client secretbir uygulama oluştururken işaretini kaldırmanız yeterlidir .

yeni uygulama oluştur


1
Benim için bu yalnızca msg = bayt (app_client_id + kullanıcı adı, 'latin-1') 'yi msg = bayt (kullanıcıadı + app_client_id,' latin-1 ') olarak değiştirdiğimde işe yaradı. Açık olmak gerekirse, clientId ve kullanıcı adının sırasını, kullanıcı adı önce görünecek şekilde değiştirdim.
Josh Wolff

1
Çok teşekkürler @JoshWolff, yanlışlıkla takas ettim app_client_idve username. Ama doğru çıktıyı username+ 'ya göre görüntüleyen bir yorum olarak gösteriyorum app_client_id. Tekrar ve tekrar çok teşekkürler.
Kushan Gunasekera

1
Hiç sorun değil! @Kushan Gunasekera
Josh Wolff

7

Java'da şu kodu kullanabilirsiniz:

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);
}

Bu gizli hash'i ekrana çıkarmanın yanı sıra SDK'da nerede kullanıyorsunuz?
Aaron

1
İstemci sırrına göre kimlik doğrulamanın açıklandığı herhangi bir çevrimiçi AWS belgesine işaret eden var mı? Base64 / sha256 imza kodlamaları ilgi çekici çözümlerdir, ancak istemci sırrına göre nasıl kimlik doğrulaması yapılacağını açıklayan AWS belgeleriyle açıkça uyumlu olmadıkça değersizdir.
Kode Charlie

6

bu, gizli hash oluşturmak için kullandığım örnek bir php kodudur

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

bu durumda sonuç:

DdSuILDJ2V84zfOChcn6TfgmlfnHsUYq0J6c01QV43I=

5

JAVA ve .NET için, yetkilendirme parametrelerindeki gizli bilgileri adıyla birlikte iletmeniz gerekir 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
};

Ve işe yaramalı.


3

Qt Framework ile C ++

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

1

Daha kompakt bir sürüm olabilir, ancak bu Ruby için, özellikle Ruby on Rails'de hiçbir şeye ihtiyaç duymadan çalışır:

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

0

Cognito Kimlik Doğrulaması

Hata: Uygulama istemcisi gizli olarak yapılandırılmadı, ancak gizli karma alındı

SecretKey'i sıfır olarak sağlamak benim için çalıştı. Sağlanan kimlik bilgileri şunları içerir: -

  • CognitoIdentityUserPoolRegion (bölge)
  • CognitoIdentityUserPoolId (userPoolId)
  • CognitoIdentityUserPoolAppClientId (ClientId)
  • AWSCognitoUserPoolsSignInProviderKey (AccessKeyId)

    // setup service configuration
    let serviceConfiguration = AWSServiceConfiguration(region: CognitoIdentityUserPoolRegion, credentialsProvider: nil)
    
    // create pool configuration
    let poolConfiguration = AWSCognitoIdentityUserPoolConfiguration(clientId: CognitoIdentityUserPoolAppClientId,
                                                                    clientSecret: nil,
                                                                    poolId: CognitoIdentityUserPoolId)
    
    // initialize user pool client
    AWSCognitoIdentityUserPool.register(with: serviceConfiguration, userPoolConfiguration: poolConfiguration, forKey: AWSCognitoUserPoolsSignInProviderKey)
    

Yukarıdaki her şey aşağıdaki bağlantılı kod örneğiyle çalışır.

AWS Örnek kodu: https://github.com/awslabs/aws-sdk-ios-samples/tree/master/CognitoYourUserPools-Sample/Swift

İşe yaramazsa bana haber ver.


bu ölü bir bağlantı
Jpnh

0

İşte benim 1 komutum ve çalışıyor (Onaylandı :))

EMAIL="EMAIL@HERE.com" \
CLIENT_ID="[CLIENT_ID]" \
CLIENT_SECRET="[CLIENT_ID]" \
&& SECRET_HASH=$(echo -n "${EMAIL}${CLIENT_ID}" | openssl dgst -sha256 -hmac "${CLIENT_SECRET}" | xxd -r -p | openssl base64) \
&& aws cognito-idp ...  --secret-hash "${SECRET_HASH}"
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.