From 3d38ae1dd2f2bb2a4bf31ef8552e47ca6b5b3203 Mon Sep 17 00:00:00 2001 From: Nikos Sklikas Date: Wed, 31 Mar 2021 16:49:44 +0300 Subject: [PATCH 1/9] Properly handle dict --- src/oidcendpoint/authz/__init__.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/oidcendpoint/authz/__init__.py b/src/oidcendpoint/authz/__init__.py index b21b9a3..2277df8 100755 --- a/src/oidcendpoint/authz/__init__.py +++ b/src/oidcendpoint/authz/__init__.py @@ -62,7 +62,9 @@ def __call__(self, session_id: str, request: Union[dict, Message], claims = request.get("claims") if claims: - args["claims"] = claims.to_dict() + if isinstance(request, Message): + claims = claims.to_dict() + args["claims"] = claims session_info = self.endpoint_context.session_manager.get_session_info( session_id=session_id, grant=True From 1db7d7689599182a1e2d8a404347485a9cf2f68a Mon Sep 17 00:00:00 2001 From: Nikos Sklikas Date: Wed, 31 Mar 2021 16:50:27 +0300 Subject: [PATCH 2/9] Allow grant to infer token_handler The access_token handler was used to mint auth codes --- src/oidcendpoint/oauth2/authorization.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/oidcendpoint/oauth2/authorization.py b/src/oidcendpoint/oauth2/authorization.py index b80a3c2..e4d1a15 100755 --- a/src/oidcendpoint/oauth2/authorization.py +++ b/src/oidcendpoint/oauth2/authorization.py @@ -316,7 +316,6 @@ def mint_token(self, token_type, grant, session_id, based_on=None): session_id=session_id, endpoint_context=self.endpoint_context, token_type=token_type, - token_handler=_mngr.token_handler["access_token"], based_on=based_on, usage_rules=usage_rules ) From 9c4a825b60176bea91981174d515b453df29e056 Mon Sep 17 00:00:00 2001 From: Nikos Sklikas Date: Wed, 31 Mar 2021 16:51:54 +0300 Subject: [PATCH 3/9] State is optional --- src/oidcendpoint/oauth2/authorization.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/oidcendpoint/oauth2/authorization.py b/src/oidcendpoint/oauth2/authorization.py index e4d1a15..d4b006e 100755 --- a/src/oidcendpoint/oauth2/authorization.py +++ b/src/oidcendpoint/oauth2/authorization.py @@ -794,7 +794,7 @@ def post_authentication(self, request: Union[dict, Message], _cookie = new_cookie( self.endpoint_context, sid=session_id, - state=request["state"], + state=request.get("state"), cookie_name=self.endpoint_context.cookie_name["session"], ) From 15b257de4f07c47152656e5fdfa1205e23bfa804 Mon Sep 17 00:00:00 2001 From: Nikos Sklikas Date: Wed, 31 Mar 2021 16:55:24 +0300 Subject: [PATCH 4/9] Check if token and authorization exist on pkce --- src/oidcendpoint/oidc/add_on/pkce.py | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/src/oidcendpoint/oidc/add_on/pkce.py b/src/oidcendpoint/oidc/add_on/pkce.py index ffb9845..e760dd0 100644 --- a/src/oidcendpoint/oidc/add_on/pkce.py +++ b/src/oidcendpoint/oidc/add_on/pkce.py @@ -47,8 +47,11 @@ def post_authn_parse(request, client_id, endpoint_context, **kwargs): request["code_challenge_method"] = "plain" if ( - request["code_challenge_method"] - not in endpoint_context.args["pkce"]["code_challenge_methods"] + "code_challenge" in request + and ( + request["code_challenge_method"] + not in endpoint_context.args["pkce"]["code_challenge_methods"] + ) ): return AuthorizationErrorResponse( error="invalid_request", @@ -121,7 +124,22 @@ def post_token_parse(request, client_id, endpoint_context, **kwargs): def add_pkce_support(endpoint, **kwargs): - endpoint["authorization"].post_parse_request.append(post_authn_parse) + authn_endpoint = endpoint.get("authorization") + if authn_endpoint is None: + LOGGER.warning( + "No authorization endpoint found, skipping PKCE configuration" + ) + return + + token_endpoint = endpoint.get("token") + if token_endpoint is None: + LOGGER.warning( + "No token endpoint found, skipping PKCE configuration" + ) + return + + authn_endpoint.post_parse_request.append(post_authn_parse) + token_endpoint.post_parse_request.append(post_token_parse) if "essential" not in kwargs: kwargs["essential"] = False @@ -136,6 +154,4 @@ def add_pkce_support(endpoint, **kwargs): raise ValueError("Unsupported method: {}".format(method)) kwargs["code_challenge_methods"][method] = CC_METHOD[method] - endpoint["authorization"].endpoint_context.args["pkce"] = kwargs - - endpoint["token"].post_parse_request.append(post_token_parse) + authn_endpoint.endpoint_context.args["pkce"] = kwargs From 7a29c5d2ea6537ada04a2617f70701fa6fa431f7 Mon Sep 17 00:00:00 2001 From: Nikos Sklikas Date: Wed, 31 Mar 2021 16:59:07 +0300 Subject: [PATCH 5/9] Handle unknown token --- src/oidcendpoint/oidc/token.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/oidcendpoint/oidc/token.py b/src/oidcendpoint/oidc/token.py index 0e51713..6aa12ce 100755 --- a/src/oidcendpoint/oidc/token.py +++ b/src/oidcendpoint/oidc/token.py @@ -21,6 +21,7 @@ from oidcendpoint.session.grant import Grant from oidcendpoint.session.grant import RefreshToken from oidcendpoint.session.token import Token as sessionToken +from oidcendpoint.token.exception import UnknownToken from oidcendpoint.util import importer logger = logging.getLogger(__name__) @@ -180,7 +181,7 @@ def post_parse_request(self, request: Union[Message, dict], try: _session_info = _mngr.get_session_info_by_token(request["code"], grant=True) - except KeyError: + except (KeyError, UnknownToken): logger.error("Access Code invalid") return self.error_cls(error="invalid_grant", error_description="Unknown code") From 28507c7b234973c30b2e629f48a16d84cecd037b Mon Sep 17 00:00:00 2001 From: Nikos Sklikas Date: Wed, 31 Mar 2021 16:59:38 +0300 Subject: [PATCH 6/9] Don't return state in token response --- src/oidcendpoint/oidc/token.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/oidcendpoint/oidc/token.py b/src/oidcendpoint/oidc/token.py index 6aa12ce..7bd1bc6 100755 --- a/src/oidcendpoint/oidc/token.py +++ b/src/oidcendpoint/oidc/token.py @@ -129,7 +129,6 @@ def process_request(self, req: Union[Message, dict], **kwargs): _response = { "token_type": "Bearer", "scope": grant.scope, - "state": _authn_req["state"] } token = self._mint_token(token_type="access_token", From 3010dcc5df4a826ceb12eb33c8ba019ef5372719 Mon Sep 17 00:00:00 2001 From: Nikos Sklikas Date: Wed, 31 Mar 2021 17:01:20 +0300 Subject: [PATCH 7/9] Get token from grant instead of manager --- src/oidcendpoint/oidc/token.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/oidcendpoint/oidc/token.py b/src/oidcendpoint/oidc/token.py index 7bd1bc6..27f3894 100755 --- a/src/oidcendpoint/oidc/token.py +++ b/src/oidcendpoint/oidc/token.py @@ -106,7 +106,7 @@ def process_request(self, req: Union[Message, dict], **kwargs): _session_info = _mngr.get_session_info_by_token(_access_code, grant=True) grant = _session_info["grant"] - code = _mngr.find_token(_session_info["session_id"], _access_code) + code = grant.get_token(_access_code) _authn_req = grant.authorization_request # If redirect_uri was in the initial authorization request From aa2dad9b7efc7ab1063a23be3c8fe6cc1a565051 Mon Sep 17 00:00:00 2001 From: Nikos Sklikas Date: Wed, 31 Mar 2021 17:05:08 +0300 Subject: [PATCH 8/9] Keep backwards compatibility with client claims --- src/oidcendpoint/session/claims.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/oidcendpoint/session/claims.py b/src/oidcendpoint/session/claims.py index b669c02..f8daed2 100755 --- a/src/oidcendpoint/session/claims.py +++ b/src/oidcendpoint/session/claims.py @@ -42,7 +42,10 @@ def authorization_request_claims(self, session_id: str, usage: Optional[str] = " def _get_client_claims(self, client_id, usage): client_info = self.endpoint_context.cdb.get(client_id, {}) - return client_info.get("{}_claims".format(usage), {}) + client_claims = client_info.get("{}_claims".format(usage), {}) + if isinstance(client_claims, list): + client_claims = {k: None for k in client_claims} + return client_claims def get_claims(self, session_id: str, From 58e8a090711a716a75ab2b1988d6953422156d3b Mon Sep 17 00:00:00 2001 From: Nikos Sklikas Date: Wed, 31 Mar 2021 17:06:51 +0300 Subject: [PATCH 9/9] Filter scopes per client --- src/oidcendpoint/session/claims.py | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/oidcendpoint/session/claims.py b/src/oidcendpoint/session/claims.py index f8daed2..b389cb4 100755 --- a/src/oidcendpoint/session/claims.py +++ b/src/oidcendpoint/session/claims.py @@ -47,10 +47,7 @@ def _get_client_claims(self, client_id, usage): client_claims = {k: None for k in client_claims} return client_claims - def get_claims(self, - session_id: str, - usage: str, - scopes: Optional[str] = None) -> dict: + def get_claims(self, session_id: str, scopes: str, usage: str) -> dict: """ :param session_id: Session identifier @@ -94,14 +91,13 @@ def get_claims(self, # Scopes can in some cases equate to set of claims, is that used here ? if module and module.kwargs.get("add_claims_by_scope"): if scopes: - _supported = self.endpoint_context.provider_info.get("scopes_supported", []) - if _supported: - _scopes = set(_supported).intersection(set(scopes)) - else: - _scopes = scopes - - _claims = convert_scopes2claims(_scopes, - map=self.endpoint_context.scope2claims) + _scopes = self.endpoint_context.scopes_handler.filter_scopes( + client_id, self.endpoint_context, scopes + ) + + _claims = convert_scopes2claims( + _scopes, map=self.endpoint_context.scope2claims + ) claims.update(_claims) # Bring in claims specification from the authorization request