Skip to content

Commit ed5866f

Browse files
committed
Add client_id validation for access token, and get_user_info method.
The client_id from access token will be validated whether it matches the one defined in the `settings.COGNITO_AUDIENCE`. When using access token, the backend will call the userinfo endpoint from Amazon Cognito, to obtain the user info based on the access key, and pass into the payload inside the Django user_model's get_or_create_for_cognito method.
1 parent ade07ec commit ed5866f

File tree

3 files changed

+31
-2
lines changed

3 files changed

+31
-2
lines changed

README.rst

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,4 +77,12 @@ The library by default uses id token. To use access token, add the following lin
7777

7878
.. code-block:: python
7979
80-
COGNITO_TOKEN_TYPE = "access" # '{'id', 'access'} Default: 'id'
80+
COGNITO_TOKEN_TYPE = "access" # {'id', 'access'}, default 'id'
81+
82+
83+
As the payload of access token only contains basic user info, we could obtain further info from the `UserInfo endpoint`.
84+
You need to specify the Cognito domain in the ``settings.py`` file to obtain the user info from the endpoint, as follows:
85+
86+
.. code-block:: python
87+
88+
COGNITO_DOMAIN = "your-user-pool-domain" # eg, exampledomain.auth.ap-southeast-1.amazoncognito.com

src/django_cognito_jwt/backend.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import logging
2+
import requests
3+
import json
24

35
from django.apps import apps as django_apps
46
from django.conf import settings
@@ -29,12 +31,26 @@ def authenticate(self, request):
2931
raise exceptions.AuthenticationFailed()
3032

3133
USER_MODEL = self.get_user_model()
32-
user = USER_MODEL.objects.get_or_create_for_cognito(jwt_payload)
34+
if settings.COGNITO_TOKEN_TYPE == "access":
35+
user_info = self.get_user_info(jwt_token.decode("UTF-8"))
36+
user_info = json.loads(user_info.decode("UTF-8"))
37+
user = USER_MODEL.objects.get_or_create_for_cognito(user_info)
38+
else:
39+
user = USER_MODEL.objects.get_or_create_for_cognito(jwt_payload)
3340
return (user, jwt_token)
3441

3542
def get_user_model(self):
3643
user_model = getattr(settings, "COGNITO_USER_MODEL", settings.AUTH_USER_MODEL)
3744
return django_apps.get_model(user_model, require_ready=False)
45+
46+
def get_user_info(self, access_token):
47+
if settings.COGNITO_TOKEN_TYPE == "access":
48+
url = f"https://{settings.COGNITO_DOMAIN}/oauth2/userInfo"
49+
50+
headers = {'Authorization': f'Bearer {access_token}'}
51+
52+
res = requests.get(url, headers=headers)
53+
return res.content
3854

3955
def get_jwt_token(self, request):
4056
auth = get_authorization_header(request).split()

src/django_cognito_jwt/validator.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,11 @@ def validate(self, token):
7373
params.update({"audience": self.audience})
7474

7575
jwt_data = jwt.decode(**params)
76+
if self.token_type == "access":
77+
if "access" not in jwt_data["token_use"]:
78+
raise TokenError("Incorrect token use")
79+
if jwt_data["client_id"] not in self.audience:
80+
raise TokenError("Incorrect client_id")
7681
except (
7782
jwt.InvalidTokenError,
7883
jwt.ExpiredSignatureError,

0 commit comments

Comments
 (0)