Skip to content

Commit 69a7e62

Browse files
committed
Introduce claims constants
1 parent 858c6d9 commit 69a7e62

File tree

4 files changed

+57
-34
lines changed

4 files changed

+57
-34
lines changed

README.rst

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,15 @@ Authentication class
3131
In order to get-or-create User accounts automatically within your microservice apps,
3232
you can use the following DRF Authentication class template::
3333

34+
from rest_framework_sso import claims
35+
3436
class Authentication(rest_framework_sso.authentication.JWTAuthentication):
3537
def authenticate_credentials(self, payload):
3638
user_model = get_user_model()
3739

3840
user, created = user_model.objects.get_or_create(
39-
service=payload.get('iss'),
40-
external_id=payload.get('uid'),
41+
service=payload.get(claims.ISSUER),
42+
external_id=payload.get(claims.USER_ID),
4143
)
4244

4345
if not user.is_active:

rest_framework_sso/claims.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# coding: utf-8
2+
from __future__ import absolute_import, unicode_literals
3+
4+
ISSUER = 'iss'
5+
SUBJECT = 'sub'
6+
AUDIENCE = 'aud'
7+
EXPIRATION_TIME = 'exp'
8+
NOT_BEFORE = 'nbf'
9+
ISSUED_AT = 'iat'
10+
JWT_ID = 'jti'
11+
12+
TOKEN = 'token'
13+
SESSION_ID = 'sid'
14+
USER_ID = 'uid'
15+
EMAIL = 'email'
16+
SCOPES = 'scopes'
17+
18+
TOKEN_SESSION = 'session'
19+
TOKEN_AUTHORIZATION = 'auth'

rest_framework_sso/utils.py

Lines changed: 31 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -11,58 +11,59 @@
1111
from jwt.exceptions import MissingRequiredClaimError, InvalidIssuerError
1212
from rest_framework import exceptions
1313

14+
from rest_framework_sso import claims
1415
from rest_framework_sso.settings import api_settings
1516

1617

1718
def create_session_payload(session_token, user, **kwargs):
1819
return {
19-
'type': 'session',
20-
'sid': session_token.pk,
21-
'uid': user.pk,
22-
'email': user.email,
20+
claims.TOKEN: claims.TOKEN_SESSION,
21+
claims.SESSION_ID: session_token.pk,
22+
claims.USER_ID: user.pk,
23+
claims.EMAIL: user.email,
2324
}
2425

2526

2627
def create_authorization_payload(session_token, user, **kwargs):
2728
return {
28-
'type': 'auth',
29-
'sid': session_token.pk,
30-
'uid': user.pk,
31-
'email': user.email,
32-
'scope': [],
29+
claims.TOKEN: claims.TOKEN_AUTHORIZATION,
30+
claims.SESSION_ID: session_token.pk,
31+
claims.USER_ID: user.pk,
32+
claims.EMAIL: user.email,
33+
claims.SCOPES: [],
3334
}
3435

3536

3637
def encode_jwt_token(payload):
37-
if payload.get('type') not in ('session', 'auth'):
38+
if payload.get(claims.TOKEN) not in (claims.TOKEN_SESSION, claims.TOKEN_AUTHORIZATION):
3839
raise RuntimeError('Unknown token type')
3940

40-
if not payload.get('iss'):
41+
if not payload.get(claims.ISSUER):
4142
if api_settings.IDENTITY is not None:
42-
payload['iss'] = api_settings.IDENTITY
43+
payload[claims.ISSUER] = api_settings.IDENTITY
4344
else:
4445
raise RuntimeError('IDENTITY must be specified in settings')
4546

46-
if not payload.get('aud'):
47-
if payload.get('type') == 'session' and api_settings.SESSION_AUDIENCE is not None:
48-
payload['aud'] = api_settings.SESSION_AUDIENCE
49-
elif payload.get('type') == 'auth' and api_settings.AUTHORIZATION_AUDIENCE is not None:
50-
payload['aud'] = api_settings.AUTHORIZATION_AUDIENCE
47+
if not payload.get(claims.AUDIENCE):
48+
if payload.get(claims.TOKEN) == claims.TOKEN_SESSION and api_settings.SESSION_AUDIENCE is not None:
49+
payload[claims.AUDIENCE] = api_settings.SESSION_AUDIENCE
50+
elif payload.get(claims.TOKEN) == claims.TOKEN_AUTHORIZATION and api_settings.AUTHORIZATION_AUDIENCE is not None:
51+
payload[claims.AUDIENCE] = api_settings.AUTHORIZATION_AUDIENCE
5152
elif api_settings.IDENTITY is not None:
52-
payload['aud'] = [api_settings.IDENTITY]
53+
payload[claims.AUDIENCE] = [api_settings.IDENTITY]
5354
else:
5455
raise RuntimeError('SESSION_AUDIENCE must be specified in settings')
5556

56-
if not payload.get('exp'):
57-
if payload.get('type') == 'session' and api_settings.SESSION_EXPIRATION is not None:
58-
payload['exp'] = datetime.utcnow() + api_settings.SESSION_EXPIRATION
59-
elif payload.get('type') == 'auth' and api_settings.AUTHORIZATION_EXPIRATION is not None:
60-
payload['exp'] = datetime.utcnow() + api_settings.AUTHORIZATION_EXPIRATION
57+
if not payload.get(claims.EXPIRATION_TIME):
58+
if payload.get(claims.TOKEN) == claims.TOKEN_SESSION and api_settings.SESSION_EXPIRATION is not None:
59+
payload[claims.EXPIRATION_TIME] = datetime.utcnow() + api_settings.SESSION_EXPIRATION
60+
elif payload.get(claims.TOKEN) == claims.TOKEN_AUTHORIZATION and api_settings.AUTHORIZATION_EXPIRATION is not None:
61+
payload[claims.EXPIRATION_TIME] = datetime.utcnow() + api_settings.AUTHORIZATION_EXPIRATION
6162

62-
if payload['iss'] not in api_settings.PRIVATE_KEYS:
63+
if payload[claims.ISSUER] not in api_settings.PRIVATE_KEYS:
6364
raise RuntimeError('Private key for specified issuer was not found in settings')
6465

65-
private_key = open(api_settings.PRIVATE_KEYS.get(payload['iss']), 'rt').read()
66+
private_key = open(api_settings.PRIVATE_KEYS.get(payload[claims.ISSUER]), 'rt').read()
6667

6768
return jwt.encode(
6869
payload=payload,
@@ -75,10 +76,10 @@ def encode_jwt_token(payload):
7576
def decode_jwt_token(token):
7677
unverified_claims = jwt.decode(token, verify=False)
7778

78-
if 'iss' not in unverified_claims:
79-
raise MissingRequiredClaimError('iss')
79+
if claims.ISSUER not in unverified_claims:
80+
raise MissingRequiredClaimError(claims.ISSUER)
8081

81-
unverified_issuer = six.text_type(unverified_claims['iss'])
82+
unverified_issuer = six.text_type(unverified_claims[claims.ISSUER])
8283

8384
if api_settings.ACCEPTED_ISSUERS is not None and unverified_issuer not in api_settings.ACCEPTED_ISSUERS:
8485
raise InvalidIssuerError('Invalid issuer')
@@ -115,13 +116,13 @@ def authenticate_payload(payload):
115116
session_token = SessionToken.objects.\
116117
active().\
117118
select_related('user').\
118-
get(pk=payload.get('sid'), user_id=payload.get('uid'))
119+
get(pk=payload.get(claims.SESSION_ID), user_id=payload.get(claims.USER_ID))
119120
user = session_token.user
120121
except SessionToken.DoesNotExist:
121122
raise exceptions.AuthenticationFailed(_('Invalid token.'))
122123
else:
123124
try:
124-
user = user_model.objects.get(pk=payload.get('uid'))
125+
user = user_model.objects.get(pk=payload.get(claims.USER_ID))
125126
except user_model.DoesNotExist:
126127
raise exceptions.AuthenticationFailed(_('Invalid token.'))
127128

rest_framework_sso/views.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from rest_framework.response import Response
77
from rest_framework.views import APIView
88

9+
from rest_framework_sso import claims
910
from rest_framework_sso.models import SessionToken
1011
from rest_framework_sso.serializers import SessionTokenSerializer, AuthorizationTokenSerializer
1112
from rest_framework_sso.settings import api_settings
@@ -88,10 +89,10 @@ def post(self, request, *args, **kwargs):
8889
serializer = self.get_serializer(data=request.data)
8990
serializer.is_valid(raise_exception=True)
9091

91-
if hasattr(request.auth, 'get') and request.auth.get('sid'):
92+
if hasattr(request.auth, 'get') and request.auth.get(claims.SESSION_ID):
9293
try:
9394
session_token = SessionToken.objects.active().\
94-
get(pk=request.auth.get('sid'), user=request.user)
95+
get(pk=request.auth.get(claims.SESSION_ID), user=request.user)
9596
except SessionToken.DoesNotExist:
9697
return Response({'detail': 'Invalid token.'}, status=status.HTTP_401_UNAUTHORIZED)
9798
else:

0 commit comments

Comments
 (0)