Skip to content

Commit 7f2dc3c

Browse files
authored
Sem-Ver: bugfix Catch JtiUniquenessException and respond with a 401 inside _process_asap_token.
Signed-off-by: David Black <[email protected]>
1 parent ae37ec2 commit 7f2dc3c

File tree

4 files changed

+41
-4
lines changed

4 files changed

+41
-4
lines changed

atlassian_jwt_auth/frameworks/common/asap.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from atlassian_jwt_auth.exceptions import (
44
PublicKeyRetrieverException,
55
NoTokenProvidedError,
6+
JtiUniquenessException,
67
)
78

89

@@ -52,6 +53,10 @@ def _process_asap_token(request, backend, settings, verifier=None):
5253
error_response = backend.get_401_response(
5354
'Unauthorized: Invalid token', request=request
5455
)
56+
except JtiUniquenessException:
57+
error_response = backend.get_401_response(
58+
'Unauthorized: Invalid token - duplicate jti', request=request
59+
)
5560

5661
if error_response is not None and settings.ASAP_REQUIRED:
5762
return error_response

atlassian_jwt_auth/frameworks/django/tests/test_django.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,16 @@ def check_response(self,
9494
def test_request_with_valid_token_is_allowed(self):
9595
self.check_response('needed', 'one', 200)
9696

97+
def test_request_with_duplicate_jti_is_rejected(self):
98+
token = create_token(
99+
issuer='client-app', audience='server-app',
100+
key_id='client-app/key01', private_key=self._private_key_pem
101+
)
102+
str_auth = 'Bearer ' + token.decode(encoding='iso-8859-1')
103+
self.check_response('needed', 'one', 200, authorization=str_auth)
104+
self.check_response('needed', 'duplicate jti', 401,
105+
authorization=str_auth)
106+
97107
def test_request_with_string_headers_is_allowed(self):
98108
token = create_token(
99109
issuer='client-app', audience='server-app',

atlassian_jwt_auth/frameworks/flask/tests/test_flask.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,15 @@ def test_request_with_valid_token_is_allowed(self):
6464
)
6565
self.assertEqual(self.send_request(token).status_code, 200)
6666

67+
@unittest.expectedFailure
68+
def test_request_with_duplicate_jti_is_rejected(self):
69+
token = create_token(
70+
'client-app', 'server-app',
71+
'client-app/key01', self._private_key_pem
72+
)
73+
self.assertEqual(self.send_request(token).status_code, 200)
74+
self.assertEqual(self.send_request(token).status_code, 401)
75+
6776
def test_request_with_invalid_audience_is_rejected(self):
6877
token = create_token(
6978
'client-app', 'invalid-audience',

atlassian_jwt_auth/frameworks/wsgi/tests/test_wsgi.py

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ def setUp(self):
3434
def get_app_with_middleware(self, config):
3535
return ASAPMiddleware(app, config)
3636

37-
def send_request(self, url='/', config=None, token=None):
37+
def send_request(self, url='/', config=None, token=None, application=None):
3838
""" returns the response of sending a request containing the given
3939
token sent in the Authorization header.
4040
"""
@@ -48,9 +48,9 @@ def start_response(status, response_headers, exc_info=None):
4848
environ = {}
4949
if token:
5050
environ['HTTP_AUTHORIZATION'] = b'Bearer ' + token
51-
52-
app = self.get_app_with_middleware(config or self.config)
53-
return app(environ, start_response), resp_info, environ
51+
if application is None:
52+
application = self.get_app_with_middleware(config or self.config)
53+
return application(environ, start_response), resp_info, environ
5454

5555
def test_request_with_valid_token_is_allowed(self):
5656
token = create_token(
@@ -61,6 +61,19 @@ def test_request_with_valid_token_is_allowed(self):
6161
self.assertEqual(resp_info['status'], '200 OK')
6262
self.assertIn('ATL_ASAP_CLAIMS', environ)
6363

64+
def test_request_with_duplicate_jti_is_rejected(self):
65+
token = create_token(
66+
'client-app', 'server-app',
67+
'client-app/key01', self._private_key_pem
68+
)
69+
application = self.get_app_with_middleware(self.config)
70+
body, resp_info, environ = self.send_request(
71+
token=token, application=application)
72+
self.assertEqual(resp_info['status'], '200 OK')
73+
body, resp_info, environ = self.send_request(
74+
token=token, application=application)
75+
self.assertEqual(resp_info['status'], '401 Unauthorized')
76+
6477
def test_request_with_invalid_audience_is_rejected(self):
6578
token = create_token(
6679
'client-app', 'invalid-audience',

0 commit comments

Comments
 (0)