python - 如何使用 boto3 为 AWS Cognito 创建 SECRET_HASH?

标签 python amazon-web-services boto3 amazon-cognito hmac

我想使用 boto3 和 python 为 AWS Cognito 创建/计算 SECRET_HASH。这将合并到我的 warrant 分支中.

我将我的 Cognito 应用程序客户端配置为使用应用程序客户端密码。但是,这破坏了以下代码。

def renew_access_token(self):
    """
    Sets a new access token on the User using the refresh token.

    NOTE:
    Does not work if "App client secret" is enabled. 'SECRET_HASH' is needed in AuthParameters.
    'SECRET_HASH' requires HMAC calculations.

    Does not work if "Device Tracking" is turned on.
    https://stackoverflow.com/a/40875783/1783439

    'DEVICE_KEY' is needed in AuthParameters. See AuthParameters section.
    https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html
    """
    refresh_response = self.client.initiate_auth(
        ClientId=self.client_id,
        AuthFlow='REFRESH_TOKEN',
        AuthParameters={
            'REFRESH_TOKEN': self.refresh_token
            # 'SECRET_HASH': How to generate this?
        },
    )

    self._set_attributes(
        refresh_response,
        {
            'access_token': refresh_response['AuthenticationResult']['AccessToken'],
            'id_token': refresh_response['AuthenticationResult']['IdToken'],
            'token_type': refresh_response['AuthenticationResult']['TokenType']
        }
    )

当我运行它时,我收到以下异常:

botocore.errorfactory.NotAuthorizedException: 
An error occurred (NotAuthorizedException) when calling the InitiateAuth operation: 
Unable to verify secret hash for client <client id echoed here>.

This answer通知我需要 SECRET_HASH 才能使用 cognito 客户端密码。

aws API reference docs AuthParameters 部分说明如下:

For REFRESH_TOKEN_AUTH/REFRESH_TOKEN: USERNAME (required), SECRET_HASH (required if the app client is configured with a client secret), REFRESH_TOKEN (required), DEVICE_KEY

boto3 docs说明 SECRET_HASH 是

A keyed-hash message authentication code (HMAC) calculated using the secret key of a user pool client and username plus the client ID in the message.

文档解释了需要什么,但没有说明如何实现。

最佳答案

下面的 get_secret_hash 方法是我用 Python 为 Cognito 用户池实现编写的解决方案,示例用法:

import boto3
import botocore
import hmac
import hashlib
import base64


class Cognito:
    client_id = app.config.get('AWS_CLIENT_ID')
    user_pool_id = app.config.get('AWS_USER_POOL_ID')
    identity_pool_id = app.config.get('AWS_IDENTITY_POOL_ID')
    client_secret = app.config.get('AWS_APP_CLIENT_SECRET')
    # Public Keys used to verify tokens returned by Cognito:
    # http://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-with-identity-providers.html#amazon-cognito-identity-user-pools-using-id-and-access-tokens-in-web-api
    id_token_public_key = app.config.get('JWT_ID_TOKEN_PUB_KEY')
    access_token_public_key = app.config.get('JWT_ACCESS_TOKEN_PUB_KEY')

    def __get_client(self):
        return boto3.client('cognito-idp')

    def get_secret_hash(self, username):
        # A keyed-hash message authentication code (HMAC) calculated using
        # the secret key of a user pool client and username plus the client
        # ID in the message.
        message = username + self.client_id
        dig = hmac.new(self.client_secret, msg=message.encode('UTF-8'),
                       digestmod=hashlib.sha256).digest()
        return base64.b64encode(dig).decode()

    # REQUIRES that `ADMIN_NO_SRP_AUTH` be enabled on Client App for User Pool
    def login_user(self, username_or_alias, password):
        try:
            return self.__get_client().admin_initiate_auth(
                UserPoolId=self.user_pool_id,
                ClientId=self.client_id,
                AuthFlow='ADMIN_NO_SRP_AUTH',
                AuthParameters={
                    'USERNAME': username_or_alias,
                    'PASSWORD': password,
                    'SECRET_HASH': self.get_secret_hash(username_or_alias)
                }
            )
        except botocore.exceptions.ClientError as e:
            return e.response

关于python - 如何使用 boto3 为 AWS Cognito 创建 SECRET_HASH?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44244441/

相关文章:

python - 在 matplotlib 中添加颜色条时出现 AttributeError

Python 字符串对象引用

node.js - 如何在 AWS lambda 上安装 phantomjs?

boto3 - Botocore 以前的版本文档

amazon-web-services - 使用 moto + serverless 模拟 DynamoDB

python - botocore.exceptions.ConnectTimeoutError : Connect timeout on endpoint URL

python - 处理特定的和一般的 Python 异常?

python - 再次从网站使用 bs4 并保存到文本文件

python - 如何使用 boto3 获取 RDS 实例的主机

amazon-web-services - AWS lambda nodejs 在使用 X-RAY 时显示错误