Amazon Cognito Userpool में क्लाइंट के लिए गुप्त हैश को सत्यापित करने में असमर्थ


131

मैं "Amazon Cognito Identity user pools" प्रक्रिया में फंस गया हूं।

मैंने उपयोगकर्ता को कॉगनिटो उपयोगकर्ता में प्रमाणित करने के लिए सभी संभव कोड आज़माए। लेकिन मुझे हमेशा यह कहते हुए त्रुटि मिलती है कि "त्रुटि: क्लाइंट 4b ******* fd के लिए गुप्त हैश को सत्यापित करने में असमर्थ"।

यहाँ कोड है:

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
स्वीकृत उत्तर अब मान्य नहीं है। निर्देश कैसे गुप्त हैश उत्पन्न करने के लिए यहाँ हैं docs.aws.amazon.com/cognito/latest/developerguide/...
jasiustasiu

हां, और जावास्क्रिप्ट कार्यान्वयन के लिए नीचे @Simon बुकान जवाब देखें। यह पूरी तरह से काम करता है।
गुज्मोने

जवाबों:


182

ऐसा लगता है कि वर्तमान में AWS Cognito क्लाइंट सीक्रेट को पूरी तरह से हैंडल नहीं करता है। यह निकट भविष्य में काम करेगा लेकिन अभी तक इसका बीटा संस्करण है।

मेरे लिए यह क्लाइंट सीक्रेट के बिना किसी ऐप के लिए ठीक काम कर रहा है लेकिन क्लाइंट सीक्रेट वाले ऐप के लिए फेल है।

तो अपने उपयोगकर्ता पूल में एक ग्राहक रहस्य पैदा किए बिना एक नया ऐप बनाने का प्रयास करें। फिर एक नए उपयोगकर्ता को साइन अप करने या पंजीकरण की पुष्टि करने के लिए उस ऐप का उपयोग करें।


14
FYI करें: यह सिर्फ मेरे लिए हुआ, अभी-अभी। यह अभी भी इस तरह से काम कर रहा है, जनवरी 2017. जब मैंने कोई क्लाइंट_सेक्रेट वाला ऐप बनाया, तो मैं जेएस एसडीके का उपयोग करने में सक्षम था। जब मैंने एक client_secret के साथ एक ऐप बनाया, तो मुझे मूल प्रश्न में उसी तरह का दोष मिला।
चीजो

5
21 अप्रैल 2017 तक, यह तब भी काम नहीं करता है जब ऐप क्लाइंट के लिए गुप्त कुंजी सक्षम होने पर AWS CLI का उपयोग कर रहा हो। aws cognito-idp admin-आरंभ-उत्तरोत्तर- aurion ap-Northeast-1 \ _user-pool-id MY_POOL_ID \ --client-id MY_CLIENT_ID \ _auth-flow ADMIN_NO_SRP_AUTH \ --auth-पैरामीटर USERNAME = उपयोगकर्ता नाम @ gmail.com, PASSWORD = som3PassW0rd
स्टेनली योंग

26
जनवरी 2018 तक, यह अभी भी समर्थित नहीं है। Github repo पर प्रलेखन github.com/aws/amazon-cognito-identity-js में इसका उल्लेख है:"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."
काकोमा

5
May19 2018, एक ही त्रुटि हमें क्लाइंट सीक्रेट के बिना ऐप बनाने की आवश्यकता है।
दिलीप

4
12 सितंबर 2018 - एक ही मुद्दा। यहां तक ​​कि जब एक ग्राहक जो एक गुप्त उत्पन्न करता है, का उपयोग नहीं कर रहा है, तो मुझे एक 400 मिलता है कि क्या उपयोगकर्ता प्रमाणित है या नहीं। हालांकि इसके बावजूद भी ऐप कार्य करता है।
foxtrotuniform6969

70

डॉक्स के अनुसार: http://docs.aws.amazon.com/cognito/latest/developerguide/setting-up-the-javascript-sdk.html

जावास्क्रिप्ट SDK क्लाइंट सीक्रेट वाले ऐप्स का समर्थन नहीं करता है।

अब निर्देश बताता है कि उपयोगकर्ता पूल के लिए ऐप बनाते समय आपको "जनरेट क्लाइंट सीक्रेट" को अनचेक करना होगा।


यह सर्वर साइड पर Node.js का उपयोग करके मेरे लिए काम करता है। धन्यवाद डॉक्टर!
रिक

37

यह कुछ साल देरी से हो सकता है लेकिन "जेनरेट क्लाइंट सीक्रेट" विकल्प को अनचेक करें और यह आपके वेब क्लाइंट के लिए काम करेगा।

एप्लिकेशन क्लाइंट विकल्प उत्पन्न करें


8
ध्यान दें कि ग्राहक द्वारा बनाए जाने के बाद आप उसे संपादित नहीं कर सकते हैं, इसलिए यदि आवश्यक हो तो एक नया बनाएं।
URL87

यदि आप एक नया ऐप क्लाइंट बनाते हैं और आपके पास एक पहचान पूल था ("Federated Identities" पर) जो एक Cognito प्रमाणीकरण प्रदाता का उपयोग करता है, तो नए ऐप क्लाइंट की आईडी के साथ ऐप क्लाइंट आईडी फ़ील्ड को अपडेट करने के लिए याद रखें।
AMS777

21

चूंकि बाकी सभी ने अपनी भाषा पोस्ट की है, यहां नोड (और यह ब्राउज़र में काम करता है browserify-crypto, स्वचालित रूप से उपयोग किया जाता है यदि आप वेबपैक या ब्राउज़र का उपयोग करते हैं:

const crypto = require('crypto');

...

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

4
यह सरल और सबसे अच्छा Node.js समाधान में बनाया गया है, धन्यवाद @simon
इंजीनियर

19

मुझे .net SDK में भी यही समस्या थी।

यहां बताया गया है कि किसी और की ज़रूरत पड़ने पर मैंने इसे कैसे हल किया:

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

साइन अप करना इस तरह दिखता है:

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

यह पुष्टि करते हुए कि यह अभी भी आवश्यक है और अभी भी v3.5 AWS .NET SDK (पूर्वावलोकन) में काम करता है।
२:३१ बजे पाईसुकेरेड

13

AWS जेएस एसडीके का उपयोग करके उपयोगकर्ता को साइन अप करने के लिए AWS लैम्ब्डा का उपयोग करने में रुचि रखने वाले किसी भी व्यक्ति के लिए, मैंने ये कदम उठाए हैं:

कुंजी उत्पन्न करने के लिए अजगर में एक और मेमना कार्य बनाएँ:

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 में नोडजेएस फ़ंक्शन के माध्यम से फ़ंक्शन को कॉल करें। हस्ताक्षर ने कॉग्निटो के लिए गुप्त हैश के रूप में काम किया

नोट: उत्तर जॉर्ज लिंकबेल के उत्तर पर दिए गए लिंक पर बहुत हद तक आधारित है: अजगर में स्ट्रिंग + गुप्त कुंजी के साथ SHA हैश की गणना


12

के लिए समाधान golang। ऐसा लगता है कि एसडीके में जोड़ा जाना चाहिए।

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 के साथ NodeJS के लिए समाधान

यह मूर्खतापूर्ण लगता है कि AWS ने SDK से गुप्त कुंजी को हटा दिया क्योंकि यह NodeJS में उजागर नहीं की जाएगी।

मैं इसे NodeJS में काम कर रहा था और भ्रूण को इंटरसेप्ट करके @Simon बुकान के उत्तर का उपयोग करके हैश कीड में जोड़ दिया।

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://kithub.com/werk85/fetch-intercept/blob/develop/src/index.js के Fork से NodeJS के लिए forked और संपादित )

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

मैं आपकी प्रक्रिया के बाद साइनअप करने में सक्षम था, लेकिन मैं इस खरीद का उपयोग करने में साइन इन करने में असमर्थ हूं। क्या कोई संशोधन है जिसे साइन इन करने के लिए किए जाने की आवश्यकता है? यदि आप इसे यहां जोड़ सकते हैं तो यह बहुत उपयोगी होगा। अग्रिम में धन्यवाद।
विनय वदगावी

7

जावा में आप इस कोड का उपयोग कर सकते हैं:

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

आप इस गुप्त हैश का उपयोग स्क्रीन पर आउटपुट करने के अलावा एसडीके में कहां करते हैं?
हारून

1
क्या कोई भी किसी भी एडब्ल्यूएस डॉक्स को ऑनलाइन इंगित कर सकता है जहां क्लाइंट सीक्रेट के खिलाफ प्रमाणित किया जाता है? Base64 / sha256 हस्ताक्षर-एनकोडिंग समाधानों को मजबूर कर रहे हैं - लेकिन बेकार जब तक कि वे स्पष्ट रूप से AWS डॉक्स के साथ अनुपालन नहीं करते हैं कि ग्राहक रहस्य के खिलाफ कैसे प्रमाणित करें।
कोडे चार्ली

7

अमेज़ॅन का उल्लेख है कि अमेज़ॅन कॉग्निटो के लिए कम्प्यूटिंग सीक्रेटहैश वैल्यू कैसे जावा एप्लीकेशन कोड के साथ अपने दस्तावेज में । यहाँ यह कोड बोटो 3 पायथन एसडीके के साथ काम करता है ।

एप्लिकेशन क्लाइंट विवरण

आप अपने पा सकते हैं App clients नीचे बाईं ओर मेनू मेंGeneral settings । उन जाओ App client idऔर App client secretबनाने के लिए SECRET_HASH। आपकी बेहतर समझ के लिए मैंने प्रत्येक और हर पंक्ति के सभी आउटपुट पर टिप्पणी की।

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=

में Boto 3 प्रलेखन, हम समय के बहुत के बारे में पूछने देख सकते हैं SECRET_HASH। तो ऊपर की पंक्तियाँ आपको इसे बनाने में मदद करती हैं SECRET_HASH

यदि आप ऐप बनाते समय SECRET_HASHसिर्फ अनचेक का उपयोग नहीं करना चाहते हैं Generate client secret

नया ऐप बनाएं


1
मेरे लिए, यह केवल तभी काम करता है जब मैंने msg = bytes (app_client_id + username, 'latin-1') को msg = bytes (उपयोगकर्ता नाम + app_client_id, 'latin-1') स्विच किया। स्पष्ट होने के लिए, मैंने क्लाइंटआईडी और उपयोगकर्ता नाम के क्रम को बदल दिया, जैसे कि उपयोगकर्ता नाम पहले दिखाई देता है।
जोश वोल्फ

1
बहुत बहुत धन्यवाद @ जोशफ्लेफ़, मैंने गलती से अदला app_client_id- बदली कर ली username। लेकिन मैं एक टिप्पणी के रूप में सही आउटपुट प्रदर्शित करता हूं जो कि username+ के अनुसार प्रदर्शित होता है app_client_id। बार-बार धन्यवाद।
कुषाण गुनासेकरा

1
बिल्कुल भी परेशानी नहीं है! @ कुशन गुणसेकेरा
जोश वोल्फ

6

यह एक नमूना php कोड है जिसका उपयोग मैं गुप्त हैश उत्पन्न करने के लिए करता हूं

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

इस मामले में परिणाम है:

DdSuILDJ2V84zfOChcn6TfgmlfnHsUYq0J6c01QV43I=

5

JAVA और .NET के लिए आपको नाम के साथ गुप्त पैरामीटर में पास करना होगा 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
};

और यह काम करना चाहिए।


3

क्यू ++ फ्रेमवर्क के साथ सी ++

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

अधिक कॉम्पैक्ट संस्करण हो सकता है, लेकिन यह रूबी के लिए काम करता है, विशेष रूप से रूबी ऑन रेल्स में कुछ भी आवश्यकता के बिना:

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 Authentication

त्रुटि: ऐप क्लाइंट को गुप्त के लिए कॉन्फ़िगर नहीं किया गया है लेकिन गुप्त हैश प्राप्त हुआ था

गुप्त प्रदान करना नील के रूप में मेरे लिए काम किया। प्रदान की गई साख में शामिल हैं: -

  • CognitoIdentityUserPoolRegion (क्षेत्र)
  • 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)
    

उपरोक्त सभी चीजें नीचे दिए गए कोड नमूने के साथ काम करती हैं।

एडब्ल्यूएस नमूना कोड: https://github.com/awslabs/aws-sdk-ios-samples/tree/master/CognitoYourUserPools-ample/Swift

मुझे पता है कि अगर आप के लिए काम नहीं करता है।


यह एक मृत कड़ी है
Jpnh

0

यहाँ मेरी 1 कमांड है, और यह काम करता है (पुष्टि :)

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}"
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.