From ec31dee613ddae61c3576193a23c334cb932dc7d Mon Sep 17 00:00:00 2001 From: Roland Hedberg Date: Thu, 6 Jun 2024 13:40:23 +0200 Subject: [PATCH] Should be possible to get endpoint_url before the headers are constructed. Less common DPoP setup when issuer och receiver doesn't exist in the same entity_type guise. --- src/idpyoidc/client/oauth2/add_on/dpop.py | 9 +++++++-- src/idpyoidc/client/service.py | 12 +++++++----- src/idpyoidc/server/oauth2/add_on/dpop.py | 21 ++++++++++----------- 3 files changed, 24 insertions(+), 18 deletions(-) diff --git a/src/idpyoidc/client/oauth2/add_on/dpop.py b/src/idpyoidc/client/oauth2/add_on/dpop.py index f92574ff..b8450500 100644 --- a/src/idpyoidc/client/oauth2/add_on/dpop.py +++ b/src/idpyoidc/client/oauth2/add_on/dpop.py @@ -99,6 +99,7 @@ def dpop_header( headers: Optional[dict] = None, token: Optional[str] = "", nonce: Optional[str] = "", + endpoint_url: Optional[str] = "", **kwargs ) -> dict: """ @@ -114,7 +115,11 @@ def dpop_header( :return: """ - provider_info = service_context.provider_info + if not endpoint_url: + endpoint_url = kwargs.get("endpoint") + if not endpoint_url: + endpoint_url = service_context.provider_info[service_endpoint] + _dpop_conf = service_context.add_on.get("dpop") if not _dpop_conf: logger.warning("Asked to do dpop when I do not support it") @@ -139,7 +144,7 @@ def dpop_header( "jwk": dpop_key.serialize(), "jti": uuid.uuid4().hex, "htm": http_method, - "htu": provider_info[service_endpoint], + "htu": endpoint_url, "iat": utc_time_sans_frac(), } diff --git a/src/idpyoidc/client/service.py b/src/idpyoidc/client/service.py index f630583c..8c0730fb 100644 --- a/src/idpyoidc/client/service.py +++ b/src/idpyoidc/client/service.py @@ -451,17 +451,19 @@ def get_request_parameters( if _context.issuer: _args["iss"] = _context.issuer - # Client authentication by usage of the Authorization HTTP header - # or by modifying the request object - _args.update(self.get_headers_args()) - _headers = self.get_headers(request, http_method=method, authn_method=authn_method, **_args) - # Find out where to send this request try: endpoint_url = kwargs["endpoint"] except KeyError: endpoint_url = self.get_endpoint() + _args["endpoint_url"] = endpoint_url + + # Client authentication by usage of the Authorization HTTP header + # or by modifying the request object + _args.update(self.get_headers_args()) + _headers = self.get_headers(request, http_method=method, authn_method=authn_method, **_args) + _info["url"] = get_http_url(endpoint_url, request, method=method) # If there is to be a body part diff --git a/src/idpyoidc/server/oauth2/add_on/dpop.py b/src/idpyoidc/server/oauth2/add_on/dpop.py index 8deba5cd..a4c39a17 100644 --- a/src/idpyoidc/server/oauth2/add_on/dpop.py +++ b/src/idpyoidc/server/oauth2/add_on/dpop.py @@ -180,9 +180,10 @@ def token_args(context, client_id, token_args: Optional[dict] = None): def add_support(endpoint: dict, **kwargs): - # - _token_endp = endpoint["token"] - _token_endp.post_parse_request.append(token_post_parse_request) + # Pick one endpoint + _endp_name = list(endpoint.keys())[0] + _endp = endpoint[_endp_name] + _endp.post_parse_request.append(token_post_parse_request) _algs_supported = kwargs.get("dpop_signing_alg_values_supported") if not _algs_supported: @@ -190,17 +191,15 @@ def add_support(endpoint: dict, **kwargs): else: _algs_supported = [alg for alg in _algs_supported if alg in get_signing_algs()] - _token_endp.upstream_get("context").provider_info[ - "dpop_signing_alg_values_supported" - ] = _algs_supported - - _context = _token_endp.upstream_get("context") + _context = _endp.upstream_get("context") + _context.provider_info["dpop_signing_alg_values_supported"] = _algs_supported _context.add_on["dpop"] = {"algs_supported": _algs_supported} _context.client_authn_methods["dpop"] = DPoPClientAuth - _userinfo_endpoint = endpoint.get("userinfo") - if _userinfo_endpoint: - _userinfo_endpoint.post_parse_request.append(userinfo_post_parse_request) + for _dpop_endpoint in kwargs.get("dpop_endpoints", ["userinfo"]): + _endpoint = endpoint.get(_dpop_endpoint, None) + if _endpoint: + _endpoint.post_parse_request.append(userinfo_post_parse_request) # DPoP-bound access token in the "Authorization" header and the DPoP proof in the "DPoP" header