【发布时间】:2020-03-29 09:48:08
【问题描述】:
我正在关注aws-cognito-tutorial-complete 并尝试将Bearer 与 Django 一起使用,因为我的目标是使用 Django REST 框架和 GraphQL 的单页应用程序 (SPA)。
通过给定的示例,我可以连接 AWS 并能够注册、登录等到 AWS Cognito。然后我使用django-cognito-jwt 来解码 Bearer 令牌。
问题:django-cognito-jwt 引发有关公钥问题的错误
尝试:TokenValidator 类与方法 _get_public_key
令牌在那里
35 def _get_public_key(self, token):
36 import ipdb; ipdb.set_trace()
---> 37 try:
38 headers = jwt.get_unverified_header(token)
39 except jwt.DecodeError as exc:
40 raise TokenError(str(exc))
41
42 if getattr(settings, "COGNITO_PUBLIC_KEYS_CACHING_ENABLED", False):
ipdb> token
b'eyJraWQiOiJUaGd4NXo5MnFxNjdPR1wvMDRjT0xDS2U2K0dsQlU3XC9LZklHK2hJdFwvSjR3PSIsImFsZyI6IlJTMjU2In0.eyJzdWIiOiIyZTQ3OTBhMC0zNWE0LTQ1ZDctYjEwYy1jZWQ3OWJlMjJlOTQiLCJhdWQiOiIxNTl1ZmpyaWhnZWhiNjdzbjM3M2FvdGxpNyIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJldmVudF9pZCI6ImM2OTA0NjYyLWZlOWUtNGYwZi04OTc3LTdhZGU4M2YyOTAxMyIsInRva2VuX3VzZSI6ImlkIiwiYXV0aF90aW1lIjoxNTc1NDU3MDIwLCJpc3MiOiJodHRwczpcL1wvY29nbml0by1pZHAudXMtd2VzdC0yLmFtYXpvbmF3cy5jb21cL3VzLXdlc3QtMl9mbENKYW9EaWciLCJjb2duaXRvOnVzZXJuYW1lIjoiam9obi1yYW1ibyIsImV4cCI6MTU3NTQ2MDYyMCwiaWF0IjoxNTc1NDU3MDIwLCJlbWFpbCI6ImZvZ2d5Z2lnYUBnbWFpbC5jb20ifQ.jk207sDdYb7CDhc5r0hZXa_EDPqG9Fi2oBTot8Tv_moJxdB1v4cNCDLB6m5rVVHzmxI8-cPj00GViMH3-LORnQcg4KitAlew_aD_RMD5Hzy3ltABrMYBf9LEI2kq6---Li9jk3NYpVji2h5W4oKoJrHRriJSuNuBFFijFXEc29iLhQclaDLWvXw4BJI087BKCYpnD-xR79bM3nYI-m9Wp40e_e7JbsGtu1JKfTym_nKLE-yncyhWq0rarIbauBHmq5hRYCQofUbSWD6IRGCZaiLRPBTk6LvUd3VigUz9x0mIU8feViRQmFcVFfRsB56Pbx10RUAUYHBR4JNHCMROpQ'
转到headers旁边
ipdb> headers
{'kid': 'Thgx5z92qq67OG/04cOLCKe6+GlBU7/KfIG+hIt/J4w=', 'alg': 'RS256'}
ipdb> cache_key
'django_cognito_jwt:Thgx5z92qq67OG/04cOLCKe6+GlBU7/KfIG+hIt/J4w='
jwk_data 是None
ipdb> self._json_web_keys
{'D2syaFjXXpkbzTjkRHLAtdX065Neb1EfUguGabpJWlo=': '{"alg": "RS256", "e": "AQAB", "kid": "D2syaFjXXpkbzTjkRHLAtdX065Neb1EfUguGabpJWlo=", "kty": "RSA", "n": "kDmz5mTlTil_r6sVMnln2ohc45_TlBPw1pOcVJtEyGW2_vXN4EXnYKxcFyFQqZIjXaYlrAFBAMAW_qlIfJ0J8coyNImLngfUbk1cbwwQr3wTB-6t8bM8x_B8D_D7uB-HfGe8SNS1yFU6gfDnd4z7kJZvJIFV_uEWP5A1cbXdTOTPlj3zKUXnpXBvnZ5d_V2Y3gPjlv_m3uh3ZejeTAnaLF-PGt69DdD9dj04ncqPa2rK8eShPWYckZ_oaH_4Ju9FmQGD6lzoUHhRxEsfq6pEr2wFt2TAcji9WG7NUFO5v83GRfaWiRnGSVI8iVzVWjzzGvdqAuiMgKUDtmq7b9r5Xw", "use": "sig"}', 'a7tocHhrCduYr7EFRiR9A2txhEbl2dCOOBvYAYEdEJA=': '{"alg": "RS256", "e": "AQAB", "kid": "a7tocHhrCduYr7EFRiR9A2txhEbl2dCOOBvYAYEdEJA=", "kty": "RSA", "n": "re0iYlsRqmSkoqZiGlz3mTYb0HJ3vjCXwN83OmbNQyAguC-Tflb95Z1bEJsVL0Wr6ZvmFFGpXjJU1n3K9DO2JadnBQkGsJegYvXaNC2IgHnHDq9chrP6cNdnO5jAo7wqtMeZi2VqccyRFXVx9dyKAbyGgborORP5raFSvHU-qT2iVfwrbSbWXAH1qwkwbMMbU6fUHJp7u9ZrJT04qMhm-asgoSA6Swe4znqcg87W2dSWMzstyUQwTN-1Kn2GXmTIyYo4lUIoyQRXyl2d8L37iTkbRayulvLqvzkKglAHlRF6jLLHLZt6-ZBf3hvISDbO5Vwo7jJGTYYu6h3tKKbSBQ", "use": "sig"}'}
ipdb> headers["kid"]
'Thgx5z92qq67OG/04cOLCKe6+GlBU7/KfIG+hIt/J4w='
此时jwk_data 是None
> /Users/sarit/.pyenv/versions/muy/lib/python3.7/site-packages/django_cognito_jwt/validator.py(48)_get_public_key()
47 jwk_data = self._json_web_keys.get(headers["kid"])
---> 48 timeout = getattr(settings, "COGNITO_PUBLIC_KEYS_CACHING_TIMEOUT", 300)
49 cache.set(cache_key, jwk_data, timeout=timeout)
ipdb> jwk_data
ipdb>
解决方法:
放大token_validator.validate(jwt_token)
class JSONWebTokenAuthentication(BaseAuthentication):
"""Token based authentication using the JSON Web Token standard."""
def authenticate(self, request):
"""Entrypoint for Django Rest Framework"""
jwt_token = self.get_jwt_token(request)
if jwt_token is None:
return None
# Authenticate token
try:
token_validator = self.get_token_validator(request)
jwt_payload = token_validator.validate(jwt_token)
except TokenError:
raise exceptions.AuthenticationFailed()
USER_MODEL = self.get_user_model()
user = USER_MODEL.objects.get_or_create_for_cognito(jwt_payload)
return (user, jwt_token)
放大self._get_public_key(token)
def validate(self, token):
public_key = self._get_public_key(token)
if not public_key:
raise TokenError("No key found for this token")
try:
jwt_data = jwt.decode(
token,
public_key,
audience=self.audience,
issuer=self.pool_url,
algorithms=["RS256"],
)
except (jwt.InvalidTokenError, jwt.ExpiredSignature, jwt.DecodeError) as exc:
raise TokenError(str(exc))
return jwt_data
放大jwt.get_unverified_header(token)
def _get_public_key(self, token):
try:
headers = jwt.get_unverified_header(token)
except jwt.DecodeError as exc:
raise TokenError(str(exc))
if getattr(settings, "COGNITO_PUBLIC_KEYS_CACHING_ENABLED", False):
cache_key = "django_cognito_jwt:%s" % headers["kid"]
jwk_data = cache.get(cache_key)
if not jwk_data:
jwk_data = self._json_web_keys.get(headers["kid"])
timeout = getattr(settings, "COGNITO_PUBLIC_KEYS_CACHING_TIMEOUT", 300)
cache.set(cache_key, jwk_data, timeout=timeout)
else:
jwk_data = self._json_web_keys.get(headers["kid"])
if jwk_data:
return RSAAlgorithm.from_jwk(jwk_data)
放大_jwt_global_obj.get_unverified_header
get_unverified_header = _jwt_global_obj.get_unverified_header
放大self._load(jwt)
def get_unverified_header(self, jwt):
"""Returns back the JWT header parameters as a dict()
Note: The signature is not verified so the header parameters
should not be fully trusted until signature verification is complete
"""
headers = self._load(jwt)[2]
self._validate_headers(headers)
return headers
在self._load(jwt) 方法。我发现我可以正确解压 Congito 令牌中的值
ipdb> from pprint import pprint
ipdb> pprint(self._load(jwt))
(b'{"sub":"2e4790a0-35a4-45d7-b10c-ced79be22e94","aud":"159ufjrihgehb67sn373aot'
b'li7","email_verified":true,"event_id":"c6904662-fe9e-4f0f-8977-7ade83f29013"'
b',"token_use":"id","auth_time":1575457020,"iss":"https:\\/\\/cognito-idp.us'
b'-west-2.amazonaws.com\\/us-west-2_flCJaoDig","cognito:username":"john-ram'
b'bo","exp":1575460620,"iat":1575457020,"email":"xxxx@gmail.com"}',
b'eyJraWQiOiJUaGd4NXo5MnFxNjdPR1wvMDRjT0xDS2U2K0dsQlU3XC9LZklHK2hJdFwvSjR3PSIs'
b'ImFsZyI6IlJTMjU2In0.eyJzdWIiOiIyZTQ3OTBhMC0zNWE0LTQ1ZDctYjEwYy1jZWQ3OWJlMjJl'
b'OTQiLCJhdWQiOiIxNTl1ZmpyaWhnZWhiNjdzbjM3M2FvdGxpNyIsImVtYWlsX3ZlcmlmaWVkIjp0'
b'cnVlLCJldmVudF9pZCI6ImM2OTA0NjYyLWZlOWUtNGYwZi04OTc3LTdhZGU4M2YyOTAxMyIsInRv'
b'a2VuX3VzZSI6ImlkIiwiYXV0aF90aW1lIjoxNTc1NDU3MDIwLCJpc3MiOiJodHRwczpcL1wvY29n'
b'bml0by1pZHAudXMtd2VzdC0yLmFtYXpvbmF3cy5jb21cL3VzLXdlc3QtMl9mbENKYW9EaWciLCJj'
b'b2duaXRvOnVzZXJuYW1lIjoiam9obi1yYW1ibyIsImV4cCI6MTU3NTQ2MDYyMCwiaWF0IjoxNTc1'
b'NDU3MDIwLCJlbWFpbCI6ImZvZ2d5Z2lnYUBnbWFpbC5jb20ifQ',
{'alg': 'RS256', 'kid': 'Thgx5z92qq67OG/04cOLCKe6+GlBU7/KfIG+hIt/J4w='},
b'\x8eM\xb4\xee\xc0\xdda\xbe\xc2\x0e\x179\xafHY]\xaf\xc4\x0c\xfa\x86\xf4X\xb6'
b'\xa0\x14\xe8\xb7\xc4\xef\xfej\t\xc5\xd0u\xbf\x87\r\x082\xc1\xeankUQ\xf3'
b'\x9b\x12<\xf9\xc3\xe3\xd3A\x95\x88\xc1\xf7\xf8\xb3\x91\x9d\x07 \xe0\xa8'
b'\xad\x02W\xb0\xfd\xa0\xffD\xc0\xf9\x1f<\xb7\x96\xd0\x01\xac\xc6\x01\x7f'
b'\xd2\xc4#i*\xeb\xef\xbe./c\x93sX\xa5X\xe2\xda\x1eV\xe2\x82\xa8&\xb1\xd1\xae"'
b'R\xb8\xdb\x81\x14X\xa3\x15q\x1c\xdb\xd8\x8b\x85\x07%h2\xd6\xbd|8\x04\x92'
b'4\xf3\xb0J\t\x8ag\x0f\xecQ\xef\xd6\xcc\xdev\x08\xfaoV\xa7\x8d\x1e\xfd\xee'
b'\xc9n\xc1\xad\xbbRJ}<\xa6\xfer\x8b\x13\xec\xa7s(V\xabJ\xda\xac\x86'
b'\xda\xb8\x11\xe6\xab\x98Q`$(}F\xd2X>\x88D`\x99j"\xd1<\x14\xe4\xe8\xbb\xd4'
b'wub\x81L\xfd\xc7I\x88S\xc7\xdeV$P\x98W\x15\x15\xf4l\x07\x9e\x8fo\x1dtE'
b'@\x14`pQ\xe0\x93G\x08\xc4N\xa5')
我可能会以自己的方式破解并从 self._load(jwt) 此处创建用户
问题:
1. 如何在这里获取公钥?
2.是django-cognito-jwt的bug吗?
【问题讨论】:
标签: python django jwt amazon-cognito