From 662e7d7c5cdc414bd987c17a02ab50cb83f85968 Mon Sep 17 00:00:00 2001 From: Roland Hedberg Date: Fri, 28 May 2021 10:45:08 +0200 Subject: [PATCH 1/6] First walk through implementing our agreement on token_type, token_syntax and token_class. --- src/oidcop/oauth2/authorization.py | 12 +-- src/oidcop/oauth2/introspection.py | 4 +- src/oidcop/oauth2/token.py | 16 ++-- src/oidcop/oidc/token.py | 12 +-- src/oidcop/oidc/userinfo.py | 2 +- src/oidcop/session/claims.py | 19 +++-- src/oidcop/session/grant.py | 49 ++++++------ src/oidcop/session/token.py | 99 ++++++++++++++++++------- src/oidcop/token/__init__.py | 25 ++++--- src/oidcop/token/exception.py | 3 + src/oidcop/token/handler.py | 48 ++++++------ src/oidcop/token/id_token.py | 4 +- src/oidcop/token/jwt_token.py | 68 +++++++++-------- tests/test_01_grant.py | 52 ++++++------- tests/test_02_sess_mngm_db.py | 2 +- tests/test_04_token_handler.py | 65 ++++++++-------- tests/test_05_id_token.py | 19 +++-- tests/test_05_jwt_token.py | 12 +-- tests/test_06_session_manager.py | 23 ++---- tests/test_07_userinfo.py | 14 ++-- tests/test_08_session_life.py | 28 +++---- tests/test_24_oauth2_token_endpoint.py | 8 +- tests/test_26_oidc_userinfo_endpoint.py | 12 +-- tests/test_31_oauth2_introspection.py | 15 +--- tests/test_35_oidc_token_endpoint.py | 8 +- tests/test_36_oauth2_token_exchange.py | 6 +- tests/test_50_persistence.py | 9 ++- tests/test_60_dpop.py | 4 +- 28 files changed, 341 insertions(+), 297 deletions(-) diff --git a/src/oidcop/oauth2/authorization.py b/src/oidcop/oauth2/authorization.py index c823588e..2a68230e 100755 --- a/src/oidcop/oauth2/authorization.py +++ b/src/oidcop/oauth2/authorization.py @@ -301,12 +301,12 @@ def verify_response_type(self, request: Union[Message, dict], cinfo: dict) -> bo # Is the asked for response_type among those that are permitted return set(request["response_type"]) in _registered - def mint_token(self, token_type, grant, session_id, based_on=None, **kwargs): - usage_rules = grant.usage_rules.get(token_type, {}) + def mint_token(self, token_class, grant, session_id, based_on=None, **kwargs): + usage_rules = grant.usage_rules.get(token_class, {}) token = grant.mint_token( session_id=session_id, endpoint_context=self.server_get("endpoint_context"), - token_type=token_type, + token_class=token_class, based_on=based_on, usage_rules=usage_rules, **kwargs, @@ -677,7 +677,7 @@ def create_authn_response(self, request: Union[dict, Message], sid: str) -> dict if "code" in request["response_type"]: _code = self.mint_token( - token_type="authorization_code", grant=grant, session_id=_sinfo["session_id"], + token_class="authorization_code", grant=grant, session_id=_sinfo["session_id"], ) aresp["code"] = _code.value handled_response_type.append("code") @@ -686,7 +686,7 @@ def create_authn_response(self, request: Union[dict, Message], sid: str) -> dict if "token" in rtype: _access_token = self.mint_token( - token_type="access_token", grant=grant, session_id=_sinfo["session_id"], + token_class="access_token", grant=grant, session_id=_sinfo["session_id"], ) aresp["access_token"] = _access_token.value aresp["token_type"] = "Bearer" @@ -707,7 +707,7 @@ def create_authn_response(self, request: Union[dict, Message], sid: str) -> dict try: id_token = self.mint_token( - token_type="id_token", + token_class="id_token", grant=grant, session_id=_sinfo["session_id"], **kwargs, diff --git a/src/oidcop/oauth2/introspection.py b/src/oidcop/oauth2/introspection.py index 0ae077f7..af1876f4 100644 --- a/src/oidcop/oauth2/introspection.py +++ b/src/oidcop/oauth2/introspection.py @@ -26,7 +26,7 @@ def __init__(self, server_get, **kwargs): def _introspect(self, token, client_id, grant): # Make sure that the token is an access_token or a refresh_token - if token.type not in ["access_token", "refresh_token"]: + if token.token_class not in ["access_token", "refresh_token"]: return None if not token.is_active(): @@ -44,7 +44,7 @@ def _introspect(self, token, client_id, grant): "active": True, "scope": " ".join(scope), "client_id": client_id, - "token_type": token.type, + "token_class": token.token_class, "exp": token.expires_at, "iat": token.issued_at, "sub": grant.sub, diff --git a/src/oidcop/oauth2/token.py b/src/oidcop/oauth2/token.py index e7e89b3d..ff1dc11f 100755 --- a/src/oidcop/oauth2/token.py +++ b/src/oidcop/oauth2/token.py @@ -48,7 +48,7 @@ def process_request(self, req: Union[Message, dict], **kwargs): def _mint_token( self, - type: str, + token_class: str, grant: Grant, session_id: str, client_id: str, @@ -75,8 +75,8 @@ def _mint_token( token = grant.mint_token( session_id, endpoint_context=_context, - token_type=type, - token_handler=_mngr.token_handler[type], + token_class=token_class, + token_handler=_mngr.token_handler[token_class], based_on=based_on, usage_rules=usage_rules, **_args, @@ -143,7 +143,7 @@ def process_request(self, req: Union[Message, dict], **kwargs): if "access_token" in _supports_minting: try: token = self._mint_token( - type="access_token", + token_class="access_token", grant=grant, session_id=_session_info["session_id"], client_id=_session_info["client_id"], @@ -159,7 +159,7 @@ def process_request(self, req: Union[Message, dict], **kwargs): if issue_refresh and "refresh_token" in _supports_minting: try: refresh_token = self._mint_token( - type="refresh_token", + token_class="refresh_token", grant=grant, session_id=_session_info["session_id"], client_id=_session_info["client_id"], @@ -227,7 +227,7 @@ def process_request(self, req: Union[Message, dict], **kwargs): _grant = _session_info["grant"] token = _grant.get_token(token_value) access_token = self._mint_token( - type="access_token", + token_class="access_token", grant=_grant, session_id=_session_info["session_id"], client_id=_session_info["client_id"], @@ -236,7 +236,7 @@ def process_request(self, req: Union[Message, dict], **kwargs): _resp = { "access_token": access_token.value, - "token_type": access_token.type, + "token_type": access_token.token_type, "scope": _grant.scope, } @@ -246,7 +246,7 @@ def process_request(self, req: Union[Message, dict], **kwargs): _mints = token.usage_rules.get("supports_minting") if "refresh_token" in _mints: refresh_token = self._mint_token( - type="refresh_token", + token_class="refresh_token", grant=_grant, session_id=_session_info["session_id"], client_id=_session_info["client_id"], diff --git a/src/oidcop/oidc/token.py b/src/oidcop/oidc/token.py index e25a8dd0..a98d1f48 100755 --- a/src/oidcop/oidc/token.py +++ b/src/oidcop/oidc/token.py @@ -89,7 +89,7 @@ def process_request(self, req: Union[Message, dict], **kwargs): if "access_token" in _supports_minting: try: token = self._mint_token( - type="access_token", + token_class="access_token", grant=grant, session_id=_session_info["session_id"], client_id=_session_info["client_id"], @@ -105,7 +105,7 @@ def process_request(self, req: Union[Message, dict], **kwargs): if issue_refresh and "refresh_token" in _supports_minting: try: refresh_token = self._mint_token( - type="refresh_token", + token_class="refresh_token", grant=grant, session_id=_session_info["session_id"], client_id=_session_info["client_id"], @@ -123,7 +123,7 @@ def process_request(self, req: Union[Message, dict], **kwargs): if "id_token" in _based_on.usage_rules.get("supports_minting"): try: _idtoken = self._mint_token( - type="id_token", + token_class="id_token", grant=grant, session_id=_session_info["session_id"], client_id=_session_info["client_id"], @@ -202,7 +202,7 @@ def process_request(self, req: Union[Message, dict], **kwargs): token = _grant.get_token(token_value) access_token = self._mint_token( - type="access_token", + token_class="access_token", grant=_grant, session_id=_session_info["session_id"], client_id=_session_info["client_id"], @@ -221,7 +221,7 @@ def process_request(self, req: Union[Message, dict], **kwargs): _mints = token.usage_rules.get("supports_minting") if "refresh_token" in _mints: refresh_token = self._mint_token( - type="refresh_token", + token_class="refresh_token", grant=_grant, session_id=_session_info["session_id"], client_id=_session_info["client_id"], @@ -233,7 +233,7 @@ def process_request(self, req: Union[Message, dict], **kwargs): if "id_token" in _mints: try: _idtoken = self._mint_token( - type="refresh_token", + token_class="refresh_token", grant=_grant, session_id=_session_info["session_id"], client_id=_session_info["client_id"], diff --git a/src/oidcop/oidc/userinfo.py b/src/oidcop/oidc/userinfo.py index 3d935c47..37f40078 100755 --- a/src/oidcop/oidc/userinfo.py +++ b/src/oidcop/oidc/userinfo.py @@ -110,7 +110,7 @@ def process_request(self, request=None, **kwargs): _grant = _session_info["grant"] token = _grant.get_token(request["access_token"]) # should be an access token - if token.type != "access_token": + if token.token_class != "access_token": return self.error_cls(error="invalid_token", error_description="Wrong type of token") # And it should be valid diff --git a/src/oidcop/session/claims.py b/src/oidcop/session/claims.py index 603d8de8..ee6c9667 100755 --- a/src/oidcop/session/claims.py +++ b/src/oidcop/session/claims.py @@ -30,10 +30,12 @@ class ClaimsInterface: def __init__(self, server_get): self.server_get = server_get - def authorization_request_claims(self, session_id: str, usage: Optional[str] = "") -> dict: + def authorization_request_claims(self, + session_id: str, + claims_release_ref: Optional[str] = "") -> dict: _grant = self.server_get("endpoint_context").session_manager.get_grant(session_id) if _grant.authorization_request and "claims" in _grant.authorization_request: - return _grant.authorization_request["claims"].get(usage, {}) + return _grant.authorization_request["claims"].get(claims_release_ref, {}) return {} @@ -63,19 +65,19 @@ def _get_module(self, usage, endpoint_context): return module - def get_claims(self, session_id: str, scopes: str, usage: str) -> dict: + def get_claims(self, session_id: str, scopes: str, claims_release_ref: str) -> dict: """ :param session_id: Session identifier :param scopes: Scopes - :param usage: Where to use the claims. One of - "userinfo"/"id_token"/"introspection"/"access_token" + :param claims_release_ref: Where to release the claims. One of + "userinfo"/"id_token"/"introspection"/"access_token" :return: Claims specification as a dictionary. """ _context = self.server_get("endpoint_context") # which endpoint module configuration to get the base claims from - module = self._get_module(usage, _context) + module = self._get_module(claims_release_ref, _context) if module: base_claims = module.kwargs.get("base_claims", {}) @@ -86,7 +88,7 @@ def get_claims(self, session_id: str, scopes: str, usage: str) -> dict: # Can there be per client specification of which claims to use. if module.kwargs.get("enable_claims_per_client"): - claims = self._get_client_claims(client_id, usage) + claims = self._get_client_claims(client_id, claims_release_ref) else: claims = {} @@ -102,7 +104,8 @@ def get_claims(self, session_id: str, scopes: str, usage: str) -> dict: # Bring in claims specification from the authorization request # This only goes for ID Token and user info - request_claims = self.authorization_request_claims(session_id=session_id, usage=usage) + request_claims = self.authorization_request_claims(session_id=session_id, + claims_release_ref=claims_release_ref) # This will add claims that has not be added before and # set filters on those claims that also appears in one of the sources above diff --git a/src/oidcop/session/grant.py b/src/oidcop/session/grant.py index 1f7d207d..634499df 100644 --- a/src/oidcop/session/grant.py +++ b/src/oidcop/session/grant.py @@ -41,14 +41,6 @@ def __init__( self.resources = resources -GRANT_TYPE_MAP = { - "authorization_code": "code", - "access_token": "access_token", - "refresh_token": "refresh_token", - "id_token": "id_token", -} - - def find_token(issued, token_id): for iss in issued: if iss.id == token_id: @@ -179,12 +171,17 @@ def payload_arguments( self, session_id: str, endpoint_context, - token_type: str, + claims_release_ref: str, scope: Optional[dict] = None, extra_payload: Optional[dict] = None, ) -> dict: """ + :param session_id: + :param endpoint_context: + :param claims_release_ref: One of "userinfo", "introspection", "id_token", "access_token" + :param scope: + :param extra_payload: :return: dictionary containing information to place in a token value """ if not scope: @@ -205,7 +202,7 @@ def payload_arguments( payload.update({"client_id": client_id, "sub": client_id}) _claims_restriction = endpoint_context.claims_interface.get_claims( - session_id, scopes=scope, usage=token_type + session_id, scopes=scope, claims_release_ref=claims_release_ref ) user_id, _, _ = endpoint_context.session_manager.decrypt_session_id(session_id) user_info = endpoint_context.claims_interface.get_user_claims(user_id, _claims_restriction) @@ -217,7 +214,7 @@ def mint_token( self, session_id: str, endpoint_context: object, - token_type: str, + token_class: str, token_handler: TokenHandler = None, based_on: Optional[SessionToken] = None, usage_rules: Optional[dict] = None, @@ -240,42 +237,46 @@ def mint_token( return None if based_on: - if based_on.supports_minting(token_type) is False: - raise MintingNotAllowed(f"Minting of {token_type} not supported") + if based_on.supports_minting(token_class) is False: + raise MintingNotAllowed(f"Minting of {token_class} not supported") if not based_on.is_active(): raise MintingNotAllowed("Token inactive") _base_on_ref = based_on.value else: _base_on_ref = None - if usage_rules is None and token_type in self.usage_rules: - usage_rules = self.usage_rules[token_type] + if usage_rules is None and token_class in self.usage_rules: + usage_rules = self.usage_rules[token_class] - token_class = self.token_map.get(token_type) - if token_type == "id_token": + _class = self.token_map.get(token_class) + if token_class == "id_token": class_args = {k: v for k, v in kwargs.items() if k not in ["code", "access_token"]} handler_args = {k: v for k, v in kwargs.items() if k in ["code", "access_token"]} else: class_args = kwargs handler_args = {} - if token_class: - item = token_class( - type=token_type, + if _class: + item = _class( + token_class=token_class, based_on=_base_on_ref, usage_rules=usage_rules, scope=scope, **class_args, ) if token_handler is None: - token_handler = endpoint_context.session_manager.token_handler.handler[ - GRANT_TYPE_MAP[token_type] - ] + token_handler = endpoint_context.session_manager.token_handler.handler[token_class] + + # Only access_token and id_token can give rise to claims release + if token_class in ["access_token", "id_token"]: + claims_release_ref = token_class + else: + claims_release_ref = "" token_payload = self.payload_arguments( session_id, endpoint_context, - token_type=token_type, + claims_release_ref=claims_release_ref, scope=scope, extra_payload=handler_args, ) diff --git a/src/oidcop/session/token.py b/src/oidcop/session/token.py index 865ebf4b..d7f301a9 100644 --- a/src/oidcop/session/token.py +++ b/src/oidcop/session/token.py @@ -20,14 +20,14 @@ class Item(ImpExp): } def __init__( - self, - usage_rules: Optional[dict] = None, - issued_at: int = 0, - expires_in: int = 0, - expires_at: int = 0, - not_before: int = 0, - revoked: bool = False, - used: int = 0, + self, + usage_rules: Optional[dict] = None, + issued_at: int = 0, + expires_in: int = 0, + expires_at: int = 0, + not_before: int = 0, + revoked: bool = False, + used: int = 0, ): ImpExp.__init__(self) self.issued_at = issued_at or time_sans_frac() @@ -84,7 +84,7 @@ class SessionToken(Item): "name": "", "resources": [], "scope": [], - "type": "", + "token_class": "", "usage_rules": {}, "used": 0, "value": "", @@ -92,21 +92,21 @@ class SessionToken(Item): ) def __init__( - self, - type: str = "", - value: str = "", - based_on: Optional[str] = None, - usage_rules: Optional[dict] = None, - issued_at: int = 0, - expires_in: int = 0, - expires_at: int = 0, - not_before: int = 0, - revoked: bool = False, - used: int = 0, - id: str = "", - scope: Optional[list] = None, - claims: Optional[dict] = None, - resources: Optional[list] = None, + self, + token_class: str = "", + value: str = "", + based_on: Optional[str] = None, + usage_rules: Optional[dict] = None, + issued_at: int = 0, + expires_in: int = 0, + expires_at: int = 0, + not_before: int = 0, + revoked: bool = False, + used: int = 0, + id: str = "", + scope: Optional[list] = None, + claims: Optional[dict] = None, + resources: Optional[list] = None, ): Item.__init__( self, @@ -119,7 +119,7 @@ def __init__( used=used, ) - self.type = type + self.token_class = token_class self.value = value self.based_on = based_on self.id = id or uuid1().hex @@ -138,16 +138,59 @@ def register_usage(self): def has_been_used(self): return self.used != 0 - def supports_minting(self, token_type): + def supports_minting(self, token_class): _supports_minting = self.usage_rules.get("supports_minting") if _supports_minting is None: return False else: - return token_type in _supports_minting + return token_class in _supports_minting class AccessToken(SessionToken): - pass + parameter = SessionToken.parameter.copy() + parameter.update( + { + "token_type": "" + } + ) + + def __init__( + self, + token_class: str = "", + value: str = "", + based_on: Optional[str] = None, + usage_rules: Optional[dict] = None, + issued_at: int = 0, + expires_in: int = 0, + expires_at: int = 0, + not_before: int = 0, + revoked: bool = False, + used: int = 0, + id: str = "", + scope: Optional[list] = None, + claims: Optional[dict] = None, + resources: Optional[list] = None, + token_type: Optional[str] = "bearer" + ): + SessionToken.__init__( + self, + token_class=token_class, + value=value, + based_on=based_on, + usage_rules=usage_rules, + issued_at=issued_at, + expires_in=expires_in, + expires_at=expires_at, + not_before=not_before, + revoked=revoked, + used=used, + id=id, + scope=scope, + claims=claims, + resources=resources + ) + + self.token_type = token_type class AuthorizationCode(SessionToken): diff --git a/src/oidcop/token/__init__.py b/src/oidcop/token/__init__.py index ba3bb1ea..afb49671 100755 --- a/src/oidcop/token/__init__.py +++ b/src/oidcop/token/__init__.py @@ -6,6 +6,7 @@ from oidcop import rndstr from oidcop.token.exception import UnknownToken +from oidcop.token.exception import WrongTokenClass from oidcop.token.exception import WrongTokenType from oidcop.util import Crypt from oidcop.util import lv_pack @@ -26,8 +27,8 @@ def is_expired(exp, when=0): class Token(object): - def __init__(self, typ, lifetime=300, **kwargs): - self.type = typ + def __init__(self, token_class, lifetime=300, **kwargs): + self.token_class = token_class self.lifetime = lifetime self.kwargs = kwargs @@ -65,22 +66,22 @@ def gather_args(self, *args, **kwargs): class DefaultToken(Token): - def __init__(self, password, typ="", token_type="Bearer", **kwargs): - Token.__init__(self, typ, **kwargs) + def __init__(self, password, token_class="", token_type="Bearer", **kwargs): + Token.__init__(self, token_class, **kwargs) self.crypt = Crypt(password) self.token_type = token_type - def __call__(self, session_id: Optional[str] = "", ttype: Optional[str] = "", **payload) -> str: + def __call__(self, session_id: Optional[str] = "", token_class: Optional[str] = "", **payload) -> str: """ Return a token. :param payload: Token information :return: """ - if not ttype and self.type: - ttype = self.type + if not token_class and self.token_class: + token_class = self.token_class else: - ttype = "A" + token_class = "authorization_code" if self.lifetime >= 0: exp = str(time_sans_frac() + self.lifetime) @@ -93,7 +94,7 @@ def __call__(self, session_id: Optional[str] = "", ttype: Optional[str] = "", ** rnd = rndstr(32) # Ultimate length multiple of 16 return base64.b64encode( - self.crypt.encrypt(lv_pack(rnd, ttype, session_id, exp).encode()) + self.crypt.encrypt(lv_pack(rnd, token_class, session_id, exp).encode()) ).decode("utf-8") def split_token(self, token): @@ -111,9 +112,9 @@ def info(self, token: str) -> dict: :param token: A token :return: dictionary with info about the token """ - _res = dict(zip(["_id", "type", "sid", "exp"], self.split_token(token))) - if _res["type"] != self.type: - raise WrongTokenType(_res["type"]) + _res = dict(zip(["_id", "token_class", "sid", "exp"], self.split_token(token))) + if _res["token_class"] != self.token_class: + raise WrongTokenClass(_res["token_class"]) else: _res["handler"] = self return _res diff --git a/src/oidcop/token/exception.py b/src/oidcop/token/exception.py index 965b38c9..8d4bef0c 100644 --- a/src/oidcop/token/exception.py +++ b/src/oidcop/token/exception.py @@ -6,6 +6,9 @@ class WrongTokenType(Exception): pass +class WrongTokenClass(Exception): + pass + class AccessCodeUsed(Exception): pass diff --git a/src/oidcop/token/handler.py b/src/oidcop/token/handler.py index 85800c8f..9fd25aa8 100755 --- a/src/oidcop/token/handler.py +++ b/src/oidcop/token/handler.py @@ -26,22 +26,23 @@ class TokenHandler(ImpExp): def __init__( self, - access_token_handler: Optional[Token] = None, - code_handler: Optional[Token] = None, - refresh_token_handler: Optional[Token] = None, - id_token_handler: Optional[Token] = None, + access_token: Optional[Token] = None, + authorization_code: Optional[Token] = None, + refresh_token: Optional[Token] = None, + id_token: Optional[Token] = None, ): ImpExp.__init__(self) - self.handler = {"code": code_handler, "access_token": access_token_handler} + self.handler = {"authorization_code": authorization_code, + "access_token": access_token} - self.handler_order = ["code", "access_token"] + self.handler_order = ["authorization_code", "access_token"] - if refresh_token_handler: - self.handler["refresh_token"] = refresh_token_handler + if refresh_token: + self.handler["refresh_token"] = refresh_token self.handler_order.append("refresh_token") - if id_token_handler: - self.handler["id_token"] = id_token_handler + if id_token: + self.handler["id_token"] = id_token self.handler_order.append("id_token") def __getitem__(self, typ): @@ -62,8 +63,8 @@ def info(self, item, order=None): def sid(self, token, order=None): return self.info(token, order)["sid"] - def type(self, token, order=None): - return self.info(token, order)["type"] + def token_class(self, token, order=None): + return self.info(token, order)["token_class"] def get_handler(self, token, order=None): if order is None: @@ -83,7 +84,7 @@ def keys(self): return self.handler.keys() -def init_token_handler(server_get, spec, typ): +def init_token_handler(server_get, spec, token_class): _kwargs = spec.get("kwargs", {}) _lt = spec.get("lifetime") @@ -109,7 +110,7 @@ def init_token_handler(server_get, spec, typ): ) _kwargs = spec - return cls(typ=typ, server_get=server_get, **_kwargs) + return cls(token_class=token_class, server_get=server_get, **_kwargs) def _add_passwd(keyjar, conf, kid): @@ -160,7 +161,10 @@ def factory( :return: TokenHandler instance """ - TTYPE = {"code": "A", "token": "T", "refresh": "R"} + token_class_map = {"code": "authorization_code", + "token": "access_token", + "refresh": "refresh_token", + 'idtoken': 'id_token'} key_defs = [] read_only = False @@ -184,17 +188,17 @@ def factory( kj = init_key_jar(key_defs=key_defs, private_path=jwks_file, read_only=read_only) args = {} - for typ, cnf, attr in [ - ("code", code, "code_handler"), - ("token", token, "access_token_handler"), - ("refresh", refresh, "refresh_token_handler"), + for cls, cnf, attr in [ + ("code", code, "authorization_code"), + ("token", token, "access_token"), + ("refresh", refresh, "refresh_token"), ]: if cnf is not None: if default_token(cnf): - _add_passwd(kj, cnf, typ) - args[attr] = init_token_handler(server_get, cnf, TTYPE[typ]) + _add_passwd(kj, cnf, cls) + args[attr] = init_token_handler(server_get, cnf, token_class_map[cls]) if id_token is not None: - args["id_token_handler"] = init_token_handler(server_get, id_token, typ="") + args["id_token"] = init_token_handler(server_get, id_token, token_class="") return TokenHandler(**args) diff --git a/src/oidcop/token/id_token.py b/src/oidcop/token/id_token.py index 609e29d8..0170dc23 100755 --- a/src/oidcop/token/id_token.py +++ b/src/oidcop/token/id_token.py @@ -119,12 +119,12 @@ class IDToken(Token): def __init__( self, - typ: Optional[str] = "I", + token_class: Optional[str] = "id_token", lifetime: Optional[int] = 300, server_get: Callable = None, **kwargs ): - Token.__init__(self, typ, **kwargs) + Token.__init__(self, token_class, **kwargs) self.lifetime = lifetime self.server_get = server_get self.kwargs = kwargs diff --git a/src/oidcop/token/jwt_token.py b/src/oidcop/token/jwt_token.py index 312c460d..d002e416 100644 --- a/src/oidcop/token/jwt_token.py +++ b/src/oidcop/token/jwt_token.py @@ -10,24 +10,25 @@ from . import is_expired from .exception import UnknownToken -TYPE_MAP = {"A": "code", "T": "access_token", "R": "refresh_token"} + +# TYPE_MAP = {"A": "code", "T": "access_token", "R": "refresh_token"} class JWTToken(Token): def __init__( - self, - typ, - # keyjar: KeyJar = None, - issuer: str = None, - aud: Optional[list] = None, - alg: str = "ES256", - lifetime: int = 300, - server_get: Callable = None, - token_type: str = "Bearer", - password: str = "", - **kwargs + self, + token_class, + # keyjar: KeyJar = None, + issuer: str = None, + aud: Optional[list] = None, + alg: str = "ES256", + lifetime: int = 300, + server_get: Callable = None, + token_type: str = "Bearer", + password: str = "", + **kwargs ): - Token.__init__(self, typ, **kwargs) + Token.__init__(self, token_class, **kwargs) self.token_type = token_type self.lifetime = lifetime self.crypt = Crypt(password) @@ -46,23 +47,23 @@ def load_custom_claims(self, payload: dict = None): # inherit me and do your things here return payload - def __call__(self, session_id: Optional[str] = "", ttype: Optional[str] = "", **payload) -> str: + def __call__(self, session_id: Optional[str] = "", token_class: Optional[str] = "", + **payload) -> str: """ Return a token. :param session_id: Session id - :param subject: - :param grant: - :param kwargs: KeyWord arguments + :param token_class: Token class + :param payload: A dictionary with information that is part of the payload of the JWT. :return: Signed JSON Web Token """ - if not ttype and self.type: - ttype = self.type + if not token_class and self.token_class: + token_class = self.token_class else: - ttype = "A" + token_class = "authorization_code" - payload.update({"sid": session_id, "ttype": ttype}) + payload.update({"sid": session_id, "token_class": token_class}) payload = self.load_custom_claims(payload) # payload.update(kwargs) @@ -73,6 +74,16 @@ def __call__(self, session_id: Optional[str] = "", ttype: Optional[str] = "", ** return signer.pack(payload) + def get_payload(self, token): + _context = self.server_get("endpoint_context") + verifier = JWT(key_jar=_context.keyjar, allowed_sign_algs=[self.alg]) + try: + _payload = verifier.unpack(token) + except JWSException: + raise UnknownToken() + + return _payload + def info(self, token): """ Return type of Token (A=Access code, T=Token, R=Refresh token) and @@ -81,19 +92,14 @@ def info(self, token): :param token: A token :return: tuple of token type and session id """ - _context = self.server_get("endpoint_context") - verifier = JWT(key_jar=_context.keyjar, allowed_sign_algs=[self.alg]) - try: - _payload = verifier.unpack(token) - except JWSException: - raise UnknownToken() + _payload = self.get_payload(token) if is_expired(_payload["exp"]): raise ToOld("Token has expired") # All the token metadata _res = { "sid": _payload["sid"], - "type": _payload["ttype"], + "token_class": _payload["token_class"], "exp": _payload["exp"], "handler": self, } @@ -104,12 +110,10 @@ def is_expired(self, token, when=0): Evaluate whether the token has expired or not :param token: The token - :param when: The time against which to check the expiration - 0 means now. + :param when: The time against which to check the expiration. 0 means now. :return: True/False """ - verifier = JWT(key_jar=self.key_jar, allowed_sign_algs=[self.alg]) - _payload = verifier.unpack(token) + _payload = self.get_payload(token) return is_expired(_payload["exp"], when) def gather_args(self, sid, sdb, udb): diff --git a/tests/test_01_grant.py b/tests/test_01_grant.py index 84302480..69708cf8 100644 --- a/tests/test_01_grant.py +++ b/tests/test_01_grant.py @@ -57,7 +57,7 @@ def test_access_code(): token = AuthorizationCode("authorization_code", value="ABCD") assert token.issued_at - assert token.type == "authorization_code" + assert token.token_class == "authorization_code" assert token.value == "ABCD" token.register_usage() @@ -71,7 +71,7 @@ def test_access_token(): "access_token", value="1234", based_on=code.id, usage_rules={"max_usage": 2} ) assert token.issued_at - assert token.type == "access_token" + assert token.token_class == "access_token" assert token.value == "1234" token.register_usage() @@ -128,14 +128,14 @@ def test_mint_token(self): code = grant.mint_token( session_id, endpoint_context=self.endpoint_context, - token_type="authorization_code", + token_class="authorization_code", token_handler=TOKEN_HANDLER["authorization_code"], ) access_token = grant.mint_token( session_id, endpoint_context=self.endpoint_context, - token_type="access_token", + token_class="access_token", token_handler=TOKEN_HANDLER["access_token"], based_on=code, scope=["openid", "foo", "bar"], @@ -152,14 +152,14 @@ def test_grant(self): code = grant.mint_token( session_id, endpoint_context=self.endpoint_context, - token_type="authorization_code", + token_class="authorization_code", token_handler=TOKEN_HANDLER["authorization_code"], ) access_token = grant.mint_token( session_id, endpoint_context=self.endpoint_context, - token_type="access_token", + token_class="access_token", token_handler=TOKEN_HANDLER["access_token"], based_on=code, ) @@ -167,7 +167,7 @@ def test_grant(self): refresh_token = grant.mint_token( session_id, endpoint_context=self.endpoint_context, - token_type="refresh_token", + token_class="refresh_token", token_handler=TOKEN_HANDLER["refresh_token"], based_on=code, ) @@ -186,14 +186,14 @@ def test_get_token(self): code = grant.mint_token( session_id, endpoint_context=self.endpoint_context, - token_type="authorization_code", + token_class="authorization_code", token_handler=TOKEN_HANDLER["authorization_code"], ) access_token = grant.mint_token( session_id, endpoint_context=self.endpoint_context, - token_type="access_token", + token_class="access_token", token_handler=TOKEN_HANDLER["access_token"], based_on=code, scope=["openid", "foo", "bar"], @@ -215,14 +215,14 @@ def test_grant_revoked_based_on(self): code = grant.mint_token( session_id, endpoint_context=self.endpoint_context, - token_type="authorization_code", + token_class="authorization_code", token_handler=TOKEN_HANDLER["authorization_code"], ) access_token = grant.mint_token( session_id, endpoint_context=self.endpoint_context, - token_type="access_token", + token_class="access_token", token_handler=TOKEN_HANDLER["access_token"], based_on=code, ) @@ -230,7 +230,7 @@ def test_grant_revoked_based_on(self): refresh_token = grant.mint_token( session_id, endpoint_context=self.endpoint_context, - token_type="refresh_token", + token_class="refresh_token", token_handler=TOKEN_HANDLER["refresh_token"], based_on=code, ) @@ -252,14 +252,14 @@ def test_revoke(self): code = grant.mint_token( session_id, endpoint_context=self.endpoint_context, - token_type="authorization_code", + token_class="authorization_code", token_handler=TOKEN_HANDLER["authorization_code"], ) access_token = grant.mint_token( session_id, endpoint_context=self.endpoint_context, - token_type="access_token", + token_class="access_token", token_handler=TOKEN_HANDLER["access_token"], based_on=code, ) @@ -272,7 +272,7 @@ def test_revoke(self): access_token_2 = grant.mint_token( session_id, endpoint_context=self.endpoint_context, - token_type="access_token", + token_class="access_token", token_handler=TOKEN_HANDLER["access_token"], based_on=code, ) @@ -291,14 +291,14 @@ def test_json_conversion(self): code = grant.mint_token( session_id, endpoint_context=self.endpoint_context, - token_type="authorization_code", + token_class="authorization_code", token_handler=TOKEN_HANDLER["authorization_code"], ) grant.mint_token( session_id, endpoint_context=self.endpoint_context, - token_type="access_token", + token_class="access_token", token_handler=TOKEN_HANDLER["access_token"], based_on=code, ) @@ -311,9 +311,9 @@ def test_json_conversion(self): tt = {"code": 0, "access_token": 0} for token in _grant_copy.issued_token: - if token.type == "authorization_code": + if token.token_class == "authorization_code": tt["code"] += 1 - if token.type == "access_token": + if token.token_class == "access_token": tt["access_token"] += 1 assert tt == {"code": 1, "access_token": 1} @@ -329,7 +329,7 @@ def test_json_no_token_map(self): grant.mint_token( session_id, endpoint_context=self.endpoint_context, - token_type="authorization_code", + token_class="authorization_code", token_handler=TOKEN_HANDLER["authorization_code"], ) @@ -346,14 +346,14 @@ def test_json_custom_token_map(self): code = grant.mint_token( session_id, endpoint_context=self.endpoint_context, - token_type="authorization_code", + token_class="authorization_code", token_handler=TOKEN_HANDLER["authorization_code"], ) grant.mint_token( session_id, endpoint_context=self.endpoint_context, - token_type="access_token", + token_class="access_token", token_handler=TOKEN_HANDLER["access_token"], based_on=code, ) @@ -361,7 +361,7 @@ def test_json_custom_token_map(self): grant.mint_token( session_id, endpoint_context=self.endpoint_context, - token_type="my_token", + token_class="my_token", token_handler=DefaultToken("my_token", typ="M"), ) @@ -375,7 +375,7 @@ def test_json_custom_token_map(self): for token in _grant_copy.issued_token: for _type in tt.keys(): - if token.type == _type: + if token.token_class == _type: tt[_type] += 1 assert tt == { @@ -400,14 +400,14 @@ def test_get_spec(self): code = grant.mint_token( session_id, endpoint_context=self.endpoint_context, - token_type="authorization_code", + token_class="authorization_code", token_handler=TOKEN_HANDLER["authorization_code"], ) access_token = grant.mint_token( session_id, endpoint_context=self.endpoint_context, - token_type="access_token", + token_class="access_token", token_handler=TOKEN_HANDLER["access_token"], based_on=code, scope=["openid", "email", "eduperson"], diff --git a/tests/test_02_sess_mngm_db.py b/tests/test_02_sess_mngm_db.py index d5c3f0c3..e4cacbdc 100644 --- a/tests/test_02_sess_mngm_db.py +++ b/tests/test_02_sess_mngm_db.py @@ -124,7 +124,7 @@ def test_jump_ahead(self): assert len(grant_info.issued_token) == 1 token = grant_info.issued_token[0] assert token.value == "1234567890" - assert token.type == "access_code" + assert token.token_class == "access_code" def test_replace_grant_info_not_there(self): grant = Grant() diff --git a/tests/test_04_token_handler.py b/tests/test_04_token_handler.py index 3e263a66..36c1b6dd 100644 --- a/tests/test_04_token_handler.py +++ b/tests/test_04_token_handler.py @@ -5,9 +5,9 @@ import secrets import time -from oidcop.configure import OPConfiguration import pytest +from oidcop.configure import OPConfiguration from oidcop.endpoint import Endpoint from oidcop.server import Server from oidcop.token import Crypt @@ -78,12 +78,13 @@ class TestDefaultToken(object): def setup_token_handler(self): password = "The longer the better. Is this close to enough ?" grant_expires_in = 600 - self.th = DefaultToken(password, typ="A", lifetime=grant_expires_in) + self.th = DefaultToken(password, token_class="authorization_code", + lifetime=grant_expires_in) def test_default_token_split_token(self): _token = self.th("session_id") p = self.th.split_token(_token) - assert p[1] == "A" + assert p[1] == "authorization_code" assert p[2] == "session_id" def test_default_token_info(self): @@ -92,7 +93,7 @@ def test_default_token_info(self): assert set(_info.keys()) == { "_id", - "type", + "token_class", "sid", "exp", "handler", @@ -115,52 +116,54 @@ def setup_token_handler(self): token_expires_in = 900 refresh_token_expires_in = 86400 - code_handler = DefaultToken(password, typ="A", lifetime=grant_expires_in) - access_token_handler = DefaultToken(password, typ="T", lifetime=token_expires_in) - refresh_token_handler = DefaultToken(password, typ="R", lifetime=refresh_token_expires_in) + authorization_code = DefaultToken(password, token_class="authorization_code", + lifetime=grant_expires_in) + access_token = DefaultToken(password, token_class="access_token", lifetime=token_expires_in) + refresh_token = DefaultToken(password, token_class="refresh_token", + lifetime=refresh_token_expires_in) self.handler = TokenHandler( - code_handler=code_handler, - access_token_handler=access_token_handler, - refresh_token_handler=refresh_token_handler, + authorization_code=authorization_code, + access_token=access_token, + refresh_token=refresh_token, ) def test_getitem(self): - th = self.handler["code"] - assert th.type == "A" + th = self.handler["authorization_code"] + assert th.token_class == "authorization_code" th = self.handler["access_token"] - assert th.type == "T" + assert th.token_class == "access_token" th = self.handler["refresh_token"] - assert th.type == "R" + assert th.token_class == "refresh_token" def test_contains(self): - assert "code" in self.handler + assert "authorization_code" in self.handler assert "access_token" in self.handler assert "refresh_token" in self.handler assert "foobar" not in self.handler def test_info(self): - _token = self.handler["code"]("another_id") + _token = self.handler["authorization_code"]("another_id") _info = self.handler.info(_token) - assert _info["type"] == "A" + assert _info["token_class"] == "authorization_code" def test_sid(self): - _token = self.handler["code"]("another_id") + _token = self.handler["authorization_code"]("another_id") sid = self.handler.sid(_token) assert sid == "another_id" - def test_type(self): - _token = self.handler["code"]("another_id") - assert self.handler.type(_token) == "A" + def test_token_class(self): + _token = self.handler["authorization_code"]("another_id") + assert self.handler.token_class(_token) == "authorization_code" def test_get_handler(self): - _token = self.handler["code"]("another_id") + _token = self.handler["authorization_code"]("another_id") th, _ = self.handler.get_handler(_token) - assert th.type == "A" + assert th.token_class == "authorization_code" def test_keys(self): - assert set(self.handler.keys()) == {"access_token", "code", "refresh_token"} + assert set(self.handler.keys()) == {"access_token", "authorization_code", "refresh_token"} KEYDEFS = [ @@ -173,7 +176,7 @@ def test_token_handler_from_config(): conf = { "issuer": "https://example.com/op", "keys": {"uri_path": "static/jwks.json", "key_defs": KEYDEFS}, - "endpoint": {"endpoint": {"path": "endpoint", "class": Endpoint, "kwargs": {}},}, + "endpoint": {"endpoint": {"path": "endpoint", "class": Endpoint, "kwargs": {}}, }, "token_handler_args": { "jwks_def": { "private_path": "private/token_jwks.json", @@ -191,7 +194,7 @@ def test_token_handler_from_config(): }, "refresh": { "class": "oidcop.token.jwt_token.JWTToken", - "kwargs": {"lifetime": 3600, "aud": ["https://example.org/appl"],}, + "kwargs": {"lifetime": 3600, "aud": ["https://example.org/appl"], }, }, "id_token": { "class": "oidcop.token.id_token.IDToken", @@ -210,17 +213,17 @@ def test_token_handler_from_config(): assert token_handler assert len(token_handler.handler) == 4 assert set(token_handler.handler.keys()) == { - "code", + "authorization_code", "access_token", "refresh_token", "id_token", } - assert isinstance(token_handler.handler["code"], DefaultToken) + assert isinstance(token_handler.handler["authorization_code"], DefaultToken) assert isinstance(token_handler.handler["access_token"], JWTToken) assert isinstance(token_handler.handler["refresh_token"], JWTToken) assert isinstance(token_handler.handler["id_token"], IDToken) - assert token_handler.handler["code"].lifetime == 600 + assert token_handler.handler["authorization_code"].lifetime == 600 assert token_handler.handler["access_token"].alg == "ES256" assert token_handler.handler["access_token"].kwargs == {"add_claims_by_scope": True} @@ -262,7 +265,7 @@ def test_file(jwks): conf = { "issuer": "https://example.com/op", "keys": {"uri_path": "static/jwks.json", "key_defs": KEYDEFS}, - "endpoint": {"endpoint": {"path": "endpoint", "class": Endpoint, "kwargs": {}},}, + "endpoint": {"endpoint": {"path": "endpoint", "class": Endpoint, "kwargs": {}}, }, "token_handler_args": { "code": {"kwargs": {"lifetime": 600}}, "token": { @@ -275,7 +278,7 @@ def test_file(jwks): }, "refresh": { "class": "oidcop.token.jwt_token.JWTToken", - "kwargs": {"lifetime": 3600, "aud": ["https://example.org/appl"],}, + "kwargs": {"lifetime": 3600, "aud": ["https://example.org/appl"], }, }, "id_token": { "class": "oidcop.token.id_token.IDToken", diff --git a/tests/test_05_id_token.py b/tests/test_05_id_token.py index 8696f76c..f584007d 100644 --- a/tests/test_05_id_token.py +++ b/tests/test_05_id_token.py @@ -186,8 +186,8 @@ def _mint_code(self, grant, session_id): return grant.mint_token( session_id=session_id, endpoint_context=self.endpoint_context, - token_type="authorization_code", - token_handler=self.session_manager.token_handler["code"], + token_class="authorization_code", + token_handler=self.session_manager.token_handler["authorization_code"], expires_at=time_sans_frac() + 300, # 5 minutes from now ) @@ -195,7 +195,7 @@ def _mint_access_token(self, grant, session_id, token_ref): access_token = grant.mint_token( session_id=session_id, endpoint_context=self.endpoint_context, - token_type="access_token", + token_class="access_token", token_handler=self.session_manager.token_handler["access_token"], expires_at=time_sans_frac() + 900, # 15 minutes from now based_on=token_ref, # Means the token (tok) was used to mint this token @@ -206,7 +206,7 @@ def _mint_id_token(self, grant, session_id, token_ref=None, code=None, access_to return grant.mint_token( session_id=session_id, endpoint_context=self.endpoint_context, - token_type="id_token", + token_class="id_token", token_handler=self.session_manager.token_handler["id_token"], expires_at=time_sans_frac() + 900, # 15 minutes from now based_on=token_ref, # Means the token (tok) was used to mint this token @@ -419,7 +419,7 @@ def test_client_claims(self): self.endpoint_context.cdb["client_1"]["id_token_claims"] = {"address": None} _claims = self.endpoint_context.claims_interface.get_claims( - session_id=session_id, scopes=AREQ["scope"], usage="id_token" + session_id=session_id, scopes=AREQ["scope"], claims_release_ref="id_token" ) grant.claims = {"id_token": _claims} @@ -438,7 +438,7 @@ def test_client_claims_with_default(self): grant = self.session_manager[session_id] _claims = self.endpoint_context.claims_interface.get_claims( - session_id=session_id, scopes=AREQ["scope"], usage="id_token" + session_id=session_id, scopes=AREQ["scope"], claims_release_ref="id_token" ) grant.claims = {"id_token": _claims} @@ -461,7 +461,7 @@ def test_client_claims_scopes(self): self.session_manager.token_handler["id_token"].kwargs["add_claims_by_scope"] = True _claims = self.endpoint_context.claims_interface.get_claims( - session_id=session_id, scopes=AREQS["scope"], usage="id_token" + session_id=session_id, scopes=AREQS["scope"], claims_release_ref="id_token" ) grant.claims = {"id_token": _claims} @@ -483,7 +483,7 @@ def test_client_claims_scopes_and_request_claims_no_match(self): self.session_manager.token_handler["id_token"].kwargs["add_claims_by_scope"] = True _claims = self.endpoint_context.claims_interface.get_claims( - session_id=session_id, scopes=AREQRC["scope"], usage="id_token" + session_id=session_id, scopes=AREQRC["scope"], claims_release_ref="id_token" ) grant.claims = {"id_token": _claims} @@ -510,7 +510,7 @@ def test_client_claims_scopes_and_request_claims_one_match(self): self.session_manager.token_handler["id_token"].kwargs["add_claims_by_scope"] = True _claims = self.endpoint_context.claims_interface.get_claims( - session_id=session_id, scopes=_req["scope"], usage="id_token" + session_id=session_id, scopes=_req["scope"], claims_release_ref="id_token" ) grant.claims = {"id_token": _claims} @@ -538,7 +538,6 @@ def test_id_token_info(self): endpoint_context = self.endpoint_context sman = endpoint_context.session_manager - server_get = sman.token_handler.handler["id_token"].server_get _info = self.session_manager.token_handler.info(id_token.value) assert "sid" in _info assert "exp" in _info diff --git a/tests/test_05_jwt_token.py b/tests/test_05_jwt_token.py index 40f5cb7f..78f5f5e3 100644 --- a/tests/test_05_jwt_token.py +++ b/tests/test_05_jwt_token.py @@ -83,7 +83,7 @@ BASEDIR = os.path.abspath(os.path.dirname(__file__)) MAP = { - "authorization_code": "code", + "authorization_code": "authorization_code", "access_token": "access_token", "refresh_token": "refresh_token", "id_token": "id_token", @@ -203,13 +203,13 @@ def _create_session(self, auth_req, sub_type="public", sector_identifier=""): ae, authz_req, self.user_id, client_id=client_id, sub_type=sub_type ) - def _mint_token(self, type, grant, session_id, based_on=None, **kwargs): + def _mint_token(self, token_class, grant, session_id, based_on=None, **kwargs): # Constructing an authorization code is now done return grant.mint_token( session_id=session_id, endpoint_context=self.endpoint_context, - token_type=type, - token_handler=self.session_manager.token_handler.handler[MAP[type]], + token_class=token_class, + token_handler=self.session_manager.token_handler.handler[token_class], expires_at=time_sans_frac() + 300, # 5 minutes from now based_on=based_on, **kwargs @@ -228,7 +228,7 @@ def test_parse(self): _verifier = JWT(self.endpoint_context.keyjar) _info = _verifier.unpack(access_token.value) - assert _info["ttype"] == "T" + assert _info["token_class"] == "access_token" # assert _info["eduperson_scoped_affiliation"] == ["staff@example.org"] assert set(_info["aud"]) == {"client_1"} @@ -241,7 +241,7 @@ def test_info(self): access_token = self._mint_token("access_token", grant, session_id, code) _info = self.session_manager.token_handler.info(access_token.value) - assert _info["type"] == "T" + assert _info["token_class"] == "access_token" assert _info["sid"] == session_id @pytest.mark.parametrize("enable_claims_per_client", [True, False]) diff --git a/tests/test_06_session_manager.py b/tests/test_06_session_manager.py index 6acb4458..acc85371 100644 --- a/tests/test_06_session_manager.py +++ b/tests/test_06_session_manager.py @@ -1,6 +1,6 @@ -import pytest from oidcmsg.oidc import AuthorizationRequest from oidcmsg.time_util import time_sans_frac +import pytest from oidcop.authn_event import AuthnEvent from oidcop.authn_event import create_authn_event @@ -23,18 +23,11 @@ response_type="code", ) -MAP = { - "authorization_code": "code", - "access_token": "access_token", - "refresh_token": "refresh_token", -} - KEYDEFS = [ {"type": "RSA", "key": "", "use": ["sig"]}, {"type": "EC", "crv": "P-256", "use": ["sig"]}, ] - USER_ID = "diana" @@ -68,7 +61,7 @@ def create_session_manager(self): }, "refresh": { "class": "oidcop.token.jwt_token.JWTToken", - "kwargs": {"lifetime": 3600, "aud": ["https://example.org/appl"],}, + "kwargs": {"lifetime": 3600, "aud": ["https://example.org/appl"], }, }, }, "endpoint": { @@ -190,13 +183,13 @@ def test_create_session_sub_type(self, sub_type, sector_identifier): assert grant_1.authorization_request != grant_3.authorization_request assert grant_3.authorization_request != grant_2.authorization_request - def _mint_token(self, type, grant, session_id, based_on=None): + def _mint_token(self, token_class, grant, session_id, based_on=None): # Constructing an authorization code is now done return grant.mint_token( session_id=session_id, endpoint_context=self.endpoint_context, - token_type=type, - token_handler=self.session_manager.token_handler.handler[MAP[type]], + token_class=token_class, + token_handler=self.session_manager.token_handler.handler[token_class], expires_at=time_sans_frac() + 300, # 5 minutes from now based_on=based_on, ) @@ -284,7 +277,7 @@ def test_find_token(self): _session_id = self.session_manager.encrypted_session_id("diana", "client_1", grant.id) _token = self.session_manager.find_token(_session_id, access_token.value) - assert _token.type == "access_token" + assert _token.token_class == "access_token" assert _token.id == access_token.id def test_get_authentication_event(self): @@ -538,7 +531,7 @@ def test_authentication_events(self): assert isinstance(res[0], AuthnEvent) try: - self.session_manager.get_authentication_events(user_id="diana",) + self.session_manager.get_authentication_events(user_id="diana", ) except AttributeError: pass else: @@ -611,7 +604,7 @@ def test_grants(self): assert isinstance(res, list) try: - self.session_manager.grants(user_id="diana",) + self.session_manager.grants(user_id="diana", ) except AttributeError: pass else: diff --git a/tests/test_07_userinfo.py b/tests/test_07_userinfo.py index d163e945..87152d07 100644 --- a/tests/test_07_userinfo.py +++ b/tests/test_07_userinfo.py @@ -280,7 +280,7 @@ def test_collect_user_info(self): session_id = self._create_session(_req) _userinfo_restriction = self.claims_interface.get_claims( - session_id=session_id, scopes=OIDR["scope"], usage="userinfo" + session_id=session_id, scopes=OIDR["scope"], claims_release_ref="userinfo" ) res = self.claims_interface.get_user_claims("diana", _userinfo_restriction) @@ -293,7 +293,7 @@ def test_collect_user_info(self): } _id_token_restriction = self.claims_interface.get_claims( - session_id=session_id, scopes=OIDR["scope"], usage="id_token" + session_id=session_id, scopes=OIDR["scope"], claims_release_ref="id_token" ) res = self.claims_interface.get_user_claims("diana", _id_token_restriction) @@ -304,7 +304,7 @@ def test_collect_user_info(self): } _restriction = self.claims_interface.get_claims( - session_id=session_id, scopes=OIDR["scope"], usage="introspection" + session_id=session_id, scopes=OIDR["scope"], claims_release_ref="introspection" ) res = self.claims_interface.get_user_claims("diana", _restriction) @@ -320,7 +320,7 @@ def test_collect_user_info_2(self): _uid, _cid, _gid = self.session_manager.decrypt_session_id(session_id) _userinfo_restriction = self.claims_interface.get_claims( - session_id=session_id, scopes=_req["scope"], usage="userinfo" + session_id=session_id, scopes=_req["scope"], claims_release_ref="userinfo" ) res = self.claims_interface.get_user_claims("diana", _userinfo_restriction) @@ -351,7 +351,7 @@ def test_collect_user_info_scope_not_supported_no_base_claims(self): del _userinfo_endpoint.kwargs["base_claims"] _userinfo_restriction = self.claims_interface.get_claims( - session_id=session_id, scopes=_req["scope"], usage="userinfo" + session_id=session_id, scopes=_req["scope"], claims_release_ref="userinfo" ) res = self.claims_interface.get_user_claims("diana", _userinfo_restriction) @@ -374,7 +374,7 @@ def test_collect_user_info_enable_claims_per_client(self): self.endpoint_context.cdb[_req["client_id"]]["userinfo_claims"] = {"phone_number": None} _userinfo_restriction = self.claims_interface.get_claims( - session_id=session_id, scopes=_req["scope"], usage="userinfo" + session_id=session_id, scopes=_req["scope"], claims_release_ref="userinfo" ) res = self.claims_interface.get_user_claims("diana", _userinfo_restriction) @@ -495,7 +495,7 @@ def test_collect_user_info_custom_scope(self): session_id = self._create_session(_req) _restriction = self.claims_interface.get_claims( - session_id=session_id, scopes=_req["scope"], usage="userinfo" + session_id=session_id, scopes=_req["scope"], claims_release_ref="userinfo" ) res = self.claims_interface.get_user_claims("diana", _restriction) diff --git a/tests/test_08_session_life.py b/tests/test_08_session_life.py index 9aca9394..4c962469 100644 --- a/tests/test_08_session_life.py +++ b/tests/test_08_session_life.py @@ -101,8 +101,8 @@ def auth(self): code = grant.mint_token( session_id=session_id, endpoint_context=self.endpoint_context, - token_type="authorization_code", - token_handler=self.session_manager.token_handler["code"], + token_class="authorization_code", + token_handler=self.session_manager.token_handler["authorization_code"], expires_at=time_sans_frac() + 300, # 5 minutes from now ) @@ -135,7 +135,7 @@ def test_code_flow(self): tok = self.session_manager.find_token(session_id, TOKEN_REQ["code"]) # Verify that it's of the correct type and can be used - assert tok.type == "authorization_code" + assert tok.token_class == "authorization_code" assert tok.is_active() # Mint an access token and a refresh token and mark the code as used @@ -144,10 +144,10 @@ def test_code_flow(self): grant = self.session_manager[session_id] - access_token = grant.mint_token( + grant.mint_token( session_id=session_id, endpoint_context=self.endpoint_context, - token_type="access_token", + token_class="access_token", token_handler=self.session_manager.token_handler["access_token"], expires_at=time_sans_frac() + 900, # 15 minutes from now based_on=tok, # Means the token (tok) was used to mint this token @@ -158,7 +158,7 @@ def test_code_flow(self): refresh_token = grant.mint_token( session_id=session_id, endpoint_context=self.endpoint_context, - token_type="refresh_token", + token_class="refresh_token", token_handler=self.session_manager.token_handler["refresh_token"], based_on=tok, ) @@ -184,7 +184,7 @@ def test_code_flow(self): access_token_2 = grant.mint_token( session_id=session_id, endpoint_context=self.endpoint_context, - token_type="access_token", + token_class="access_token", token_handler=self.session_manager.token_handler["access_token"], expires_at=time_sans_frac() + 900, # 15 minutes from now based_on=reftok, # Means the token (tok) was used to mint this token @@ -350,8 +350,8 @@ def auth(self): code = grant.mint_token( session_id=session_id, endpoint_context=self.endpoint_context, - token_type="authorization_code", - token_handler=self.session_manager.token_handler["code"], + token_class="authorization_code", + token_handler=self.session_manager.token_handler["authorization_code"], expires_at=time_sans_frac() + 300, # 5 minutes from now ) return code @@ -382,7 +382,7 @@ def test_code_flow(self): tok = self.session_manager.find_token(session_id, TOKEN_REQ["code"]) # Verify that it's of the correct type and can be used - assert tok.type == "authorization_code" + assert tok.token_class == "authorization_code" assert tok.is_active() # Mint an access token and a refresh token and mark the code as used @@ -395,10 +395,10 @@ def test_code_flow(self): grant = self.session_manager[session_id] - access_token = grant.mint_token( + grant.mint_token( session_id=session_id, endpoint_context=self.endpoint_context, - token_type="access_token", + token_class="access_token", token_handler=self.session_manager.token_handler["access_token"], expires_at=time_sans_frac() + 900, # 15 minutes from now based_on=tok, # Means the token (tok) was used to mint this token @@ -410,7 +410,7 @@ def test_code_flow(self): refresh_token = grant.mint_token( session_id=session_id, endpoint_context=self.endpoint_context, - token_type="refresh_token", + token_class="refresh_token", token_handler=self.session_manager.token_handler["refresh_token"], based_on=tok, ) @@ -444,7 +444,7 @@ def test_code_flow(self): access_token_2 = grant.mint_token( session_id=session_id, endpoint_context=self.endpoint_context, - token_type="access_token", + token_class="access_token", token_handler=self.session_manager.token_handler["access_token"], expires_at=time_sans_frac() + 900, # 15 minutes from now based_on=reftok, # Means the refresh token (reftok) was used to mint this token diff --git a/tests/test_24_oauth2_token_endpoint.py b/tests/test_24_oauth2_token_endpoint.py index 2222447d..424346e8 100644 --- a/tests/test_24_oauth2_token_endpoint.py +++ b/tests/test_24_oauth2_token_endpoint.py @@ -191,8 +191,8 @@ def _mint_code(self, grant, client_id): _code = grant.mint_token( session_id=session_id, endpoint_context=self.endpoint_context, - token_type="authorization_code", - token_handler=self.session_manager.token_handler["code"], + token_class="authorization_code", + token_handler=self.session_manager.token_handler["authorization_code"], usage_rules=usage_rules, ) @@ -211,7 +211,7 @@ def _mint_access_token(self, grant, session_id, token_ref=None): _token = grant.mint_token( _session_info, endpoint_context=self.endpoint_context, - token_type="access_token", + token_class="access_token", token_handler=self.session_manager.token_handler["access_token"], based_on=token_ref, # Means the token (tok) was used to mint this token usage_rules=usage_rules, @@ -329,7 +329,6 @@ def test_do_refresh_access_token(self): assert set(_resp["response_args"].keys()) == { "access_token", "token_type", - "expires_in", "refresh_token", "scope", } @@ -376,7 +375,6 @@ def test_do_2nd_refresh_access_token(self): assert set(_2nd_resp["response_args"].keys()) == { "access_token", "token_type", - "expires_in", "refresh_token", "scope", } diff --git a/tests/test_26_oidc_userinfo_endpoint.py b/tests/test_26_oidc_userinfo_endpoint.py index e607a230..367c0541 100755 --- a/tests/test_26_oidc_userinfo_endpoint.py +++ b/tests/test_26_oidc_userinfo_endpoint.py @@ -189,18 +189,18 @@ def _mint_code(self, grant, session_id): return grant.mint_token( session_id=session_id, endpoint_context=self.endpoint.server_get("endpoint_context"), - token_type="authorization_code", - token_handler=self.session_manager.token_handler["code"], + token_class="authorization_code", + token_handler=self.session_manager.token_handler["authorization_code"], expires_at=time_sans_frac() + 300, # 5 minutes from now ) - def _mint_token(self, token_type, grant, session_id, token_ref=None): + def _mint_token(self, token_class, grant, session_id, token_ref=None): _session_info = self.session_manager.get_session_info(session_id, grant=True) return grant.mint_token( session_id=session_id, endpoint_context=self.endpoint.server_get("endpoint_context"), - token_type=token_type, - token_handler=self.session_manager.token_handler[token_type], + token_class=token_class, + token_handler=self.session_manager.token_handler[token_class], expires_at=time_sans_frac() + 900, # 15 minutes from now based_on=token_ref, # Means the token (tok) was used to mint this token ) @@ -324,7 +324,7 @@ def test_custom_scope(self): self.endpoint.server_get("endpoint_context").claims_interface.add_claims_by_scope = True grant.claims = { "userinfo": self.endpoint.server_get("endpoint_context").claims_interface.get_claims( - session_id=session_id, scopes=_auth_req["scope"], usage="userinfo" + session_id=session_id, scopes=_auth_req["scope"], claims_release_ref="userinfo" ) } diff --git a/tests/test_31_oauth2_introspection.py b/tests/test_31_oauth2_introspection.py index ae497157..36450cc1 100644 --- a/tests/test_31_oauth2_introspection.py +++ b/tests/test_31_oauth2_introspection.py @@ -85,12 +85,6 @@ BASEDIR = os.path.abspath(os.path.dirname(__file__)) -MAP = { - "authorization_code": "code", - "access_token": "access_token", - "refresh_token": "refresh_token", -} - def full_path(local_file): return os.path.join(BASEDIR, local_file) @@ -217,13 +211,13 @@ def _create_session(self, auth_req, sub_type="public", sector_identifier=""): ae, authz_req, self.user_id, client_id=client_id, sub_type=sub_type ) - def _mint_token(self, type, grant, session_id, based_on=None, **kwargs): + def _mint_token(self, token_class, grant, session_id, based_on=None, **kwargs): # Constructing an authorization code is now done return grant.mint_token( session_id=session_id, endpoint_context=self.token_endpoint.server_get("endpoint_context"), - token_type=type, - token_handler=self.session_manager.token_handler.handler[MAP[type]], + token_class=token_class, + token_handler=self.session_manager.token_handler.handler[token_class], expires_at=time_sans_frac() + 300, # 5 minutes from now based_on=based_on, **kwargs @@ -325,7 +319,6 @@ def test_do_response(self): assert set(_payload.keys()) == { "active", "iss", - "token_type", "sub", "client_id", "exp", @@ -396,7 +389,7 @@ def test_introspection_claims(self): _c_interface = self.introspection_endpoint.server_get("endpoint_context").claims_interface grant.claims = { "introspection": _c_interface.get_claims( - session_id, scopes=AUTH_REQ["scope"], usage="introspection" + session_id, scopes=AUTH_REQ["scope"], claims_release_ref="introspection" ) } diff --git a/tests/test_35_oidc_token_endpoint.py b/tests/test_35_oidc_token_endpoint.py index ec0bd6a4..c85b114a 100755 --- a/tests/test_35_oidc_token_endpoint.py +++ b/tests/test_35_oidc_token_endpoint.py @@ -223,8 +223,8 @@ def _mint_code(self, grant, client_id): _code = grant.mint_token( session_id=session_id, endpoint_context=self.endpoint_context, - token_type="authorization_code", - token_handler=self.session_manager.token_handler["code"], + token_class="authorization_code", + token_handler=self.session_manager.token_handler["authorization_code"], usage_rules=usage_rules, ) @@ -243,7 +243,7 @@ def _mint_access_token(self, grant, session_id, token_ref=None): _token = grant.mint_token( _session_info, endpoint_context=self.endpoint_context, - token_type="access_token", + token_class="access_token", token_handler=self.session_manager.token_handler["access_token"], based_on=token_ref, # Means the token (tok) was used to mint this token usage_rules=usage_rules, @@ -365,7 +365,6 @@ def test_do_refresh_access_token(self): assert set(_resp["response_args"].keys()) == { "access_token", "token_type", - "expires_in", "refresh_token", "id_token", "scope", @@ -413,7 +412,6 @@ def test_do_2nd_refresh_access_token(self): assert set(_2nd_resp["response_args"].keys()) == { "access_token", "token_type", - "expires_in", "refresh_token", "id_token", "scope", diff --git a/tests/test_36_oauth2_token_exchange.py b/tests/test_36_oauth2_token_exchange.py index 5e7641c1..56e76ed2 100644 --- a/tests/test_36_oauth2_token_exchange.py +++ b/tests/test_36_oauth2_token_exchange.py @@ -193,15 +193,15 @@ def _mint_code(self, grant, session_id): return grant.mint_token( session_id=session_id, endpoint_context=self.endpoint.server_get("endpoint_context"), - token_type="authorization_code", - token_handler=self.session_manager.token_handler["code"], + token_class="authorization_code", + token_handler=self.session_manager.token_handler["authorization_code"], ) def _mint_access_token(self, grant, session_id, token_ref=None, resources=None): return grant.mint_token( session_id=session_id, endpoint_context=self.endpoint.server_get("endpoint_context"), - token_type="access_token", + token_class="access_token", token_handler=self.session_manager.token_handler["access_token"], based_on=token_ref, resources=resources, diff --git a/tests/test_50_persistence.py b/tests/test_50_persistence.py index 11b801c8..6c137322 100644 --- a/tests/test_50_persistence.py +++ b/tests/test_50_persistence.py @@ -231,8 +231,8 @@ def _mint_code(self, grant, session_id, index=1): _code = grant.mint_token( session_id, endpoint_context=self.endpoint[index].server_get("endpoint_context"), - token_type="authorization_code", - token_handler=self.session_manager[index].token_handler["code"], + token_class="authorization_code", + token_handler=self.session_manager[index].token_handler["authorization_code"], ) self.session_manager[index].set( @@ -249,7 +249,7 @@ def _mint_access_token(self, grant, session_id, token_ref=None, index=1): _token = grant.mint_token( session_id=session_id, endpoint_context=self.endpoint[index].server_get("endpoint_context"), - token_type="access_token", + token_class="access_token", token_handler=self.session_manager[index].token_handler["access_token"], based_on=token_ref, # Means the token (tok) was used to mint this token ) @@ -409,7 +409,8 @@ def test_custom_scope(self): grant.claims = { "userinfo": self.endpoint[1] .server_get("endpoint_context") - .claims_interface.get_claims(session_id, scopes=_auth_req["scope"], usage="userinfo") + .claims_interface.get_claims(session_id, scopes=_auth_req["scope"], + claims_release_ref="userinfo") } self._dump_restore(1, 2) diff --git a/tests/test_60_dpop.py b/tests/test_60_dpop.py index 62af2b79..14e7dc9a 100644 --- a/tests/test_60_dpop.py +++ b/tests/test_60_dpop.py @@ -218,8 +218,8 @@ def _mint_code(self, grant, client_id): _code = grant.mint_token( session_id=session_id, endpoint_context=self.endpoint_context, - token_type="authorization_code", - token_handler=self.session_manager.token_handler["code"], + token_class="authorization_code", + token_handler=self.session_manager.token_handler["authorization_code"], usage_rules=usage_rules, ) From 5a13dbfa2d7cfcdf055806613af069641977cea9 Mon Sep 17 00:00:00 2001 From: Roland Hedberg Date: Fri, 28 May 2021 15:01:49 +0200 Subject: [PATCH 2/6] More descriptive name. --- src/oidcop/session/claims.py | 22 +++++++++++----------- src/oidcop/session/grant.py | 12 ++++++------ tests/test_05_id_token.py | 10 +++++----- tests/test_07_userinfo.py | 14 +++++++------- tests/test_26_oidc_userinfo_endpoint.py | 2 +- tests/test_31_oauth2_introspection.py | 2 +- tests/test_50_persistence.py | 2 +- 7 files changed, 32 insertions(+), 32 deletions(-) diff --git a/src/oidcop/session/claims.py b/src/oidcop/session/claims.py index ee6c9667..edcb1076 100755 --- a/src/oidcop/session/claims.py +++ b/src/oidcop/session/claims.py @@ -25,17 +25,17 @@ def available_claims(endpoint_context): class ClaimsInterface: init_args = {"add_claims_by_scope": False, "enable_claims_per_client": False} - claims_types = ["userinfo", "introspection", "id_token", "access_token"] + claims_release_points = ["userinfo", "introspection", "id_token", "access_token"] def __init__(self, server_get): self.server_get = server_get def authorization_request_claims(self, session_id: str, - claims_release_ref: Optional[str] = "") -> dict: + claims_release_point: Optional[str] = "") -> dict: _grant = self.server_get("endpoint_context").session_manager.get_grant(session_id) if _grant.authorization_request and "claims" in _grant.authorization_request: - return _grant.authorization_request["claims"].get(claims_release_ref, {}) + return _grant.authorization_request["claims"].get(claims_release_point, {}) return {} @@ -65,19 +65,19 @@ def _get_module(self, usage, endpoint_context): return module - def get_claims(self, session_id: str, scopes: str, claims_release_ref: str) -> dict: + def get_claims(self, session_id: str, scopes: str, claims_release_point: str) -> dict: """ :param session_id: Session identifier :param scopes: Scopes - :param claims_release_ref: Where to release the claims. One of + :param claims_release_point: Where to release the claims. One of "userinfo"/"id_token"/"introspection"/"access_token" :return: Claims specification as a dictionary. """ _context = self.server_get("endpoint_context") # which endpoint module configuration to get the base claims from - module = self._get_module(claims_release_ref, _context) + module = self._get_module(claims_release_point, _context) if module: base_claims = module.kwargs.get("base_claims", {}) @@ -88,7 +88,7 @@ def get_claims(self, session_id: str, scopes: str, claims_release_ref: str) -> d # Can there be per client specification of which claims to use. if module.kwargs.get("enable_claims_per_client"): - claims = self._get_client_claims(client_id, claims_release_ref) + claims = self._get_client_claims(client_id, claims_release_point) else: claims = {} @@ -105,7 +105,7 @@ def get_claims(self, session_id: str, scopes: str, claims_release_ref: str) -> d # Bring in claims specification from the authorization request # This only goes for ID Token and user info request_claims = self.authorization_request_claims(session_id=session_id, - claims_release_ref=claims_release_ref) + claims_release_point=claims_release_point) # This will add claims that has not be added before and # set filters on those claims that also appears in one of the sources above @@ -116,7 +116,7 @@ def get_claims(self, session_id: str, scopes: str, claims_release_ref: str) -> d def get_claims_all_usage(self, session_id: str, scopes: str) -> dict: _claims = {} - for usage in self.claims_types: + for usage in self.claims_release_points: _claims[usage] = self.get_claims(session_id, scopes, usage) return _claims @@ -192,7 +192,7 @@ def by_schema(cls, **kwa): class OAuth2ClaimsInterface(ClaimsInterface): - claims_types = ["introspection", "access_token"] + claims_release_points = ["introspection", "access_token"] def _get_module(self, usage, endpoint_context): module = None @@ -208,6 +208,6 @@ def _get_module(self, usage, endpoint_context): def get_claims_all_usage(self, session_id: str, scopes: str) -> dict: _claims = {} - for usage in self.claims_types: + for usage in self.claims_release_points: _claims[usage] = self.get_claims(session_id, scopes, usage) return _claims diff --git a/src/oidcop/session/grant.py b/src/oidcop/session/grant.py index 634499df..297ea08c 100644 --- a/src/oidcop/session/grant.py +++ b/src/oidcop/session/grant.py @@ -171,7 +171,7 @@ def payload_arguments( self, session_id: str, endpoint_context, - claims_release_ref: str, + claims_release_point: str, scope: Optional[dict] = None, extra_payload: Optional[dict] = None, ) -> dict: @@ -179,7 +179,7 @@ def payload_arguments( :param session_id: :param endpoint_context: - :param claims_release_ref: One of "userinfo", "introspection", "id_token", "access_token" + :param claims_release_point: One of "userinfo", "introspection", "id_token", "access_token" :param scope: :param extra_payload: :return: dictionary containing information to place in a token value @@ -202,7 +202,7 @@ def payload_arguments( payload.update({"client_id": client_id, "sub": client_id}) _claims_restriction = endpoint_context.claims_interface.get_claims( - session_id, scopes=scope, claims_release_ref=claims_release_ref + session_id, scopes=scope, claims_release_point=claims_release_point ) user_id, _, _ = endpoint_context.session_manager.decrypt_session_id(session_id) user_info = endpoint_context.claims_interface.get_user_claims(user_id, _claims_restriction) @@ -269,14 +269,14 @@ def mint_token( # Only access_token and id_token can give rise to claims release if token_class in ["access_token", "id_token"]: - claims_release_ref = token_class + claims_release_point = token_class else: - claims_release_ref = "" + claims_release_point = "" token_payload = self.payload_arguments( session_id, endpoint_context, - claims_release_ref=claims_release_ref, + claims_release_point=claims_release_point, scope=scope, extra_payload=handler_args, ) diff --git a/tests/test_05_id_token.py b/tests/test_05_id_token.py index f584007d..c6f3058b 100644 --- a/tests/test_05_id_token.py +++ b/tests/test_05_id_token.py @@ -419,7 +419,7 @@ def test_client_claims(self): self.endpoint_context.cdb["client_1"]["id_token_claims"] = {"address": None} _claims = self.endpoint_context.claims_interface.get_claims( - session_id=session_id, scopes=AREQ["scope"], claims_release_ref="id_token" + session_id=session_id, scopes=AREQ["scope"], claims_release_point="id_token" ) grant.claims = {"id_token": _claims} @@ -438,7 +438,7 @@ def test_client_claims_with_default(self): grant = self.session_manager[session_id] _claims = self.endpoint_context.claims_interface.get_claims( - session_id=session_id, scopes=AREQ["scope"], claims_release_ref="id_token" + session_id=session_id, scopes=AREQ["scope"], claims_release_point="id_token" ) grant.claims = {"id_token": _claims} @@ -461,7 +461,7 @@ def test_client_claims_scopes(self): self.session_manager.token_handler["id_token"].kwargs["add_claims_by_scope"] = True _claims = self.endpoint_context.claims_interface.get_claims( - session_id=session_id, scopes=AREQS["scope"], claims_release_ref="id_token" + session_id=session_id, scopes=AREQS["scope"], claims_release_point="id_token" ) grant.claims = {"id_token": _claims} @@ -483,7 +483,7 @@ def test_client_claims_scopes_and_request_claims_no_match(self): self.session_manager.token_handler["id_token"].kwargs["add_claims_by_scope"] = True _claims = self.endpoint_context.claims_interface.get_claims( - session_id=session_id, scopes=AREQRC["scope"], claims_release_ref="id_token" + session_id=session_id, scopes=AREQRC["scope"], claims_release_point="id_token" ) grant.claims = {"id_token": _claims} @@ -510,7 +510,7 @@ def test_client_claims_scopes_and_request_claims_one_match(self): self.session_manager.token_handler["id_token"].kwargs["add_claims_by_scope"] = True _claims = self.endpoint_context.claims_interface.get_claims( - session_id=session_id, scopes=_req["scope"], claims_release_ref="id_token" + session_id=session_id, scopes=_req["scope"], claims_release_point="id_token" ) grant.claims = {"id_token": _claims} diff --git a/tests/test_07_userinfo.py b/tests/test_07_userinfo.py index 87152d07..f556fcca 100644 --- a/tests/test_07_userinfo.py +++ b/tests/test_07_userinfo.py @@ -280,7 +280,7 @@ def test_collect_user_info(self): session_id = self._create_session(_req) _userinfo_restriction = self.claims_interface.get_claims( - session_id=session_id, scopes=OIDR["scope"], claims_release_ref="userinfo" + session_id=session_id, scopes=OIDR["scope"], claims_release_point="userinfo" ) res = self.claims_interface.get_user_claims("diana", _userinfo_restriction) @@ -293,7 +293,7 @@ def test_collect_user_info(self): } _id_token_restriction = self.claims_interface.get_claims( - session_id=session_id, scopes=OIDR["scope"], claims_release_ref="id_token" + session_id=session_id, scopes=OIDR["scope"], claims_release_point="id_token" ) res = self.claims_interface.get_user_claims("diana", _id_token_restriction) @@ -304,7 +304,7 @@ def test_collect_user_info(self): } _restriction = self.claims_interface.get_claims( - session_id=session_id, scopes=OIDR["scope"], claims_release_ref="introspection" + session_id=session_id, scopes=OIDR["scope"], claims_release_point="introspection" ) res = self.claims_interface.get_user_claims("diana", _restriction) @@ -320,7 +320,7 @@ def test_collect_user_info_2(self): _uid, _cid, _gid = self.session_manager.decrypt_session_id(session_id) _userinfo_restriction = self.claims_interface.get_claims( - session_id=session_id, scopes=_req["scope"], claims_release_ref="userinfo" + session_id=session_id, scopes=_req["scope"], claims_release_point="userinfo" ) res = self.claims_interface.get_user_claims("diana", _userinfo_restriction) @@ -351,7 +351,7 @@ def test_collect_user_info_scope_not_supported_no_base_claims(self): del _userinfo_endpoint.kwargs["base_claims"] _userinfo_restriction = self.claims_interface.get_claims( - session_id=session_id, scopes=_req["scope"], claims_release_ref="userinfo" + session_id=session_id, scopes=_req["scope"], claims_release_point="userinfo" ) res = self.claims_interface.get_user_claims("diana", _userinfo_restriction) @@ -374,7 +374,7 @@ def test_collect_user_info_enable_claims_per_client(self): self.endpoint_context.cdb[_req["client_id"]]["userinfo_claims"] = {"phone_number": None} _userinfo_restriction = self.claims_interface.get_claims( - session_id=session_id, scopes=_req["scope"], claims_release_ref="userinfo" + session_id=session_id, scopes=_req["scope"], claims_release_point="userinfo" ) res = self.claims_interface.get_user_claims("diana", _userinfo_restriction) @@ -495,7 +495,7 @@ def test_collect_user_info_custom_scope(self): session_id = self._create_session(_req) _restriction = self.claims_interface.get_claims( - session_id=session_id, scopes=_req["scope"], claims_release_ref="userinfo" + session_id=session_id, scopes=_req["scope"], claims_release_point="userinfo" ) res = self.claims_interface.get_user_claims("diana", _restriction) diff --git a/tests/test_26_oidc_userinfo_endpoint.py b/tests/test_26_oidc_userinfo_endpoint.py index 367c0541..e30a429f 100755 --- a/tests/test_26_oidc_userinfo_endpoint.py +++ b/tests/test_26_oidc_userinfo_endpoint.py @@ -324,7 +324,7 @@ def test_custom_scope(self): self.endpoint.server_get("endpoint_context").claims_interface.add_claims_by_scope = True grant.claims = { "userinfo": self.endpoint.server_get("endpoint_context").claims_interface.get_claims( - session_id=session_id, scopes=_auth_req["scope"], claims_release_ref="userinfo" + session_id=session_id, scopes=_auth_req["scope"], claims_release_point="userinfo" ) } diff --git a/tests/test_31_oauth2_introspection.py b/tests/test_31_oauth2_introspection.py index 36450cc1..fbdbc0f6 100644 --- a/tests/test_31_oauth2_introspection.py +++ b/tests/test_31_oauth2_introspection.py @@ -389,7 +389,7 @@ def test_introspection_claims(self): _c_interface = self.introspection_endpoint.server_get("endpoint_context").claims_interface grant.claims = { "introspection": _c_interface.get_claims( - session_id, scopes=AUTH_REQ["scope"], claims_release_ref="introspection" + session_id, scopes=AUTH_REQ["scope"], claims_release_point="introspection" ) } diff --git a/tests/test_50_persistence.py b/tests/test_50_persistence.py index 6c137322..9052dd27 100644 --- a/tests/test_50_persistence.py +++ b/tests/test_50_persistence.py @@ -410,7 +410,7 @@ def test_custom_scope(self): "userinfo": self.endpoint[1] .server_get("endpoint_context") .claims_interface.get_claims(session_id, scopes=_auth_req["scope"], - claims_release_ref="userinfo") + claims_release_point="userinfo") } self._dump_restore(1, 2) From e9930489d315582f66ab6899baee7d4a55f52b5a Mon Sep 17 00:00:00 2001 From: Roland Hedberg Date: Fri, 28 May 2021 16:06:04 +0200 Subject: [PATCH 3/6] Carry token_type to the token minting. --- src/oidcop/oauth2/token.py | 2 ++ src/oidcop/oidc/token.py | 2 ++ src/oidcop/session/grant.py | 6 +++++- tests/test_60_dpop.py | 5 +++++ 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/oidcop/oauth2/token.py b/src/oidcop/oauth2/token.py index ff1dc11f..d35af5d3 100755 --- a/src/oidcop/oauth2/token.py +++ b/src/oidcop/oauth2/token.py @@ -54,6 +54,7 @@ def _mint_token( client_id: str, based_on: Optional[SessionToken] = None, token_args: Optional[dict] = None, + token_type: Optional[str] = "" ) -> SessionToken: _context = self.endpoint.server_get("endpoint_context") _mngr = _context.session_manager @@ -79,6 +80,7 @@ def _mint_token( token_handler=_mngr.token_handler[token_class], based_on=based_on, usage_rules=usage_rules, + token_type=token_type, **_args, ) diff --git a/src/oidcop/oidc/token.py b/src/oidcop/oidc/token.py index a98d1f48..0e4dc5e3 100755 --- a/src/oidcop/oidc/token.py +++ b/src/oidcop/oidc/token.py @@ -94,6 +94,7 @@ def process_request(self, req: Union[Message, dict], **kwargs): session_id=_session_info["session_id"], client_id=_session_info["client_id"], based_on=_based_on, + token_type=token_type, ) except MintingNotAllowed as err: logger.warning(err) @@ -207,6 +208,7 @@ def process_request(self, req: Union[Message, dict], **kwargs): session_id=_session_info["session_id"], client_id=_session_info["client_id"], based_on=token, + token_type=token_type ) _resp = { diff --git a/src/oidcop/session/grant.py b/src/oidcop/session/grant.py index 297ea08c..3b7b91cf 100644 --- a/src/oidcop/session/grant.py +++ b/src/oidcop/session/grant.py @@ -152,7 +152,7 @@ def __init__( self.issued_token = issued_token or [] self.id = uuid1().hex self.sub = sub - self.extra = {} + self.extra = extra or {} if token_map is None: self.token_map = TOKEN_MAP @@ -219,6 +219,7 @@ def mint_token( based_on: Optional[SessionToken] = None, usage_rules: Optional[dict] = None, scope: Optional[list] = None, + token_type: Optional[str] = "", **kwargs, ) -> Optional[SessionToken]: """ @@ -256,6 +257,9 @@ def mint_token( class_args = kwargs handler_args = {} + if token_class == "access_token" and token_type: + class_args["token_type"] = token_type + if _class: item = _class( token_class=token_class, diff --git a/tests/test_60_dpop.py b/tests/test_60_dpop.py index 14e7dc9a..35aa2ffd 100644 --- a/tests/test_60_dpop.py +++ b/tests/test_60_dpop.py @@ -264,3 +264,8 @@ def test_process_request(self): _payload = jws.jwt.payload() assert "cnf" in _payload assert _payload["cnf"]["jkt"] == _req["dpop_jkt"] + + # Make sure DPoP also is in the session access token instance. + _session_info = self.session_manager.get_session_info_by_token(access_token) + _token = self.session_manager.find_token(_session_info["session_id"], access_token) + assert _token.token_type == "DPoP" From 011e8351b4f0a269310f0340db405e1addf6e1d7 Mon Sep 17 00:00:00 2001 From: Roland Hedberg Date: Mon, 31 May 2021 09:32:44 +0200 Subject: [PATCH 4/6] Publish token_type at introspection endpoint. --- src/oidcop/oauth2/introspection.py | 8 ++++++++ tests/test_31_oauth2_introspection.py | 2 ++ 2 files changed, 10 insertions(+) diff --git a/src/oidcop/oauth2/introspection.py b/src/oidcop/oauth2/introspection.py index af1876f4..1266c610 100644 --- a/src/oidcop/oauth2/introspection.py +++ b/src/oidcop/oauth2/introspection.py @@ -51,6 +51,14 @@ def _introspect(self, token, client_id, grant): "iss": _context.issuer, } + try: + _token_type = token.token_type + except AttributeError: + _token_type = None + + if _token_type: + ret["token_type"] = _token_type + if aud: ret["aud"] = aud diff --git a/tests/test_31_oauth2_introspection.py b/tests/test_31_oauth2_introspection.py index fbdbc0f6..52cb6330 100644 --- a/tests/test_31_oauth2_introspection.py +++ b/tests/test_31_oauth2_introspection.py @@ -325,8 +325,10 @@ def test_do_response(self): "iat", "scope", "aud", + "token_type" } assert _payload["active"] is True + assert _payload["token_type"] == "bearer" def test_do_response_no_token(self): # access_token = self._get_access_token(AUTH_REQ) From afbf9c32bb2fd264ffc90cfa2074252e922a45e2 Mon Sep 17 00:00:00 2001 From: Roland Hedberg Date: Tue, 1 Jun 2021 09:07:28 +0200 Subject: [PATCH 5/6] Update grant.py Fixed a merge mistake --- src/oidcop/session/grant.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/oidcop/session/grant.py b/src/oidcop/session/grant.py index 3fed9d61..b9adb41e 100644 --- a/src/oidcop/session/grant.py +++ b/src/oidcop/session/grant.py @@ -270,15 +270,18 @@ def mint_token( class_args = kwargs handler_args = {} - if token_class: + if token_class == "access_token" and token_type: + class_args["token_type"] = token_type + + if _class: if scope is None: if based_on: scope = self.find_scope(based_on) else: scope = self.scope - item = token_class( - type=token_type, + item = _class( + token_class=token_class, based_on=_base_on_ref, usage_rules=usage_rules, scope=scope, From aea4b54ad75fb8518dc3c92e9a014eaec5094ace Mon Sep 17 00:00:00 2001 From: Roland Hedberg Date: Tue, 1 Jun 2021 09:16:12 +0200 Subject: [PATCH 6/6] Update test_01_grant.py token_type -> token_class --- tests/test_01_grant.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/test_01_grant.py b/tests/test_01_grant.py index 71c5a0f4..ddccb7bf 100644 --- a/tests/test_01_grant.py +++ b/tests/test_01_grant.py @@ -448,7 +448,7 @@ def test_assigned_scope(self): code = grant.mint_token( session_id, endpoint_context=self.endpoint_context, - token_type="authorization_code", + token_class="authorization_code", token_handler=TOKEN_HANDLER["authorization_code"], ) @@ -457,7 +457,7 @@ def test_assigned_scope(self): access_token = grant.mint_token( session_id, endpoint_context=self.endpoint_context, - token_type="access_token", + token_class="access_token", token_handler=TOKEN_HANDLER["access_token"], based_on=code, ) @@ -473,7 +473,7 @@ def test_assigned_scope_2nd(self): code = grant.mint_token( session_id, endpoint_context=self.endpoint_context, - token_type="authorization_code", + token_class="authorization_code", token_handler=TOKEN_HANDLER["authorization_code"], ) @@ -482,7 +482,7 @@ def test_assigned_scope_2nd(self): refresh_token = grant.mint_token( session_id, endpoint_context=self.endpoint_context, - token_type="refresh_token", + token_class="refresh_token", token_handler=TOKEN_HANDLER["refresh_token"], based_on=code, ) @@ -490,7 +490,7 @@ def test_assigned_scope_2nd(self): access_token = grant.mint_token( session_id, endpoint_context=self.endpoint_context, - token_type="access_token", + token_class="access_token", token_handler=TOKEN_HANDLER["access_token"], based_on=refresh_token, ) @@ -502,7 +502,7 @@ def test_assigned_scope_2nd(self): access_token = grant.mint_token( session_id, endpoint_context=self.endpoint_context, - token_type="access_token", + token_class="access_token", token_handler=TOKEN_HANDLER["access_token"], based_on=refresh_token, )