diff --git a/src/Config/Server.php b/src/Config/Server.php index 05e9a00..e265702 100644 --- a/src/Config/Server.php +++ b/src/Config/Server.php @@ -41,6 +41,7 @@ final public function getRequired() : array OidcMeta::JWKS_URI, OidcMeta::RESPONSE_TYPES_SUPPORTED, OidcMeta::SUBJECT_TYPES_SUPPORTED, + OidcMeta::AUTHORIZATION_RESPONSE_ISS_PARAMETER_SUPPORTED // required as per https://solid.github.io/solid-oidc/#iss-check ]; if ($this->strict === true) { @@ -57,23 +58,24 @@ final public function __construct(array $data, bool $strict = false) $data = array_merge([ OidcMeta::ID_TOKEN_SIGNING_ALG_VALUES_SUPPORTED => ['RS256'], OidcMeta::SUBJECT_TYPES_SUPPORTED => ['public'], - OidcMeta::RESPONSE_TYPES_SUPPORTED => array("code","code token","code id_token","id_token code","id_token","id_token token","code id_token token","none"), - OidcMeta::TOKEN_TYPES_SUPPORTED => array("legacyPop","dpop"), - OidcMeta::RESPONSE_MODES_SUPPORTED => array("query","fragment"), - OidcMeta::GRANT_TYPES_SUPPORTED => array("authorization_code","implicit","refresh_token","client_credentials"), - OidcMeta::TOKEN_ENDPOINT_AUTH_METHODS_SUPPORTED => ["client_secret_basic"], - OidcMeta::TOKEN_ENDPOINT_AUTH_SIGNING_ALG_VALUES_SUPPORTED => ["RS256"], - OidcMeta::CODE_CHALLENGE_METHODS_SUPPORTED => ["S256"], - OidcMeta::DPOP_SIGNING_ALG_VALUES_SUPPORTED => ["RS256"], - OidcMeta::DISPLAY_VALUES_SUPPORTED => [], - OidcMeta::CLAIM_TYPES_SUPPORTED => ["normal"], - OidcMeta::CLAIMS_SUPPORTED => ["webid"], - OidcMeta::SCOPES_SUPPORTED => ["webid"], - OidcMeta::CLAIMS_PARAMETER_SUPPORTED => false, - OidcMeta::REQUEST_PARAMETER_SUPPORTED => true, - OidcMeta::REQUEST_URI_PARAMETER_SUPPORTED => false, - OidcMeta::REQUIRE_REQUEST_URI_REGISTRATION => false - ], $data); + OidcMeta::RESPONSE_TYPES_SUPPORTED => array("code","code token","code id_token","id_token code","id_token","id_token token","code id_token token","none"), + OidcMeta::TOKEN_TYPES_SUPPORTED => array("legacyPop","dpop"), + OidcMeta::RESPONSE_MODES_SUPPORTED => array("query","fragment"), + OidcMeta::GRANT_TYPES_SUPPORTED => array("authorization_code","implicit","refresh_token","client_credentials"), + OidcMeta::TOKEN_ENDPOINT_AUTH_METHODS_SUPPORTED => ["client_secret_basic"], + OidcMeta::TOKEN_ENDPOINT_AUTH_SIGNING_ALG_VALUES_SUPPORTED => ["RS256"], + OidcMeta::CODE_CHALLENGE_METHODS_SUPPORTED => ["S256"], + OidcMeta::DPOP_SIGNING_ALG_VALUES_SUPPORTED => ["RS256"], + OidcMeta::DISPLAY_VALUES_SUPPORTED => [], + OidcMeta::CLAIM_TYPES_SUPPORTED => ["normal"], + OidcMeta::CLAIMS_SUPPORTED => ["webid"], + OidcMeta::SCOPES_SUPPORTED => ["webid"], + OidcMeta::CLAIMS_PARAMETER_SUPPORTED => false, + OidcMeta::REQUEST_PARAMETER_SUPPORTED => true, + OidcMeta::REQUEST_URI_PARAMETER_SUPPORTED => false, + OidcMeta::REQUIRE_REQUEST_URI_REGISTRATION => false, + OidcMeta::AUTHORIZATION_RESPONSE_ISS_PARAMETER_SUPPORTED => true + ], $data); $this->data = array_filter($data, [OidcMeta::class, 'has'], ARRAY_FILTER_USE_KEY); $this->strict = $strict; diff --git a/src/Enum/OpenId/OpenIdConnectMetadata.php b/src/Enum/OpenId/OpenIdConnectMetadata.php index a8c025f..91bc4b3 100644 --- a/src/Enum/OpenId/OpenIdConnectMetadata.php +++ b/src/Enum/OpenId/OpenIdConnectMetadata.php @@ -223,4 +223,5 @@ class OpenIdConnectMetadata extends AbstractEnum public const TOKEN_TYPES_SUPPORTED = 'token_types_supported'; public const CHECK_SESSION_IFRAME = 'check_session_iframe'; public const END_SESSION_ENDPOINT = 'end_session_endpoint'; + public const AUTHORIZATION_RESPONSE_ISS_PARAMETER_SUPPORTED = 'authorization_response_iss_parameter_supported'; // as per [RFC9207] } diff --git a/src/Server.php b/src/Server.php index 6e098d1..2de4331 100644 --- a/src/Server.php +++ b/src/Server.php @@ -40,10 +40,12 @@ final public function respondToAccessTokenRequest(Request $request) : Response $response = $this->response; try { - return $authorizationServer->respondToAccessTokenRequest($request, $response); + $response = $authorizationServer->respondToAccessTokenRequest($request, $response); } catch (OAuthServerException $serverException) { - return $this->createOauthServerExceptionResponse($response, $serverException); + $response = $this->createOauthServerExceptionResponse($response, $serverException); } + $response = $this->addIssuerToResponse($response); + return $response; } /** @@ -71,7 +73,9 @@ final public function respondToAuthorizationRequest( // Validate the HTTP request and return an AuthorizationRequest object. $authRequest = $authorizationServer->validateAuthorizationRequest($request); } catch (OAuthServerException $serverException) { - return $this->createOauthServerExceptionResponse($response, $serverException); + $response = $this->createOauthServerExceptionResponse($response, $serverException); + $response = $this->addIssuerToResponse($response); + return $response; } if ($user instanceof UserEntityInterface) { @@ -95,6 +99,7 @@ final public function respondToAuthorizationRequest( // Return the HTTP redirect response $response = $authorizationServer->completeAuthorizationRequest($authRequest, $response); + $this->addIssuerToResponse($response); // add &iss=... to the response to comply with RFC 9207 } else { // @CHECKME: 404 or throw Exception? $response = $response->withStatus(404); @@ -109,6 +114,25 @@ final public function respondToAuthorizationRequest( return $response; } + public function addIssuerToResponse($response): Response + { + // Adds &iss=... to the response to comply with RFC 9207 + $location = $response->getHeaderLine('Location'); + $uri = new Uri($location); + + parse_str($uri->getQuery(), $params); + $params['iss'] = $this->config->getServer()->get(OidcMeta::ISSUER); + + $uri = $uri->withQuery(http_build_query($params)); + + $response = $response->withHeader( + 'Location', + (string) $uri + ); + + return $response; + } + final public function respondToJwksMetadataRequest(/*Jwks $jwks*/) : Response { $response = $this->response; diff --git a/tests/unit/Config/ServerTest.php b/tests/unit/Config/ServerTest.php index bffa784..7dcd5d7 100644 --- a/tests/unit/Config/ServerTest.php +++ b/tests/unit/Config/ServerTest.php @@ -41,6 +41,7 @@ final public function testServerConfigShouldProvideRequiredPropertiesWhenAskedFo OidcMeta::JWKS_URI, OidcMeta::RESPONSE_TYPES_SUPPORTED, OidcMeta::SUBJECT_TYPES_SUPPORTED, + OidcMeta::AUTHORIZATION_RESPONSE_ISS_PARAMETER_SUPPORTED, ]; self::assertEquals($expected, $actual); @@ -119,7 +120,8 @@ final public function testServerConfigShouldReturnExpectedValuesWhenSerializedWi 'require_request_uri_registration' => false, 'code_challenge_methods_supported' => ['S256'], 'dpop_signing_alg_values_supported' => ['RS256'], - 'scopes_supported' => ['webid'] + 'scopes_supported' => ['webid'], + 'authorization_response_iss_parameter_supported' => true, ], $actual); } } diff --git a/tests/unit/Enum/OpenId/OpenIdConnectMetadataTest.php b/tests/unit/Enum/OpenId/OpenIdConnectMetadataTest.php index 1af63fe..26236bd 100644 --- a/tests/unit/Enum/OpenId/OpenIdConnectMetadataTest.php +++ b/tests/unit/Enum/OpenId/OpenIdConnectMetadataTest.php @@ -56,7 +56,8 @@ final public function getExpectedValues() : array 'userinfo_signing_alg_values_supported', 'token_types_supported', 'check_session_iframe', - 'end_session_endpoint' + 'end_session_endpoint', + 'authorization_response_iss_parameter_supported' ]; }