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

Commit cec45f3

Browse files
committed
Changed how verifiable claims (basically claims that as value have a signed JWT) are represented once they are
verified.
1 parent 59105e2 commit cec45f3

File tree

2 files changed

+45
-10
lines changed

2 files changed

+45
-10
lines changed

src/oidcmsg/oidc/__init__.py

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -170,10 +170,15 @@ def claims_request_deser(val, sformat="json"):
170170
# never 'urlencoded'
171171
if sformat == "urlencoded":
172172
sformat = "json"
173-
if sformat in ["dict", "json"]:
173+
174+
if sformat == "json":
174175
if not isinstance(val, str):
175176
val = json.dumps(val)
176177
sformat = "json"
178+
elif sformat == 'dict':
179+
if isinstance(val, str):
180+
val = json.loads(val)
181+
177182
return ClaimsRequest().deserialize(val, sformat)
178183

179184

@@ -232,6 +237,25 @@ def check_char_set(string, allowed):
232237
'issuer', 'allow_missing_kid', 'no_kid_issuer',
233238
'trusting', 'skew', 'nonce_storage_time', 'client_id']
234239

240+
241+
CLAIMS_WITH_VERIFIED = ['id_token', 'id_token_hint', 'request']
242+
VERIFIED_CLAIM_PREFIX = '__verified'
243+
244+
245+
def verified_claim_name(claim):
246+
return '{}_{}'.format(VERIFIED_CLAIM_PREFIX, claim)
247+
248+
249+
def clear_verified_claims(msg):
250+
for claim in CLAIMS_WITH_VERIFIED:
251+
_vc_name = verified_claim_name(claim)
252+
try:
253+
del msg[_vc_name]
254+
except KeyError:
255+
pass
256+
return msg
257+
258+
235259
class RefreshAccessTokenRequest(oauth2.RefreshAccessTokenRequest):
236260
pass
237261

@@ -246,6 +270,9 @@ class AccessTokenResponse(oauth2.AccessTokenResponse):
246270

247271
def verify(self, **kwargs):
248272
super(AccessTokenResponse, self).verify(**kwargs)
273+
274+
clear_verified_claims(self)
275+
249276
if "id_token" in self:
250277
# Try to decode the JWT, checks the signature
251278
args = {}
@@ -258,7 +285,7 @@ def verify(self, **kwargs):
258285
if not idt.verify(**kwargs):
259286
return False
260287

261-
self["__verified_id_token"] = idt
288+
self[verified_claim_name("id_token")] = idt
262289
logger.info('Verified ID Token: {}'.format(idt.to_dict()))
263290

264291
return True
@@ -284,6 +311,7 @@ class AuthorizationResponse(oauth2.AuthorizationResponse,
284311

285312
def verify(self, **kwargs):
286313
super(AuthorizationResponse, self).verify(**kwargs)
314+
clear_verified_claims(self)
287315

288316
if "aud" in self:
289317
if "client_id" in kwargs:
@@ -324,7 +352,7 @@ def verify(self, **kwargs):
324352
if idt["c_hash"] != jws.left_hash(self["code"], hfunc):
325353
raise CHashError("Failed to verify code hash", idt)
326354

327-
self["__verified_id_token"] = idt
355+
self[verified_claim_name("id_token")] = idt
328356
return True
329357

330358

@@ -382,6 +410,8 @@ def verify(self, **kwargs):
382410
match."""
383411
super(AuthorizationRequest, self).verify(**kwargs)
384412

413+
clear_verified_claims(self)
414+
385415
args = {}
386416
for arg in ["keyjar", "opponent_id", "sender"]:
387417
try:
@@ -404,7 +434,7 @@ def verify(self, **kwargs):
404434
raise ValueError('{} != {}'.format(self[key], val))
405435

406436
# replace the JWT with the parsed and verified instance
407-
self["request"] = oidr
437+
self[verified_claim_name("request")] = oidr
408438

409439
if "id_token_hint" in self:
410440
if isinstance(self["id_token_hint"], str):
@@ -798,6 +828,8 @@ class EndSessionRequest(Message):
798828

799829
def verify(self, **kwargs):
800830
super(EndSessionRequest, self).verify(**kwargs)
831+
clear_verified_claims(self)
832+
801833
if "id_token_hint" in self:
802834
# Try to decode the JWT, checks the signature
803835
args = {}
@@ -811,7 +843,7 @@ def verify(self, **kwargs):
811843
return False
812844

813845
# replace the JWT with the IdToken instance
814-
self["verified_id_token_hint"] = idt
846+
self[verified_claim_name("id_token_hint")] = idt
815847

816848
return True
817849

tests/test_6_oidc.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
from oidcmsg.key_bundle import KeyBundle
1919
from oidcmsg.key_jar import KeyJar
2020
from oidcmsg.oauth2 import ResponseMessage
21-
from oidcmsg.oidc import AccessTokenRequest
21+
from oidcmsg.oidc import AccessTokenRequest, verified_claim_name
2222
from oidcmsg.oidc import CheckSessionRequest
2323
from oidcmsg.oidc import ClaimsRequest
2424
from oidcmsg.oidc import DiscoveryRequest
@@ -643,7 +643,7 @@ def test_at_hash():
643643

644644
at = AuthorizationResponse(**_info)
645645
assert at.verify(keyjar=keyjar, sigalg="HS256")
646-
assert 'at_hash' in at['__verified_id_token']
646+
assert 'at_hash' in at[verified_claim_name('id_token')]
647647

648648

649649
def test_c_hash():
@@ -667,7 +667,7 @@ def test_c_hash():
667667

668668
at = AuthorizationResponse(**_info)
669669
r = at.verify(keyjar=keyjar, sigalg="HS256")
670-
assert 'c_hash' in at['__verified_id_token']
670+
assert 'c_hash' in at[verified_claim_name('id_token')]
671671

672672

673673
def test_missing_c_hash():
@@ -766,9 +766,12 @@ def test_example(self):
766766
keyjar.add_symmetric('', _key.key)
767767
request.verify(keyjar=keyjar)
768768
assert isinstance(request, EndSessionRequest)
769-
assert _eq(request.keys(), ['id_token_hint', 'redirect_url', 'state'])
769+
assert _eq(request.keys(),
770+
[verified_claim_name('id_token_hint'), 'id_token_hint',
771+
'redirect_url', 'state'])
770772
assert request["state"] == "state0"
771-
assert request["id_token_hint"]["aud"] == ["client_1"]
773+
assert request[
774+
verified_claim_name("id_token_hint")]["aud"] == ["client_1"]
772775

773776

774777
class TestCheckSessionRequest(object):

0 commit comments

Comments
 (0)