AWS Boto3+Cognito实现Remember Me时DeviceSecretVerifierConfig构造问题
AWS Cognito confirm_device方法DeviceSecretVerifierConfig参数构造方案
核心逻辑说明
DeviceSecretVerifierConfig是Cognito用于设备身份验证的校验参数,包含两个必填字段:
Salt:随机生成的盐值,base64编码PasswordVerifier:基于SRP协议生成的验证器,base64编码
前置依赖
需要先安装加密依赖库:pip install pycryptodome
完整实现代码
首先封装SRP参数计算工具函数:
import base64 import binascii import hashlib import hmac import os from Crypto.Util import number # Cognito官方指定的2048位SRP组固定参数,不可修改 N = int('FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF', 16) g = 2 def hash_sha256(data): return hashlib.sha256(data).digest() def hmac_sha256(key, data): return hmac.new(key, data, hashlib.sha256).digest() def compute_device_verifier(device_group_key, device_key, client_id, client_secret=None, username=None): # 生成16位随机盐 salt = os.urandom(16) # 计算设备密钥 if client_secret: device_secret = hmac_sha256(client_secret.encode(), f"{username}{client_id}{device_group_key}{device_key}".encode()) else: device_secret = hmac_sha256(device_group_key.encode(), device_key.encode()) # 计算SRP验证器 x = int(binascii.hexlify(hash_sha256(salt + device_secret)), 16) verifier = pow(g, x, N) # 转换为Cognito要求的base64格式 return { 'Salt': base64.standard_b64encode(salt).decode(), 'PasswordVerifier': base64.standard_b64encode(number.long_to_bytes(verifier)).decode() }
补全后的业务逻辑代码:
# 第一步:发起登录认证 auth_resp = client.admin_initiate_auth( UserPoolId=COG_USER_POOL, ClientId=COG_USER_POOL_APP, AuthFlow='ADMIN_USER_PASSWORD_AUTH', AuthParameters={ 'USERNAME': username, 'PASSWORD': password, } ) new_device_meta = auth_resp['AuthenticationResult']['NewDeviceMetadata'] device_key = new_device_meta['DeviceKey'] device_group_key = new_device_meta['DeviceGroupKey'] # 第二步:生成校验参数 # 如果用户池应用开启了客户端密钥,需要额外传入client_secret和username参数 device_verifier_config = compute_device_verifier( device_group_key=device_group_key, device_key=device_key, client_id=COG_USER_POOL_APP, # client_secret=COG_USER_POOL_APP_SECRET, # username=username ) # 第三步:确认设备 confirm_resp = client.confirm_device( AccessToken=auth_resp['AuthenticationResult']['AccessToken'], DeviceKey=device_key, DeviceSecretVerifierConfig=device_verifier_config ) # 第四步:更新设备记住状态 remember_status = 'remembered' if remember else 'not_remembered' client.admin_update_device_status( UserPoolId=COG_USER_POOL, Username=username, DeviceKey=device_key, DeviceRememberedStatus=remember_status )
注意事项
- 若你的用户池应用未开启「生成客户端密钥」配置,生成验证器时不需要传入
client_secret和username参数 - 原有代码存在响应变量名不一致的问题(第一行定义的是
esp,后续用resp访问),上述代码已经做了修正 - 生成的盐和验证器不需要本地存储,Cognito会自行维护设备验证信息
内容的提问来源于stack exchange,提问作者Belgin Fish
相关产品推荐
相关产品推荐

