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

Commit 40fe88a

Browse files
authored
Merge pull request #42 from IdentityPython/reread_jwks_uri
Needed to complete certification.
2 parents 0a1532f + 48186d6 commit 40fe88a

File tree

6 files changed

+70
-46
lines changed

6 files changed

+70
-46
lines changed

src/oidcmsg/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
__author__ = "Roland Hedberg"
2-
__version__ = "1.4.0"
2+
__version__ = "1.4.1"
33

44
import os
55
from typing import Dict

src/oidcmsg/impexp.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from typing import List
33
from typing import Optional
44

5+
from cryptojwt import as_unicode
56
from cryptojwt.utils import as_bytes
67
from cryptojwt.utils import importer
78
from cryptojwt.utils import qualified_name
@@ -25,7 +26,7 @@ def __init__(self):
2526
def dump_attr(self, cls, item, exclude_attributes: Optional[List[str]] = None) -> dict:
2627
if cls in [None, 0, "", [], {}, bool, b'']:
2728
if cls == b'':
28-
val = as_bytes(item)
29+
val = as_unicode(item)
2930
else:
3031
val = item
3132
elif cls == "DICT_TYPE":

src/oidcmsg/message.py

+39-29
Original file line numberDiff line numberDiff line change
@@ -314,10 +314,10 @@ def from_dict(self, dictionary, **kwargs):
314314
self._dict[key] = val
315315
continue
316316

317-
self._add_value(skey, vtyp, key, val, _deser, null_allowed)
317+
self._add_value(skey, vtyp, key, val, _deser, null_allowed, sformat="dict")
318318
return self
319319

320-
def _add_value(self, skey, vtyp, key, val, _deser, null_allowed):
320+
def _add_value(self, skey, vtyp, key, val, _deser, null_allowed, sformat="urlencoded"):
321321
"""
322322
Main method for adding a value to the instance. Does all the
323323
checking on type of value and if among allowed values.
@@ -350,7 +350,7 @@ def _add_value(self, skey, vtyp, key, val, _deser, null_allowed):
350350
self._dict[skey] = [val]
351351
elif _deser:
352352
try:
353-
self._dict[skey] = _deser(val, sformat="urlencoded")
353+
self._dict[skey] = _deser(val, sformat=sformat)
354354
except Exception as exc:
355355
raise DecodeError(ERRTXT % (key, exc))
356356
else:
@@ -402,16 +402,6 @@ def _add_value(self, skey, vtyp, key, val, _deser, null_allowed):
402402
except Exception as exc:
403403
raise DecodeError(ERRTXT % (key, exc))
404404
else:
405-
# if isinstance(val, str):
406-
# self._dict[skey] = val
407-
# elif isinstance(val, list):
408-
# if len(val) == 1:
409-
# self._dict[skey] = val[0]
410-
# elif not len(val):
411-
# pass
412-
# else:
413-
# raise TooManyValues(key)
414-
# else:
415405
self._dict[skey] = val
416406
elif vtyp is int:
417407
try:
@@ -468,6 +458,28 @@ def to_jwt(self, key=None, algorithm="", lev=0, lifetime=0):
468458
_jws = JWS(self.to_json(lev), alg=algorithm)
469459
return _jws.sign_compact(key)
470460

461+
def _gather_keys(self, keyjar, jwt, header, **kwargs):
462+
key = []
463+
464+
if keyjar:
465+
_keys = keyjar.get_jwt_verify_keys(jwt, **kwargs)
466+
if not _keys:
467+
keyjar.update()
468+
_keys = keyjar.get_jwt_verify_keys(jwt, **kwargs)
469+
key.extend(_keys)
470+
471+
if "alg" in header and header["alg"] != "none":
472+
if not key:
473+
if keyjar:
474+
keyjar.update()
475+
key = keyjar.get_jwt_verify_keys(jwt, **kwargs)
476+
if not key:
477+
raise MissingSigningKey("alg=%s" % header["alg"])
478+
else:
479+
raise MissingSigningKey("alg=%s" % header["alg"])
480+
481+
return key
482+
471483
def from_jwt(self, txt, keyjar, verify=True, **kwargs):
472484
"""
473485
Given a signed and/or encrypted JWT, verify its correctness and then
@@ -515,7 +527,6 @@ def from_jwt(self, txt, keyjar, verify=True, **kwargs):
515527
jso = _jwt.payload()
516528
_header = _jwt.headers
517529

518-
key = []
519530
# if "sender" in kwargs:
520531
# key.extend(keyjar.get_verify_key(owner=kwargs["sender"]))
521532

@@ -524,21 +535,13 @@ def from_jwt(self, txt, keyjar, verify=True, **kwargs):
524535
if _header["alg"] == "none":
525536
pass
526537
elif verify:
527-
if keyjar:
528-
key.extend(keyjar.get_jwt_verify_keys(_jwt, **kwargs))
538+
key = self._gather_keys(keyjar, _jwt, _header, **kwargs)
529539

530-
if "alg" in _header and _header["alg"] != "none":
531-
if not key:
532-
raise MissingSigningKey("alg=%s" % _header["alg"])
540+
if not key:
541+
raise MissingSigningKey("alg=%s" % _header["alg"])
533542

534543
logger.debug("Found signing key.")
535-
try:
536-
_verifier.verify_compact(txt, key)
537-
except NoSuitableSigningKeys:
538-
if keyjar:
539-
keyjar.update()
540-
key = keyjar.get_jwt_verify_keys(_jwt, **kwargs)
541-
_verifier.verify_compact(txt, key)
544+
_verifier.verify_compact(txt, key)
542545

543546
self.jws_header = _jwt.headers
544547
else:
@@ -850,8 +853,12 @@ def add_non_standard(msg1, msg2):
850853

851854

852855
def list_serializer(vals, sformat="urlencoded", lev=0):
853-
if isinstance(vals, str) or not isinstance(vals, list):
856+
if isinstance(vals, str) and sformat == "dict":
857+
return [vals]
858+
859+
if not isinstance(vals, list):
854860
raise ValueError("Expected list: %s" % vals)
861+
855862
if sformat == "urlencoded":
856863
return " ".join(vals)
857864
else:
@@ -864,8 +871,11 @@ def list_deserializer(val, sformat="urlencoded"):
864871
return val.split(" ")
865872
elif isinstance(val, list) and len(val) == 1:
866873
return val[0].split(" ")
867-
else:
868-
return val
874+
elif sformat == "dict":
875+
if isinstance(val, str):
876+
val = [val]
877+
878+
return val
869879

870880

871881
def sp_sep_list_serializer(vals, sformat="urlencoded", lev=0):

src/oidcmsg/oidc/__init__.py

+2-10
Original file line numberDiff line numberDiff line change
@@ -633,7 +633,7 @@ class RegistrationRequest(Message):
633633
# "client_id": SINGLE_OPTIONAL_STRING,
634634
# "client_secret": SINGLE_OPTIONAL_STRING,
635635
# "access_token": SINGLE_OPTIONAL_STRING,
636-
"post_logout_redirect_uris": OPTIONAL_LIST_OF_STRINGS,
636+
"post_logout_redirect_uri": SINGLE_OPTIONAL_STRING,
637637
"frontchannel_logout_uri": SINGLE_OPTIONAL_STRING,
638638
"frontchannel_logout_session_required": SINGLE_OPTIONAL_BOOLEAN,
639639
"backchannel_logout_uri": SINGLE_OPTIONAL_STRING,
@@ -771,14 +771,6 @@ def pack(self, alg="", **kwargs):
771771
else:
772772
self.pack_init()
773773

774-
# if 'jti' in self.c_param:
775-
# try:
776-
# _jti = kwargs['jti']
777-
# except KeyError:
778-
# _jti = uuid.uuid4().hex
779-
#
780-
# self['jti'] = _jti
781-
782774
def to_jwt(self, key=None, algorithm="", lev=0, lifetime=0):
783775
self.pack(alg=algorithm, lifetime=lifetime)
784776
return Message.to_jwt(self, key=key, algorithm=algorithm, lev=lev)
@@ -797,7 +789,7 @@ def verify(self, **kwargs):
797789
# check that I'm among the recipients
798790
if kwargs["client_id"] not in self["aud"]:
799791
raise NotForMe(
800-
"{} not in aud:{}".format(kwargs["client_id"], self["aud"]), self
792+
'"{}" not in {}'.format(kwargs["client_id"], self["aud"]), self
801793
)
802794

803795
# Then azp has to be present and be one of the aud values

src/oidcmsg/oidc/session.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,6 @@ def verify(self, **kwargs):
179179
return False
180180

181181
self[verified_claim_name("logout_token")] = idt
182-
logger.info("Verified ID Token: {}".format(idt.to_dict()))
182+
logger.info("Verified Logout Token: {}".format(idt.to_dict()))
183183

184184
return True

tests/test_06_oidc.py

+25-4
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,23 @@
66
from urllib.parse import parse_qs
77
from urllib.parse import urlencode
88

9-
import pytest
109
from cryptojwt.exception import BadSignature
1110
from cryptojwt.exception import UnsupportedAlgorithm
1211
from cryptojwt.jws.exception import SignerAlgError
1312
from cryptojwt.jws.utils import left_hash
1413
from cryptojwt.jwt import JWT
1514
from cryptojwt.key_bundle import KeyBundle
1615
from cryptojwt.key_jar import KeyJar
16+
import pytest
1717

1818
from oidcmsg import proper_path
1919
from oidcmsg import time_util
2020
from oidcmsg.exception import MessageException
2121
from oidcmsg.exception import MissingRequiredAttribute
2222
from oidcmsg.exception import NotAllowedValue
2323
from oidcmsg.exception import OidcMsgError
24-
from oidcmsg.oauth2 import ResponseMessage
2524
from oidcmsg.oauth2 import ROPCAccessTokenRequest
26-
from oidcmsg.oidc import JRD
25+
from oidcmsg.oauth2 import ResponseMessage
2726
from oidcmsg.oidc import AccessTokenRequest
2827
from oidcmsg.oidc import AccessTokenResponse
2928
from oidcmsg.oidc import AddressClaim
@@ -38,6 +37,7 @@
3837
from oidcmsg.oidc import EXPError
3938
from oidcmsg.oidc import IATError
4039
from oidcmsg.oidc import IdToken
40+
from oidcmsg.oidc import JRD
4141
from oidcmsg.oidc import Link
4242
from oidcmsg.oidc import OpenIDSchema
4343
from oidcmsg.oidc import ProviderConfigurationResponse
@@ -661,7 +661,7 @@ def test_deserialize(self):
661661
"client_secret_expires_at": 1577858400,
662662
"registration_access_token": "this.is.an.access.token.value.ffx83",
663663
"registration_client_uri": "https://server.example.com/connect/register?client_id"
664-
"=s6BhdRkqt3",
664+
"=s6BhdRkqt3",
665665
"token_endpoint_auth_method": "client_secret_basic",
666666
"application_type": "web",
667667
"redirect_uris": [
@@ -1601,3 +1601,24 @@ def test_correct_sign_alg():
16011601
client_id="554295ce3770612820620000",
16021602
allowed_sign_alg="HS256",
16031603
)
1604+
1605+
1606+
def test_ID_Token_space_in_id():
1607+
idt = IdToken(**{
1608+
"at_hash": "buCCujNN632UIV8-VbKhgw",
1609+
"sub": "user-subject-1234531",
1610+
"aud": "client_ifCttPphtLxtPWd20602 ^.+/",
1611+
"iss": "https://www.certification.openid.net/test/a/idpy/",
1612+
"exp": 1632495959,
1613+
"nonce": "B88En9UpdHkQZMQXK9U3KHzV",
1614+
"iat": 1632495659
1615+
})
1616+
1617+
assert idt["aud"] == ["client_ifCttPphtLxtPWd20602 ^.+/"]
1618+
1619+
idt = IdToken(**{'at_hash': 'rgMbiR-Dj11dQjxhCyLkOw', 'sub': 'user-subject-1234531',
1620+
'aud': 'client_dVCwIQuSKklinFP70742;#__$',
1621+
'iss': 'https://www.certification.openid.net/test/a/idpy/', 'exp': 1632639462,
1622+
'nonce': 'hUT3RhSooxC9CilrD8al6bGx', 'iat': 1632639162})
1623+
1624+
assert idt["aud"] == ["client_dVCwIQuSKklinFP70742;#__$"]

0 commit comments

Comments
 (0)