diff --git a/README.SATOSA.md b/README.SATOSA.md index 393b158a..3e5f8674 100644 --- a/README.SATOSA.md +++ b/README.SATOSA.md @@ -77,7 +77,7 @@ To install the OpenID4VP SATOSA backend you just need to: | Parameter | Description | Example value | | -------------------------------------- | ------------------------------------------------------------------------------ | --------------------------------------------- | -| config.authorization.url_scheme | The URL scheme for the authorization | eudiw | +| config.authorization.url_scheme | Either a custom URL scheme for the authorization, or a universal link | haip, https://wallet.example | | config.authorization.scopes | The list of scopes for the authorization | [pid-sd-jwt:unique_id+given_name+family_name] | | config.authorization.default_acr_value | The default authentication context class reference value for the authorization | https://www.spid.gov.it/SpidL2 | diff --git a/example/satosa/integration_test/same_device_integration_test.py b/example/satosa/integration_test/same_device_integration_test.py index d52cd447..79aa9946 100644 --- a/example/satosa/integration_test/same_device_integration_test.py +++ b/example/satosa/integration_test/same_device_integration_test.py @@ -21,8 +21,9 @@ db_engine_inst = setup_test_db_engine() db_engine_inst = apply_trust_settings(db_engine_inst) -def _extract_request_uri(e: requests.exceptions.InvalidSchema) -> str: - request_uri = re.search(r'request_uri=(.*?)(?:\'|$)', urllib.parse.unquote_plus(e.args[0])).group(1) +def _extract_request_uri(e: Exception) -> str: + request_uri: str = re.search(r'request_uri=(.*?)(?:\'|\s|$)', urllib.parse.unquote_plus(e.args[0])).group(1) + request_uri = request_uri.rstrip() return request_uri @@ -43,7 +44,11 @@ def _extract_request_uri(e: requests.exceptions.InvalidSchema) -> str: timeout=TIMEOUT_S ) except requests.exceptions.InvalidSchema as e: + # custom url scheme such as 'haip' or 'eudiw' will raise this exception request_uri = _extract_request_uri(e) +except requests.exceptions.ConnectionError as e: + # universal link such as 'https://wallet.example' will raise this exception + request_uri = _extract_request_uri(e.args[0]) sign_request_obj = http_user_agent.get( request_uri, diff --git a/pyeudiw/satosa/default/openid4vp_backend.py b/pyeudiw/satosa/default/openid4vp_backend.py index 4db4edbd..e55c6b1c 100644 --- a/pyeudiw/satosa/default/openid4vp_backend.py +++ b/pyeudiw/satosa/default/openid4vp_backend.py @@ -205,20 +205,18 @@ def pre_request_endpoint(self, context: Context, internal_request, **kwargs) -> 'client_id': self.client_id, 'request_uri': f"{self.absolute_request_url}?id={state}", } - url_params = urlencode(payload, quote_via=quote_plus) + + response_url = self._build_authz_request_url(payload) if is_smartphone(context.http_headers.get('HTTP_USER_AGENT')): # Same Device flow - res_url = f'{self.config["authorization"]["url_scheme"]}://authorize?{url_params}' - return Redirect(res_url) + return Redirect(response_url) # Cross Device flow - res_url = f'{self.client_id}?{url_params}' - result = self.template.qrcode_page.render( { "qrcode_color": self.config["qrcode"]["color"], - "qrcode_text": res_url, + "qrcode_text": response_url, "qrcode_size": self.config["qrcode"]["size"], "qrcode_logo_path": self.config["qrcode"]["logo_path"], "qrcode_expiration_time": self.config["qrcode"]["expiration_time"], @@ -342,6 +340,19 @@ def db_engine(self) -> DBEngine: return self._db_engine + def _build_authz_request_url(self, payload: dict) -> str: + scheme = self.config["authorization"]["url_scheme"] + if "://" not in scheme: + scheme = scheme + "://" + if not scheme.endswith("/"): + scheme = scheme + "/" + # NOTE: path component is currently unused by the protocol, but currently + # we leave it there as 'authorize' to stress the fact that this is an + # OAuth 2.0 request modified by JAR (RFC9101) + path = "authorize" + query_params = urlencode(payload, quote_via=quote_plus) + return f"{scheme}{path}?{query_params}" + @property def default_metadata_private_jwk(self) -> tuple: """Returns the default metadata private JWK"""