Skip to content
This repository was archived by the owner on Jun 1, 2023. It is now read-only.

Commit 9ec3b08

Browse files
committed
Refactored nonce checking.
Fixed tests.
1 parent 6b59b2a commit 9ec3b08

4 files changed

Lines changed: 33 additions & 32 deletions

File tree

src/oidcrp/oidc/authorization.py

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from oidcmsg import oauth2
44
from oidcmsg import oidc
5+
from oidcmsg.exception import MissingRequiredAttribute
56
from oidcmsg.oidc import make_openid_request
67
from oidcmsg.oidc import verified_claim_name
78
from oidcmsg.time_util import time_sans_frac
@@ -49,26 +50,32 @@ def set_state(self, request_args, **kwargs):
4950
def update_service_context(self, resp, key='', **kwargs):
5051
_context = self.client_get("service_context")
5152

52-
_idt = resp.get(verified_claim_name('id_token'))
53-
if _idt:
54-
# If there is a verified ID Token then we have to do nonce
55-
# verification
56-
item = _context.state.get_item(oauth2.AuthorizationRequest, 'auth_request', key)
57-
if item['nonce'] != _idt['nonce']:
58-
raise ValueError('Invalid nonce')
59-
60-
# try:
61-
# if _context.state.get_state_by_nonce(_idt['nonce']) != key:
62-
# raise ParameterError('Someone has messed with "nonce"')
63-
# except KeyError:
64-
# raise ValueError('Invalid nonce')
65-
66-
_context.state.store_sub2state(_idt['sub'], key)
67-
6853
if 'expires_in' in resp:
6954
resp['__expires_at'] = time_sans_frac() + int(resp['expires_in'])
7055
_context.state.store_item(resp.to_json(), 'auth_response', key)
7156

57+
def get_request_from_response(self, response):
58+
_context = self.client_get("service_context")
59+
return _context.state.get_item(oauth2.AuthorizationRequest, 'auth_request',
60+
response["state"])
61+
62+
def post_parse_response(self, response, **kwargs):
63+
response = authorization.Authorization.post_parse_response(self, response, **kwargs)
64+
65+
_idt = response.get(verified_claim_name('id_token'))
66+
if _idt:
67+
# If there is a verified ID Token then we have to do nonce
68+
# verification.
69+
_request = self.get_request_from_response(response)
70+
_req_nonce = _request.get('nonce')
71+
if _req_nonce:
72+
_id_token_nonce = _idt.get('nonce')
73+
if not _id_token_nonce:
74+
raise MissingRequiredAttribute('nonce')
75+
elif _req_nonce != _id_token_nonce:
76+
raise ValueError('Invalid nonce')
77+
return response
78+
7279
def oidc_pre_construct(self, request_args=None, post_args=None, **kwargs):
7380
_context = self.client_get("service_context")
7481
if request_args is None:
@@ -272,10 +279,6 @@ def gather_verify_arguments(self):
272279
'skew': _context.clock_skew
273280
}
274281

275-
_nonce = _context.state.get_item(oauth2.AuthorizationRequest, 'auth_request', 'nonce')
276-
if _nonce:
277-
kwargs["nonce"] = _nonce
278-
279282
_client_id = _context.client_id
280283
if _client_id:
281284
kwargs['client_id'] = _client_id

src/oidcrp/service.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -557,8 +557,7 @@ def parse_response(self, info, sformat="", state="", **kwargs):
557557
vargs = self.gather_verify_arguments()
558558
LOGGER.debug("Verify response with %s", vargs)
559559
try:
560-
# verify the message. If something is wrong an exception is
561-
# thrown
560+
# verify the message. If something is wrong an exception is thrown
562561
resp.verify(**vargs)
563562
except Exception as err:
564563
LOGGER.error(

tests/request123456.jwt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
eyJhbGciOiJSUzI1NiIsImtpZCI6IlNVc3dOaTFNUkZsRFQwWTJZalUxWjFSZlFsbzJTM2RFYTNGVFRrVjNMVGhGY25oRFRIRjVlbGsyVlEifQ.eyJyZXNwb25zZV90eXBlIjogImNvZGUiLCAic3RhdGUiOiAic3RhdGUiLCAicmVkaXJlY3RfdXJpIjogImh0dHBzOi8vZXhhbXBsZS5jb20vY2xpL2F1dGh6X2NiIiwgInNjb3BlIjogIm9wZW5pZCIsICJub25jZSI6ICI4Tkc4VWt1cm9qWEE4azJ4SEJhYXQyRnpCcFVpbDRXNyIsICJjbGllbnRfaWQiOiAiY2xpZW50X2lkIiwgImlzcyI6ICJjbGllbnRfaWQiLCAiaWF0IjogMTYzMzM1Mjk1NywgImF1ZCI6IFsiaHR0cHM6Ly9leGFtcGxlLmNvbSJdfQ.KEY0WdzULSWr7M4guCOArwRWPpY6S8_ldckWYDvihTIy-V59zqQxucNrxEtSh8nkCr_dzZB4ZyHX836g77UOCtFh8TYMARpADWGV-m83OBR0_nwiohMlZJL1H4sH-ovID7CUHebr0yXu0NzEI_Fx_hr1PUeQru2UcoQBZg9g8uGpfW9GXy9H_rLg_l2T3xtpPTQfE057q9KREmQmc0XDXVi1XXUyUSGNeXJUlVLu14sWO5y92b5rWjujk9tUTS2wAiVOtH3qNCP8BorSkiG6pvCHDejYZYRG037pKiUJSN3z8McXgTSSIOxW4zfpP9D5FSkYn-re9kKh5jMWpv9w_Q
1+
eyJhbGciOiJSUzI1NiIsImtpZCI6IlNVc3dOaTFNUkZsRFQwWTJZalUxWjFSZlFsbzJTM2RFYTNGVFRrVjNMVGhGY25oRFRIRjVlbGsyVlEifQ.eyJyZXNwb25zZV90eXBlIjogImNvZGUiLCAic3RhdGUiOiAic3RhdGUiLCAicmVkaXJlY3RfdXJpIjogImh0dHBzOi8vZXhhbXBsZS5jb20vY2xpL2F1dGh6X2NiIiwgInNjb3BlIjogIm9wZW5pZCIsICJub25jZSI6ICJCZ25yS0daMHZNQ3lFRlU1U0d5ekZmVlNkVGxHZmhIaSIsICJjbGllbnRfaWQiOiAiY2xpZW50X2lkIiwgImlzcyI6ICJjbGllbnRfaWQiLCAiaWF0IjogMTYzMzU5MjI4OCwgImF1ZCI6IFsiaHR0cHM6Ly9leGFtcGxlLmNvbSJdfQ.xYAc40jcNNioyQ_FbbhrBectUkhxX62rPmf8whkH-7FBkrzAdjYIM7PmyDfJXRmXz0mw54EOriq3aXS-CPZqcSfRAYf7e-Shw2Ve1-138o307l6x7LmvLpK8EnUealcO5fEs-aLEwVre1ZOXNHchWKt-Lj_eL5cVA-FNQj09IzKTlDv_1gh_bSJJKELW0BsK9f3JYf-pM4EoCqoajbt_jw2WakzF0Phg2mc_wolpUPPZigjgQj8AGeAcDVf6y74E9j9csSVpB8YlnFwyUyJ0Yh-zRnIK0EInufdHu7qo1rJS6UpcTb2eS354Zm3cd1YDcfvPfsT__YV8Rb32Uo2_WQ

tests/test_13_oidc_service.py

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from cryptojwt.jwt import JWT
88
from cryptojwt.key_jar import build_keyjar
99
from cryptojwt.key_jar import init_key_jar
10+
from oidcmsg.exception import MissingRequiredAttribute
1011
from oidcmsg.oidc import AccessTokenRequest
1112
from oidcmsg.oidc import AccessTokenResponse
1213
from oidcmsg.oidc import AuthorizationRequest
@@ -202,7 +203,7 @@ def test_update_service_context_with_idtoken_wrong_nonce(self):
202203
idt = JWT(ISS_KEY, iss=ISS, lifetime=3600)
203204
payload = {
204205
'sub': '123456789', 'aud': ['client_id'],
205-
'nonce': 'nonce'
206+
'nonce': 'noice'
206207
}
207208
# have to calculate c_hash
208209
alg = 'RS256'
@@ -211,9 +212,8 @@ def test_update_service_context_with_idtoken_wrong_nonce(self):
211212

212213
_idt = idt.pack(payload)
213214
resp = AuthorizationResponse(state='state', code='code', id_token=_idt)
214-
resp = self.service.parse_response(resp.to_urlencoded())
215-
with pytest.raises(ParameterError):
216-
self.service.update_service_context(resp, 'state2')
215+
with pytest.raises(ValueError):
216+
self.service.parse_response(resp.to_urlencoded())
217217

218218
def test_update_service_context_with_idtoken_missing_nonce(self):
219219
req_args = {'response_type': 'code', 'state': 'state', 'nonce': 'nonce'}
@@ -229,9 +229,8 @@ def test_update_service_context_with_idtoken_missing_nonce(self):
229229

230230
_idt = idt.pack(payload)
231231
resp = AuthorizationResponse(state='state', code='code', id_token=_idt)
232-
resp = self.service.parse_response(resp.to_urlencoded())
233-
with pytest.raises(ValueError):
234-
self.service.update_service_context(resp, 'state')
232+
with pytest.raises(MissingRequiredAttribute):
233+
self.service.parse_response(resp.to_urlencoded())
235234

236235
@pytest.mark.parametrize("allow_sign_alg_none", [True, False])
237236
def test_allow_unsigned_idtoken(self, allow_sign_alg_none):
@@ -240,14 +239,14 @@ def test_allow_unsigned_idtoken(self, allow_sign_alg_none):
240239
self.service.get_request_parameters(request_args=req_args)
241240
# Build an ID Token
242241
idt = JWT(ISS_KEY, iss=ISS, lifetime=3600, sign_alg='none')
243-
payload = {'sub': '123456789', 'aud': ['client_id']}
242+
payload = {'sub': '123456789', 'aud': ['client_id'], 'nonce': req_args['nonce']}
244243
_idt = idt.pack(payload)
245244
self.service.client_get("service_context").behaviour["verify_args"] = {
246245
"allow_sign_alg_none": allow_sign_alg_none
247246
}
248247
resp = AuthorizationResponse(state='state', code='code', id_token=_idt)
249248
if allow_sign_alg_none:
250-
resp = self.service.parse_response(resp.to_urlencoded())
249+
self.service.parse_response(resp.to_urlencoded())
251250
else:
252251
with pytest.raises(UnsupportedAlgorithm):
253252
self.service.parse_response(resp.to_urlencoded())

0 commit comments

Comments
 (0)