diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml
index 79156c9e..faf787a3 100644
--- a/.github/workflows/test.yaml
+++ b/.github/workflows/test.yaml
@@ -259,6 +259,12 @@ jobs:
- name: Run RP backchannel
run: |
./conformance-suite/scripts/run-test-plan.py "oidcc-backchannel-rp-initiated-logout-certification-test-plan[response_type=code][client_registration=static_client]" ./main/conformance-tests/conformance-back-channel-logout-ci.json
+ - name: Run form_post basic tests
+ run: |
+ ./conformance-suite/scripts/run-test-plan.py "oidcc-formpost-basic-certification-test-plan[server_metadata=discovery][client_registration=static_client]" ./main/conformance-tests/conformance-basic-ci.json
+ - name: Run form_post implicit tests
+ run: |
+ ./conformance-suite/scripts/run-test-plan.py "oidcc-formpost-implicit-certification-test-plan[server_metadata=discovery][client_registration=static_client]" ./main/conformance-tests/conformance-implicit-ci.json
- name: Stop SSP
working-directory: ./main
run: |
diff --git a/public/assets/js/src/formpost.js b/public/assets/js/src/formpost.js
new file mode 100644
index 00000000..88950b52
--- /dev/null
+++ b/public/assets/js/src/formpost.js
@@ -0,0 +1 @@
+document.forms[0].submit();
\ No newline at end of file
diff --git a/routing/services/services.yml b/routing/services/services.yml
index 5b8f7c6c..ffcad634 100644
--- a/routing/services/services.yml
+++ b/routing/services/services.yml
@@ -67,6 +67,12 @@ services:
SimpleSAML\Module\oidc\Server\ResponseTypes\TokenResponse:
factory: ['@SimpleSAML\Module\oidc\Factories\TokenResponseFactory', 'build']
+ SimpleSAML\Module\oidc\Server\ResponseModes\:
+ resource: '../../src/Server/ResponseModes/*'
+
+ SimpleSAML\Configuration:
+ factory: ['SimpleSAML\Configuration', 'getInstance']
+
oidc.key.private:
class: League\OAuth2\Server\CryptKey
factory: ['@SimpleSAML\Module\oidc\Factories\CryptKeyFactory', 'buildPrivateKey']
diff --git a/src/Controllers/Admin/ClientController.php b/src/Controllers/Admin/ClientController.php
index 7f7ff7ef..db1db0f4 100644
--- a/src/Controllers/Admin/ClientController.php
+++ b/src/Controllers/Admin/ClientController.php
@@ -239,6 +239,7 @@ public function edit(Request $request): Response
$clientData = $originalClient->toArray();
$clientData['allowed_origin'] = $clientAllowedOrigins;
+ $clientData['response_modes_allowed'] = $originalClient->getAllowedResponseModes();
// Handle extra metadata
@@ -358,6 +359,9 @@ protected function buildClientEntityFromFormData(
ClaimsEnum::IdTokenSignedResponseAlg->value => $idTokenSignedResponseAlg,
];
+ $allowedResponseModes = is_array($data['response_modes_allowed']) ? $data['response_modes_allowed'] : [];
+ $extraMetadata['allowed_response_modes'] = $allowedResponseModes;
+
return $this->clientEntityFactory->fromData(
$identifier,
$secret,
diff --git a/src/Entities/ClientEntity.php b/src/Entities/ClientEntity.php
index a0ffb92b..aae1958a 100644
--- a/src/Entities/ClientEntity.php
+++ b/src/Entities/ClientEntity.php
@@ -388,4 +388,21 @@ public function getIdTokenSignedResponseAlg(): ?string
return $idTokenSignedResponseAlg;
}
+
+ public function getAllowedResponseModes(): array
+ {
+ if (!is_array($this->extraMetadata)) {
+ // Default to allowing all response modes
+ return ['query', 'fragment', 'form_post'];
+ }
+
+ $allowedResponseModes = $this->extraMetadata['allowed_response_modes'] ?? null;
+
+ if (!is_array($allowedResponseModes)) {
+ // Default to allowing all response modes
+ return ['query', 'fragment', 'form_post'];
+ }
+
+ return $allowedResponseModes;
+ }
}
diff --git a/src/Entities/Interfaces/ClientEntityInterface.php b/src/Entities/Interfaces/ClientEntityInterface.php
index dea9ff66..47bc6f15 100644
--- a/src/Entities/Interfaces/ClientEntityInterface.php
+++ b/src/Entities/Interfaces/ClientEntityInterface.php
@@ -82,4 +82,5 @@ public function isGeneric(): bool;
public function getExtraMetadata(): array;
public function getIdTokenSignedResponseAlg(): ?string;
+ public function getAllowedResponseModes(): array;
}
diff --git a/src/Factories/Grant/ImplicitGrantFactory.php b/src/Factories/Grant/ImplicitGrantFactory.php
index a22791d8..47d5ec6b 100644
--- a/src/Factories/Grant/ImplicitGrantFactory.php
+++ b/src/Factories/Grant/ImplicitGrantFactory.php
@@ -43,7 +43,6 @@ public function build(): ImplicitGrant
$this->accessTokenRepository,
$this->requestRulesManager,
$this->requestParamsResolver,
- '#',
$this->accessTokenEntityFactory,
);
}
diff --git a/src/Factories/RequestRulesManagerFactory.php b/src/Factories/RequestRulesManagerFactory.php
index 9b77e7c0..85fbf083 100644
--- a/src/Factories/RequestRulesManagerFactory.php
+++ b/src/Factories/RequestRulesManagerFactory.php
@@ -31,11 +31,15 @@
use SimpleSAML\Module\oidc\Server\RequestRules\Rules\RequestObjectRule;
use SimpleSAML\Module\oidc\Server\RequestRules\Rules\RequiredNonceRule;
use SimpleSAML\Module\oidc\Server\RequestRules\Rules\RequiredOpenIdScopeRule;
+use SimpleSAML\Module\oidc\Server\RequestRules\Rules\ResponseModeRule;
use SimpleSAML\Module\oidc\Server\RequestRules\Rules\ResponseTypeRule;
use SimpleSAML\Module\oidc\Server\RequestRules\Rules\ScopeOfflineAccessRule;
use SimpleSAML\Module\oidc\Server\RequestRules\Rules\ScopeRule;
use SimpleSAML\Module\oidc\Server\RequestRules\Rules\StateRule;
use SimpleSAML\Module\oidc\Server\RequestRules\Rules\UiLocalesRule;
+use SimpleSAML\Module\oidc\Server\ResponseModes\FormPostResponseMode;
+use SimpleSAML\Module\oidc\Server\ResponseModes\FragmentResponseMode;
+use SimpleSAML\Module\oidc\Server\ResponseModes\QueryResponseMode;
use SimpleSAML\Module\oidc\Services\AuthenticationService;
use SimpleSAML\Module\oidc\Services\LoggerService;
use SimpleSAML\Module\oidc\Utils\AuthenticatedOAuth2ClientResolver;
@@ -72,6 +76,9 @@ public function __construct(
private readonly AuthenticatedOAuth2ClientResolver $authenticatedOAuth2ClientResolver,
private readonly ?FederationCache $federationCache = null,
private readonly ?ProtocolCache $protocolCache = null,
+ private readonly QueryResponseMode $queryResponseMode,
+ private readonly FragmentResponseMode $fragmentResponseMode,
+ private readonly FormPostResponseMode $formPostResponseMode,
) {
}
@@ -107,6 +114,13 @@ private function getDefaultRules(): array
),
new ClientRedirectUriRule($this->requestParamsResolver, $this->helpers, $this->moduleConfig),
new RequestObjectRule($this->requestParamsResolver, $this->helpers, $this->jwksResolver),
+ new ResponseModeRule(
+ $this->requestParamsResolver,
+ $this->helpers,
+ $this->queryResponseMode,
+ $this->fragmentResponseMode,
+ $this->formPostResponseMode,
+ ),
new PromptRule(
$this->requestParamsResolver,
$this->helpers,
diff --git a/src/Forms/ClientForm.php b/src/Forms/ClientForm.php
index 694a206e..a912c885 100644
--- a/src/Forms/ClientForm.php
+++ b/src/Forms/ClientForm.php
@@ -284,6 +284,12 @@ public function getValues(string|object|bool|null $returnType = null, ?array $co
$values[ClaimsEnum::IdTokenSignedResponseAlg->value] = empty($idTokenSignedResponseAlg) ?
null : $idTokenSignedResponseAlg;
+ $responseModesAllowed = is_array($values['response_modes_allowed']) ? $values['response_modes_allowed'] : [];
+ $values['response_modes_allowed'] = array_intersect(
+ $responseModesAllowed,
+ array_keys($this->getAllowedResponseModesValues()),
+ );
+
return $values;
}
@@ -336,6 +342,9 @@ public function setDefaults(object|array $data, bool $erase = false): static
$data['auth_source'] = null;
}
+ $data['response_modes_allowed'] = is_array($data['response_modes_allowed']) ?
+ $data['response_modes_allowed'] : [];
+
parent::setDefaults($data, $erase);
return $this;
@@ -354,6 +363,7 @@ protected function buildForm(): void
$this->onValidate[] = $this->validateBackChannelLogoutUri(...);
$this->onValidate[] = $this->validateEntityIdentifier(...);
$this->onValidate[] = $this->validateClientRegistrationTypes(...);
+ $this->onValidate[] = $this->validateResponseModes(...);
$this->onValidate[] = $this->validateFederationJwks(...);
$this->onValidate[] = $this->validateProtocolJwks(...);
$this->onValidate[] = $this->validateJwksUri(...);
@@ -423,6 +433,46 @@ protected function buildForm(): void
->setHtmlAttribute('class', 'full-width')
->setItems(['RS256'], false)
->setPrompt(Translate::noop('-'));
+
+ $this->addMultiSelect(
+ 'response_modes_allowed',
+ Translate::noop('Allowed Response Modes'),
+ $this->getAllowedResponseModesValues(),
+ 3,
+ )->setHtmlAttribute('class', 'full-width')
+ ->setRequired(Translate::noop('At least one response mode is required.'));
+ }
+
+ /**
+ * Validate provided response modes
+ *
+ * @throws \Exception
+ */
+ public function validateResponseModes(Form $form): void
+ {
+ $values = $form->getValues(self::TYPE_ARRAY);
+ /** @var string[]|null $responseModes */
+ $responseModes = $values['response_modes_allowed'] ?? null;
+ if (is_array($responseModes)) {
+ $allowed = array_keys($this->getAllowedResponseModesValues());
+ foreach ($responseModes as $mode) {
+ if (!in_array($mode, $allowed, true)) {
+ $this->addError("Invalid value: $mode");
+ }
+ }
+ }
+ }
+
+ /**
+ * @return string[] map of value => label
+ */
+ protected function getAllowedResponseModesValues(): array
+ {
+ return [
+ 'query' => 'query',
+ 'fragment' => 'fragment',
+ 'form_post' => 'form_post',
+ ];
}
/**
diff --git a/src/Server/AuthorizationServer.php b/src/Server/AuthorizationServer.php
index f0cc0585..56e1d7c4 100644
--- a/src/Server/AuthorizationServer.php
+++ b/src/Server/AuthorizationServer.php
@@ -22,9 +22,11 @@
use SimpleSAML\Module\oidc\Server\RequestRules\Rules\ClientRule;
use SimpleSAML\Module\oidc\Server\RequestRules\Rules\IdTokenHintRule;
use SimpleSAML\Module\oidc\Server\RequestRules\Rules\PostLogoutRedirectUriRule;
+use SimpleSAML\Module\oidc\Server\RequestRules\Rules\ResponseModeRule;
use SimpleSAML\Module\oidc\Server\RequestRules\Rules\StateRule;
use SimpleSAML\Module\oidc\Server\RequestRules\Rules\UiLocalesRule;
use SimpleSAML\Module\oidc\Server\RequestTypes\LogoutRequest;
+use SimpleSAML\Module\oidc\Server\ResponseModes\QueryResponseMode;
use SimpleSAML\Module\oidc\Services\LoggerService;
use SimpleSAML\OpenID\Codebooks\HttpMethodsEnum;
@@ -85,13 +87,14 @@ public function validateAuthorizationRequest(ServerRequestInterface $request): O
StateRule::class,
ClientRule::class,
ClientRedirectUriRule::class,
+ ResponseModeRule::class,
];
try {
$resultBag = $this->requestRulesManager->check(
$request,
$rulesToExecute,
- false,
+ new QueryResponseMode(),
[HttpMethodsEnum::GET, HttpMethodsEnum::POST],
);
} catch (OidcServerException $exception) {
@@ -114,6 +117,8 @@ public function validateAuthorizationRequest(ServerRequestInterface $request): O
$state = $resultBag->getOrFail(StateRule::class)->getValue();
/** @var string $redirectUri */
$redirectUri = $resultBag->getOrFail(ClientRedirectUriRule::class)->getValue();
+ /** @var \SimpleSAML\Module\oidc\Server\ResponseModes\ResponseModeInterface $responseMode */
+ $responseMode = $resultBag->getOrFail(ResponseModeRule::class)->getValue();
foreach ($this->enabledGrantTypes as $grantType) {
$this->loggerService?->debug(
@@ -157,7 +162,7 @@ public function validateAuthorizationRequest(ServerRequestInterface $request): O
'request.',
['requestQueryParams' => $request->getQueryParams()],
);
- throw OidcServerException::unsupportedResponseType($redirectUri, $state);
+ throw OidcServerException::unsupportedResponseType($redirectUri, $state, $responseMode);
}
/**
@@ -177,7 +182,7 @@ public function validateLogoutRequest(ServerRequestInterface $request): LogoutRe
$resultBag = $this->requestRulesManager->check(
$request,
$rulesToExecute,
- false,
+ new QueryResponseMode(),
[HttpMethodsEnum::GET, HttpMethodsEnum::POST],
);
} catch (OidcServerException $exception) {
diff --git a/src/Server/Exceptions/OidcServerException.php b/src/Server/Exceptions/OidcServerException.php
index 5a9be60d..96edca56 100644
--- a/src/Server/Exceptions/OidcServerException.php
+++ b/src/Server/Exceptions/OidcServerException.php
@@ -6,10 +6,12 @@
use League\OAuth2\Server\Exception\OAuthServerException;
use Psr\Http\Message\ResponseInterface;
+use SimpleSAML\Module\oidc\Server\ResponseModes\FragmentResponseMode;
+use SimpleSAML\Module\oidc\Server\ResponseModes\QueryResponseMode;
+use SimpleSAML\Module\oidc\Server\ResponseModes\ResponseModeInterface;
use SimpleSAML\OpenID\Codebooks\ErrorsEnum;
use Throwable;
-use function http_build_query;
use function json_encode;
class OidcServerException extends OAuthServerException
@@ -37,9 +39,9 @@ class OidcServerException extends OAuthServerException
protected ?string $redirectUri;
/**
- * @var bool
+ * @var null|ResponseModeInterface
*/
- protected bool $useFragmentInHttpResponses = false;
+ protected ?ResponseModeInterface $responseMode = null;
/**
* Throw a new exception.
@@ -62,12 +64,14 @@ public function __construct(
?string $redirectUri = null,
?Throwable $previous = null,
?string $state = null,
+ ?ResponseModeInterface $responseMode = new QueryResponseMode(),
) {
parent::__construct($message, $code, $errorType, $httpStatusCode, $hint, $redirectUri, $previous);
$this->httpStatusCode = $httpStatusCode;
$this->errorType = $errorType;
$this->redirectUri = $redirectUri;
+ $this->responseMode = $responseMode;
if ($hint !== null) {
$message .= ' (' . $hint . ')';
@@ -90,19 +94,19 @@ public function __construct(
*
* @param string|null $redirectUri
* @param string|null $state
- * @param bool $useFragment Use URI fragment to return error parameters
- * @return self
+ * @param \SimpleSAML\Module\oidc\Server\ResponseModes\ResponseModeInterface|null $responseMode
+ * @return OidcServerException
*/
public static function unsupportedResponseType(
?string $redirectUri = null,
?string $state = null,
- bool $useFragment = false,
+ ?ResponseModeInterface $responseMode = null,
): OidcServerException {
$errorMessage = 'The response type is not supported by the authorization server.';
$hint = 'Check that all required parameters have been provided';
$e = new self($errorMessage, 2, 'unsupported_response_type', 400, $hint, $redirectUri, null, $state);
- $e->useFragmentInHttpResponses($useFragment);
+ $e->responseMode = $responseMode;
return $e;
}
@@ -112,19 +116,36 @@ public static function unsupportedResponseType(
* @param string $scope The bad scope
* @param string|null $redirectUri An HTTP URI to redirect the user back to
* @param string|null $state
- * @param bool $useFragment Use URI fragment to return error parameters
- * @return static
+ * @param \SimpleSAML\Module\oidc\Server\ResponseModes\ResponseModeInterface|null $responseMode
+ * @return OidcServerException
+ * @psalm-suppress LessSpecificImplementedReturnType
*/
public static function invalidScope(
$scope,
$redirectUri = null,
?string $state = null,
- bool $useFragment = false,
+ ?ResponseModeInterface $responseMode = null,
): OidcServerException {
- // OAuthServerException correctly implements this error, however, it misses state parameter.
- $e = parent::invalidScope($scope, $redirectUri);
- $e->setState($state);
- $e->useFragmentInHttpResponses($useFragment);
+ if (empty($scope)) {
+ $hint = 'Specify a scope in the request or set a default scope';
+ } else {
+ $hint = sprintf(
+ 'Check the `%s` scope',
+ htmlspecialchars($scope, ENT_QUOTES, 'UTF-8', false),
+ );
+ }
+
+ $e = new self(
+ 'The requested scope is invalid, unknown, or malformed',
+ 5,
+ 'invalid_scope',
+ 400,
+ $hint,
+ $redirectUri,
+ null,
+ $state,
+ $responseMode,
+ );
return $e;
}
@@ -137,8 +158,9 @@ public static function invalidScope(
* @param \Throwable|null $previous
* @param string|null $redirectUri
* @param string|null $state
- * @param bool $useFragment Use URI fragment to return error parameters
- * @return static
+ * @param \SimpleSAML\Module\oidc\Server\ResponseModes\ResponseModeInterface|null $responseMode
+ * @return OidcServerException
+ * @psalm-suppress LessSpecificImplementedReturnType
*/
public static function invalidRequest(
$parameter,
@@ -146,13 +168,12 @@ public static function invalidRequest(
?Throwable $previous = null,
?string $redirectUri = null,
?string $state = null,
- bool $useFragment = false,
+ ?ResponseModeInterface $responseMode = null,
): OidcServerException {
- $e = parent::invalidRequest($parameter, $hint, $previous);
- // OAuthServerException misses the ability to set redirectUri for invalid requests, as well as state.
- $e->setRedirectUri($redirectUri);
- $e->setState($state);
- $e->useFragmentInHttpResponses($useFragment);
+ $errorMessage = 'The request is missing a required parameter, includes an invalid parameter value, ' .
+ 'includes a parameter more than once, or is otherwise malformed.';
+ $hint = ($hint === null) ? \sprintf('Check the `%s` parameter', $parameter) : $hint;
+ $e = new self($errorMessage, 9, 'invalid_request', 400, $hint, $redirectUri, $previous, $state, $responseMode);
return $e;
}
@@ -162,19 +183,28 @@ public static function invalidRequest(
* @param string|null $redirectUri
* @param \Throwable|null $previous
* @param string|null $state
- * @param bool $useFragment Use URI fragment to return error parameters
- * @return static
+ * @param \SimpleSAML\Module\oidc\Server\ResponseModes\ResponseModeInterface|null $responseMode
+ * @return OidcServerException
+ * @psalm-suppress LessSpecificImplementedReturnType
*/
public static function accessDenied(
$hint = null,
$redirectUri = null,
?Throwable $previous = null,
?string $state = null,
- bool $useFragment = false,
+ ?ResponseModeInterface $responseMode = null,
): OidcServerException {
- $e = parent::accessDenied($hint, $redirectUri, $previous);
- $e->setState($state);
- $e->useFragmentInHttpResponses($useFragment);
+ $e = new self(
+ 'The resource owner or authorization server denied the request.',
+ 9,
+ 'access_denied',
+ 401,
+ $hint,
+ $redirectUri,
+ $previous,
+ $state,
+ $responseMode,
+ );
return $e;
}
@@ -186,21 +216,20 @@ public static function accessDenied(
* @param string|null $redirectUri
* @param \Throwable|null $previous
* @param string|null $state
- * @param bool $useFragment Use URI fragment to return error parameters
+ * @param \SimpleSAML\Module\oidc\Server\ResponseModes\ResponseModeInterface|null $responseMode
*
- * @return self
+ * @return OidcServerException
*/
public static function loginRequired(
?string $hint = null,
?string $redirectUri = null,
?Throwable $previous = null,
?string $state = null,
- bool $useFragment = false,
+ ?ResponseModeInterface $responseMode = null,
): OidcServerException {
$errorMessage = "End-User is not already authenticated.";
- $e = new self($errorMessage, 6, 'login_required', 400, $hint, $redirectUri, $previous, $state);
- $e->useFragmentInHttpResponses($useFragment);
+ $e = new self($errorMessage, 6, 'login_required', 400, $hint, $redirectUri, $previous, $state, $responseMode);
return $e;
}
@@ -212,21 +241,30 @@ public static function loginRequired(
* @param string|null $redirectUri
* @param \Throwable|null $previous
* @param string|null $state
- * @param bool $useFragment Use URI fragment to return error parameters
+ * @param \SimpleSAML\Module\oidc\Server\ResponseModes\ResponseModeInterface|null $responseMode
*
- * @return self
+ * @return OidcServerException
*/
public static function requestNotSupported(
?string $hint = null,
?string $redirectUri = null,
?Throwable $previous = null,
?string $state = null,
- bool $useFragment = false,
+ ?ResponseModeInterface $responseMode = null,
): OidcServerException {
$errorMessage = "Request object not supported.";
- $e = new self($errorMessage, 7, 'request_not_supported', 400, $hint, $redirectUri, $previous, $state);
- $e->useFragmentInHttpResponses($useFragment);
+ $e = new self(
+ $errorMessage,
+ 7,
+ 'request_not_supported',
+ 400,
+ $hint,
+ $redirectUri,
+ $previous,
+ $state,
+ $responseMode,
+ );
return $e;
}
@@ -237,7 +275,7 @@ public static function requestNotSupported(
* @param string|null $hint
* @param \Throwable|null $previous
*
- * @return self
+ * @return OidcServerException
* @psalm-suppress LessSpecificImplementedReturnType
*/
public static function invalidRefreshToken($hint = null, ?Throwable $previous = null): OidcServerException
@@ -250,7 +288,7 @@ public static function invalidTrustChain(
?string $redirectUri = null,
?Throwable $previous = null,
?string $state = null,
- bool $useFragment = false,
+ ?ResponseModeInterface $responseMode = null,
): OidcServerException {
$errorMessage = 'Trust chain validation failed.';
@@ -263,8 +301,8 @@ public static function invalidTrustChain(
$redirectUri,
$previous,
$state,
+ $responseMode,
);
- $e->useFragmentInHttpResponses($useFragment);
return $e;
}
@@ -361,8 +399,7 @@ public function setState(?string $state = null): void
* Generate an HTTP response.
*
* @param \Psr\Http\Message\ResponseInterface $response
- * @param bool $useFragment True if errors should be in the URI fragment instead of query string. Note
- * that this can also be set using useFragmentInHttpResponses().
+ * @param bool $useFragment
* @param int $jsonOptions options passed to json_encode
*
* @return \Psr\Http\Message\ResponseInterface
@@ -377,16 +414,13 @@ public function generateHttpResponse(
$payload = $this->getPayload();
- if ($this->redirectUri !== null) {
- $paramSeparator = '?';
-
- if ($this->useFragmentInHttpResponses || $useFragment) {
- $paramSeparator = '#';
- }
-
- $this->redirectUri .= (!str_contains($this->redirectUri, $paramSeparator)) ? $paramSeparator : '&';
+ if ($this->responseMode === null) {
+ // Fallback to useFragment if responseMode is not set
+ $this->responseMode = $useFragment ? new FragmentResponseMode() : new QueryResponseMode();
+ }
- return $response->withStatus(302)->withHeader('Location', $this->redirectUri . http_build_query($payload));
+ if ($this->redirectUri !== null) {
+ return $this->responseMode->buildResponse($this->redirectUri, $payload)->generateHttpResponse($response);
}
foreach ($headers as $header => $content) {
@@ -399,14 +433,4 @@ public function generateHttpResponse(
return $response->withStatus($this->getHttpStatusCode());
}
-
- /**
- * Use URI fragment to return parameters in HTTP redirection error responses
- *
- * @param bool $useFragment True if fragment should be used, false otherwise
- */
- public function useFragmentInHttpResponses(bool $useFragment): void
- {
- $this->useFragmentInHttpResponses = $useFragment;
- }
}
diff --git a/src/Server/Grants/AuthCodeGrant.php b/src/Server/Grants/AuthCodeGrant.php
index dbbbce0b..d6fc76b8 100644
--- a/src/Server/Grants/AuthCodeGrant.php
+++ b/src/Server/Grants/AuthCodeGrant.php
@@ -17,7 +17,7 @@
use League\OAuth2\Server\Repositories\AuthCodeRepositoryInterface as OAuth2AuthCodeRepositoryInterface;
use League\OAuth2\Server\RequestEvent;
use League\OAuth2\Server\RequestTypes\AuthorizationRequest as OAuth2AuthorizationRequest;
-use League\OAuth2\Server\ResponseTypes\RedirectResponse;
+use League\OAuth2\Server\ResponseTypes\AbstractResponseType;
use League\OAuth2\Server\ResponseTypes\ResponseTypeInterface;
use LogicException;
use Psr\Http\Message\ServerRequestInterface;
@@ -59,10 +59,12 @@
use SimpleSAML\Module\oidc\Server\RequestRules\Rules\RequestedClaimsRule;
use SimpleSAML\Module\oidc\Server\RequestRules\Rules\RequestObjectRule;
use SimpleSAML\Module\oidc\Server\RequestRules\Rules\RequiredOpenIdScopeRule;
+use SimpleSAML\Module\oidc\Server\RequestRules\Rules\ResponseModeRule;
use SimpleSAML\Module\oidc\Server\RequestRules\Rules\ScopeOfflineAccessRule;
use SimpleSAML\Module\oidc\Server\RequestRules\Rules\ScopeRule;
use SimpleSAML\Module\oidc\Server\RequestRules\Rules\StateRule;
use SimpleSAML\Module\oidc\Server\RequestTypes\AuthorizationRequest;
+use SimpleSAML\Module\oidc\Server\ResponseModes\QueryResponseMode;
use SimpleSAML\Module\oidc\Server\ResponseTypes\Interfaces\AcrResponseTypeInterface;
use SimpleSAML\Module\oidc\Server\ResponseTypes\Interfaces\AuthTimeResponseTypeInterface;
use SimpleSAML\Module\oidc\Server\ResponseTypes\Interfaces\NonceResponseTypeInterface;
@@ -255,7 +257,7 @@ public function completeAuthorizationRequest(
*/
public function completeOidcAuthorizationRequest(
AuthorizationRequest $authorizationRequest,
- ): RedirectResponse {
+ ): AbstractResponseType {
$user = $authorizationRequest->getUser();
if ($user instanceof UserEntity === false) {
throw new LogicException('An instance of UserEntity should be set on the ' .
@@ -272,6 +274,7 @@ public function completeOidcAuthorizationRequest(
$finalRedirectUri,
null,
$authorizationRequest->getState(),
+ $authorizationRequest->getResponseMode(),
);
}
@@ -304,15 +307,13 @@ public function completeOidcAuthorizationRequest(
$jsonPayload = json_encode($payload, JSON_THROW_ON_ERROR);
- $response = new RedirectResponse();
- $response->setRedirectUri(
- $this->makeRedirectUri(
- $finalRedirectUri,
- [
- 'code' => $this->encrypt($jsonPayload),
- 'state' => $authorizationRequest->getState(),
- ],
- ),
+ $responseMode = $authorizationRequest->getResponseMode() ?? new QueryResponseMode();
+ $response = $responseMode->buildResponse(
+ $finalRedirectUri,
+ [
+ 'code' => $this->encrypt($jsonPayload),
+ 'state' => $authorizationRequest->getState(),
+ ],
);
return $response;
@@ -503,7 +504,9 @@ public function respondToAccessTokenRequest(
$resultBag = $this->requestRulesManager->check(
$request,
$rulesToExecute,
- false,
+ // TODO: Response mode is not relevant for token request, as there is
+ // no redirection, but we need to provide something to execute rules.
+ new QueryResponseMode(),
$this->allowedTokenHttpMethods,
);
@@ -770,6 +773,8 @@ public function validateAuthorizationRequestWithRequestRules(
$state = $resultBag->getOrFail(StateRule::class)->getValue();
/** @var \SimpleSAML\Module\oidc\Entities\Interfaces\ClientEntityInterface $client */
$client = $resultBag->getOrFail(ClientRule::class)->getValue();
+ /** @var \SimpleSAML\Module\oidc\Server\ResponseModes\ResponseModeInterface $responseMode */
+ $responseMode = $resultBag->getOrFail(ResponseModeRule::class)->getValue();
$this->loggerService->debug('AuthCodeGrant: Resolved data:', [
'redirectUri' => $redirectUri,
@@ -784,7 +789,7 @@ public function validateAuthorizationRequestWithRequestRules(
$resultBag = $this->requestRulesManager->check(
$request,
$rulesToExecute,
- false,
+ $responseMode,
$this->allowedAuthorizationHttpMethods,
);
@@ -902,6 +907,14 @@ public function validateAuthorizationRequestWithRequestRules(
);
$authorizationRequest->setAuthorizationDetails($authorizationDetails);
+ /** @var \SimpleSAML\Module\oidc\Server\ResponseModes\ResponseModeInterface $responseMode */
+ $responseMode = $resultBag->getOrFail(ResponseModeRule::class)->getValue();
+ $this->loggerService->debug(
+ 'AuthCodeGrant: Response mode: ',
+ ['responseMode' => $responseMode],
+ );
+ $authorizationRequest->setResponseMode($responseMode);
+
// TODO This is a band-aid fix for having credential claims in the userinfo endpoint when
// only VCI authorizationDetails are supplied. This requires configuring a matching OIDC scope
// that has all the credential type claims as well.
diff --git a/src/Server/Grants/ImplicitGrant.php b/src/Server/Grants/ImplicitGrant.php
index 2677ca98..75fcf1c8 100644
--- a/src/Server/Grants/ImplicitGrant.php
+++ b/src/Server/Grants/ImplicitGrant.php
@@ -7,7 +7,6 @@
use DateInterval;
use League\OAuth2\Server\Grant\ImplicitGrant as OAuth2ImplicitGrant;
use League\OAuth2\Server\RequestTypes\AuthorizationRequest as OAuth2AuthorizationRequest;
-use League\OAuth2\Server\ResponseTypes\RedirectResponse;
use League\OAuth2\Server\ResponseTypes\ResponseTypeInterface;
use LogicException;
use Psr\Http\Message\ServerRequestInterface;
@@ -32,10 +31,12 @@
use SimpleSAML\Module\oidc\Server\RequestRules\Rules\RequestObjectRule;
use SimpleSAML\Module\oidc\Server\RequestRules\Rules\RequiredNonceRule;
use SimpleSAML\Module\oidc\Server\RequestRules\Rules\RequiredOpenIdScopeRule;
+use SimpleSAML\Module\oidc\Server\RequestRules\Rules\ResponseModeRule;
use SimpleSAML\Module\oidc\Server\RequestRules\Rules\ResponseTypeRule;
use SimpleSAML\Module\oidc\Server\RequestRules\Rules\ScopeRule;
use SimpleSAML\Module\oidc\Server\RequestRules\Rules\StateRule;
use SimpleSAML\Module\oidc\Server\RequestTypes\AuthorizationRequest;
+use SimpleSAML\Module\oidc\Server\ResponseModes\FragmentResponseMode;
use SimpleSAML\Module\oidc\Services\IdTokenBuilder;
use SimpleSAML\Module\oidc\Utils\RequestParamsResolver;
use SimpleSAML\OpenID\Codebooks\HttpMethodsEnum;
@@ -62,10 +63,9 @@ public function __construct(
AccessTokenRepositoryInterface $accessTokenRepository,
protected RequestRulesManager $requestRulesManager,
protected RequestParamsResolver $requestParamsResolver,
- protected string $queryDelimiter,
AccessTokenEntityFactory $accessTokenEntityFactory,
) {
- parent::__construct($accessTokenTTL, $queryDelimiter);
+ parent::__construct($accessTokenTTL);
$this->accessTokenRepository = $accessTokenRepository;
$this->accessTokenEntityFactory = $accessTokenEntityFactory;
@@ -143,6 +143,8 @@ public function validateAuthorizationRequestWithRequestRules(
$state = $resultBag->getOrFail(StateRule::class)->getValue();
/** @var \SimpleSAML\Module\oidc\Entities\Interfaces\ClientEntityInterface $client */
$client = $resultBag->getOrFail(ClientRule::class)->getValue();
+ /** @var \SimpleSAML\Module\oidc\Server\ResponseModes\ResponseModeInterface $responseMode */
+ $responseMode = $resultBag->getOrFail(ResponseModeRule::class)->getValue();
// Some rules need certain things available in order to work properly...
$this->requestRulesManager->setData('default_scope', $this->defaultScope);
@@ -151,7 +153,7 @@ public function validateAuthorizationRequestWithRequestRules(
$resultBag = $this->requestRulesManager->check(
$request,
$rulesToExecute,
- $this->shouldUseFragment(),
+ $responseMode,
$this->allowedAuthorizationHttpMethods,
);
@@ -195,6 +197,10 @@ public function validateAuthorizationRequestWithRequestRules(
$acrValues = $resultBag->getOrFail(AcrValuesRule::class)->getValue();
$authorizationRequest->setRequestedAcrValues($acrValues);
+ /** @var \SimpleSAML\Module\oidc\Server\ResponseModes\ResponseModeInterface $responseMode */
+ $responseMode = $resultBag->getOrFail(ResponseModeRule::class)->getValue();
+ $authorizationRequest->setResponseMode($responseMode);
+
return $authorizationRequest;
}
@@ -220,7 +226,7 @@ private function completeOidcAuthorizationRequest(AuthorizationRequest $authoriz
$redirectUrl,
null,
$authorizationRequest->getState(),
- $this->shouldUseFragment(),
+ $authorizationRequest->getResponseMode(),
);
}
@@ -274,14 +280,10 @@ private function completeOidcAuthorizationRequest(AuthorizationRequest $authoriz
$responseParams['id_token'] = $idToken->getToken();
- $response = new RedirectResponse();
-
- $response->setRedirectUri(
- $this->makeRedirectUri(
- $redirectUrl,
- $responseParams,
- $this->queryDelimiter,
- ),
+ $responseMode = $authorizationRequest->getResponseMode() ?? new FragmentResponseMode();
+ $response = $responseMode->buildResponse(
+ $redirectUrl,
+ $responseParams,
);
return $response;
@@ -301,14 +303,4 @@ private function getRedirectUrl(AuthorizationRequest $authorizationRequest): str
return $redirectUris;
}
-
- /**
- * Check if fragment should be used for params transportation in HTTP responses
- *
- * @return bool
- */
- protected function shouldUseFragment(): bool
- {
- return $this->queryDelimiter === '#';
- }
}
diff --git a/src/Server/Grants/PreAuthCodeGrant.php b/src/Server/Grants/PreAuthCodeGrant.php
index 5c7e0a24..4b13ef5c 100644
--- a/src/Server/Grants/PreAuthCodeGrant.php
+++ b/src/Server/Grants/PreAuthCodeGrant.php
@@ -22,6 +22,7 @@
use SimpleSAML\Module\oidc\Server\RequestRules\Interfaces\ResultBagInterface;
use SimpleSAML\Module\oidc\Server\RequestRules\Rules\AuthorizationDetailsRule;
use SimpleSAML\Module\oidc\Server\RequestTypes\AuthorizationRequest;
+use SimpleSAML\Module\oidc\Server\ResponseModes\QueryResponseMode;
use SimpleSAML\OpenID\Codebooks\GrantTypesEnum;
use SimpleSAML\OpenID\Codebooks\ParamsEnum;
@@ -174,7 +175,9 @@ public function respondToAccessTokenRequest(
$resultBag = $this->requestRulesManager->check(
$request,
[AuthorizationDetailsRule::class],
- false,
+ // TODO: Response mode is not relevant for token request, as there is
+ // no redirection, but we need to provide something to execute rules.
+ new QueryResponseMode(),
$this->allowedTokenHttpMethods,
);
diff --git a/src/Server/RequestRules/Interfaces/RequestRuleInterface.php b/src/Server/RequestRules/Interfaces/RequestRuleInterface.php
index 6f719a31..65a39950 100644
--- a/src/Server/RequestRules/Interfaces/RequestRuleInterface.php
+++ b/src/Server/RequestRules/Interfaces/RequestRuleInterface.php
@@ -5,6 +5,8 @@
namespace SimpleSAML\Module\oidc\Server\RequestRules\Interfaces;
use Psr\Http\Message\ServerRequestInterface;
+use SimpleSAML\Module\oidc\Server\ResponseModes\QueryResponseMode;
+use SimpleSAML\Module\oidc\Server\ResponseModes\ResponseModeInterface;
use SimpleSAML\Module\oidc\Services\LoggerService;
use SimpleSAML\OpenID\Codebooks\HttpMethodsEnum;
@@ -18,13 +20,15 @@ public function getKey(): string;
/**
* Check specific rule.
+ *
* @param \SimpleSAML\Module\oidc\Server\RequestRules\Interfaces\ResultBagInterface $currentResultBag
* ResultBag with all results of the checks performed to current check
* @param array $data Data which will be available during check.
- * @param bool $useFragmentInHttpErrorResponses Indicate that in case of HTTP error responses, params should be
- * returned in URI fragment instead of query.
+ * @param ResponseModeInterface $responseMode Response mode to use for error responses
* @param HttpMethodsEnum[] $allowedServerRequestMethods Indicate allowed HTTP methods used for request
+ *
* @return \SimpleSAML\Module\oidc\Server\RequestRules\Interfaces\ResultInterface|null Result of the specific check
+ *
* @throws \SimpleSAML\Module\oidc\Server\Exceptions\OidcServerException If check fails
*/
public function checkRule(
@@ -32,7 +36,7 @@ public function checkRule(
ResultBagInterface $currentResultBag,
LoggerService $loggerService,
array $data = [],
- bool $useFragmentInHttpErrorResponses = false,
+ ResponseModeInterface $responseMode = new QueryResponseMode(),
array $allowedServerRequestMethods = [HttpMethodsEnum::GET],
): ?ResultInterface;
}
diff --git a/src/Server/RequestRules/RequestRulesManager.php b/src/Server/RequestRules/RequestRulesManager.php
index c08c1a67..9adfad34 100644
--- a/src/Server/RequestRules/RequestRulesManager.php
+++ b/src/Server/RequestRules/RequestRulesManager.php
@@ -9,6 +9,8 @@
use SimpleSAML\Module\oidc\Server\RequestRules\Interfaces\RequestRuleInterface;
use SimpleSAML\Module\oidc\Server\RequestRules\Interfaces\ResultBagInterface;
use SimpleSAML\Module\oidc\Server\RequestRules\Interfaces\ResultInterface;
+use SimpleSAML\Module\oidc\Server\ResponseModes\QueryResponseMode;
+use SimpleSAML\Module\oidc\Server\ResponseModes\ResponseModeInterface;
use SimpleSAML\Module\oidc\Services\LoggerService;
use SimpleSAML\OpenID\Codebooks\HttpMethodsEnum;
@@ -45,15 +47,16 @@ public function add(RequestRuleInterface $rule): void
/**
* @param class-string[] $ruleKeysToExecute
- * @param bool $useFragmentInHttpErrorResponses Indicate that in case of HTTP error responses, params should be
- * returned in URI fragment instead of query.
+ * @param ResponseModeInterface $responseMode Response mode which will be
+ * used in rules execution, as some rules might need to adjust their
+ * behaviour based on response mode used in request.
* @param HttpMethodsEnum[] $allowedServerRequestMethods Indicate allowed HTTP methods used for request
* @throws \SimpleSAML\Module\oidc\Server\Exceptions\OidcServerException
*/
public function check(
ServerRequestInterface $request,
array $ruleKeysToExecute,
- bool $useFragmentInHttpErrorResponses = false,
+ ResponseModeInterface $responseMode = new QueryResponseMode(),
array $allowedServerRequestMethods = [HttpMethodsEnum::GET],
): ResultBagInterface {
foreach ($ruleKeysToExecute as $ruleKey) {
@@ -66,7 +69,7 @@ public function check(
$this->resultBag,
$this->loggerService,
$this->data,
- $useFragmentInHttpErrorResponses,
+ $responseMode,
$allowedServerRequestMethods,
);
@@ -97,7 +100,7 @@ public function predefineResultBag(ResultBagInterface $resultBag): void
/**
* Set data which will be available in each check, using key value pair
*/
- public function setData(string $key, mixed $value): void
+ public function setData(string $key, string $value): void
{
$this->data[$key] = $value;
}
diff --git a/src/Server/RequestRules/Rules/AcrValuesRule.php b/src/Server/RequestRules/Rules/AcrValuesRule.php
index 7d02cf1f..d971303b 100644
--- a/src/Server/RequestRules/Rules/AcrValuesRule.php
+++ b/src/Server/RequestRules/Rules/AcrValuesRule.php
@@ -8,6 +8,8 @@
use SimpleSAML\Module\oidc\Server\RequestRules\Interfaces\ResultBagInterface;
use SimpleSAML\Module\oidc\Server\RequestRules\Interfaces\ResultInterface;
use SimpleSAML\Module\oidc\Server\RequestRules\Result;
+use SimpleSAML\Module\oidc\Server\ResponseModes\QueryResponseMode;
+use SimpleSAML\Module\oidc\Server\ResponseModes\ResponseModeInterface;
use SimpleSAML\Module\oidc\Services\LoggerService;
use SimpleSAML\OpenID\Codebooks\HttpMethodsEnum;
use SimpleSAML\OpenID\Codebooks\ParamsEnum;
@@ -16,13 +18,16 @@ class AcrValuesRule extends AbstractRule
{
/**
* @inheritDoc
+ *
+ * @param ResponseModeInterface $responseMode
+ * @param HttpMethodsEnum[] $allowedServerRequestMethods
*/
public function checkRule(
ServerRequestInterface $request,
ResultBagInterface $currentResultBag,
LoggerService $loggerService,
array $data = [],
- bool $useFragmentInHttpErrorResponses = false,
+ ResponseModeInterface $responseMode = new QueryResponseMode(),
array $allowedServerRequestMethods = [HttpMethodsEnum::GET],
): ?ResultInterface {
$loggerService->debug('AcrValuesRule::checkRule');
diff --git a/src/Server/RequestRules/Rules/AddClaimsToIdTokenRule.php b/src/Server/RequestRules/Rules/AddClaimsToIdTokenRule.php
index a6aae64f..e0ca70f1 100644
--- a/src/Server/RequestRules/Rules/AddClaimsToIdTokenRule.php
+++ b/src/Server/RequestRules/Rules/AddClaimsToIdTokenRule.php
@@ -8,6 +8,8 @@
use SimpleSAML\Module\oidc\Server\RequestRules\Interfaces\ResultBagInterface;
use SimpleSAML\Module\oidc\Server\RequestRules\Interfaces\ResultInterface;
use SimpleSAML\Module\oidc\Server\RequestRules\Result;
+use SimpleSAML\Module\oidc\Server\ResponseModes\QueryResponseMode;
+use SimpleSAML\Module\oidc\Server\ResponseModes\ResponseModeInterface;
use SimpleSAML\Module\oidc\Services\LoggerService;
use SimpleSAML\OpenID\Codebooks\HttpMethodsEnum;
@@ -15,14 +17,17 @@ class AddClaimsToIdTokenRule extends AbstractRule
{
/**
* @inheritDoc
+ *
* @throws \Throwable
+ *
+ * @param ResponseModeInterface $responseMode
*/
public function checkRule(
ServerRequestInterface $request,
ResultBagInterface $currentResultBag,
LoggerService $loggerService,
array $data = [],
- bool $useFragmentInHttpErrorResponses = false,
+ ResponseModeInterface $responseMode = new QueryResponseMode(),
array $allowedServerRequestMethods = [HttpMethodsEnum::GET],
): ?ResultInterface {
/** @var string $responseType */
diff --git a/src/Server/RequestRules/Rules/AuthorizationDetailsRule.php b/src/Server/RequestRules/Rules/AuthorizationDetailsRule.php
index 4b4ff89f..4af36369 100644
--- a/src/Server/RequestRules/Rules/AuthorizationDetailsRule.php
+++ b/src/Server/RequestRules/Rules/AuthorizationDetailsRule.php
@@ -11,6 +11,8 @@
use SimpleSAML\Module\oidc\Server\RequestRules\Interfaces\ResultBagInterface;
use SimpleSAML\Module\oidc\Server\RequestRules\Interfaces\ResultInterface;
use SimpleSAML\Module\oidc\Server\RequestRules\Result;
+use SimpleSAML\Module\oidc\Server\ResponseModes\QueryResponseMode;
+use SimpleSAML\Module\oidc\Server\ResponseModes\ResponseModeInterface;
use SimpleSAML\Module\oidc\Services\LoggerService;
use SimpleSAML\Module\oidc\Utils\RequestParamsResolver;
use SimpleSAML\OpenID\Codebooks\HttpMethodsEnum;
@@ -28,13 +30,16 @@ public function __construct(
/**
* @inheritDoc
+ *
+ * @param ResponseModeInterface $responseMode
+ * @param HttpMethodsEnum[] $allowedServerRequestMethods
*/
public function checkRule(
ServerRequestInterface $request,
ResultBagInterface $currentResultBag,
LoggerService $loggerService,
array $data = [],
- bool $useFragmentInHttpErrorResponses = false,
+ ResponseModeInterface $responseMode = new QueryResponseMode(),
array $allowedServerRequestMethods = [HttpMethodsEnum::GET],
): ?ResultInterface {
$loggerService->debug('AuthorizationDetailsRule::checkRule.');
diff --git a/src/Server/RequestRules/Rules/ClientAuthenticationRule.php b/src/Server/RequestRules/Rules/ClientAuthenticationRule.php
index 7a062bd6..f6e7a92f 100644
--- a/src/Server/RequestRules/Rules/ClientAuthenticationRule.php
+++ b/src/Server/RequestRules/Rules/ClientAuthenticationRule.php
@@ -10,6 +10,8 @@
use SimpleSAML\Module\oidc\Server\RequestRules\Interfaces\ResultBagInterface;
use SimpleSAML\Module\oidc\Server\RequestRules\Interfaces\ResultInterface;
use SimpleSAML\Module\oidc\Server\RequestRules\Result;
+use SimpleSAML\Module\oidc\Server\ResponseModes\QueryResponseMode;
+use SimpleSAML\Module\oidc\Server\ResponseModes\ResponseModeInterface;
use SimpleSAML\Module\oidc\Services\LoggerService;
use SimpleSAML\Module\oidc\Utils\AuthenticatedOAuth2ClientResolver;
use SimpleSAML\Module\oidc\Utils\RequestParamsResolver;
@@ -28,13 +30,15 @@ public function __construct(
/**
* @throws \SimpleSAML\Module\oidc\Server\Exceptions\OidcServerException
* @throws \Throwable
+ *
+ * @param ResponseModeInterface $responseMode
*/
public function checkRule(
ServerRequestInterface $request,
ResultBagInterface $currentResultBag,
LoggerService $loggerService,
array $data = [],
- bool $useFragmentInHttpErrorResponses = false,
+ ResponseModeInterface $responseMode = new QueryResponseMode(),
array $allowedServerRequestMethods = [HttpMethodsEnum::GET],
): ?ResultInterface {
diff --git a/src/Server/RequestRules/Rules/ClientIdRule.php b/src/Server/RequestRules/Rules/ClientIdRule.php
index b329c179..0a2e80bc 100644
--- a/src/Server/RequestRules/Rules/ClientIdRule.php
+++ b/src/Server/RequestRules/Rules/ClientIdRule.php
@@ -9,6 +9,8 @@
use SimpleSAML\Module\oidc\Server\RequestRules\Interfaces\ResultBagInterface;
use SimpleSAML\Module\oidc\Server\RequestRules\Interfaces\ResultInterface;
use SimpleSAML\Module\oidc\Server\RequestRules\Result;
+use SimpleSAML\Module\oidc\Server\ResponseModes\QueryResponseMode;
+use SimpleSAML\Module\oidc\Server\ResponseModes\ResponseModeInterface;
use SimpleSAML\Module\oidc\Services\LoggerService;
use SimpleSAML\OpenID\Codebooks\HttpMethodsEnum;
use SimpleSAML\OpenID\Codebooks\ParamsEnum;
@@ -20,6 +22,7 @@ class ClientIdRule extends AbstractRule
{
/**
* @inheritDoc
+ *
* @throws \JsonException
* @throws \League\OAuth2\Server\Exception\OAuthServerException
* @throws \Psr\SimpleCache\InvalidArgumentException
@@ -32,13 +35,16 @@ class ClientIdRule extends AbstractRule
* @throws \SimpleSAML\OpenID\Exceptions\RequestObjectException
* @throws \SimpleSAML\OpenID\Exceptions\TrustChainException
* @throws \SimpleSAML\OpenID\Exceptions\TrustMarkException
+ *
+ * @param ResponseModeInterface $responseMode
+ * @param HttpMethodsEnum[] $allowedServerRequestMethods
*/
public function checkRule(
ServerRequestInterface $request,
ResultBagInterface $currentResultBag,
LoggerService $loggerService,
array $data = [],
- bool $useFragmentInHttpErrorResponses = false,
+ ResponseModeInterface $responseMode = new QueryResponseMode(),
array $allowedServerRequestMethods = [HttpMethodsEnum::GET],
): ?ResultInterface {
$loggerService->debug('ClientIdRule::checkRule');
diff --git a/src/Server/RequestRules/Rules/ClientRedirectUriRule.php b/src/Server/RequestRules/Rules/ClientRedirectUriRule.php
index 3c00c763..d4aa11f1 100644
--- a/src/Server/RequestRules/Rules/ClientRedirectUriRule.php
+++ b/src/Server/RequestRules/Rules/ClientRedirectUriRule.php
@@ -13,6 +13,8 @@
use SimpleSAML\Module\oidc\Server\RequestRules\Interfaces\ResultBagInterface;
use SimpleSAML\Module\oidc\Server\RequestRules\Interfaces\ResultInterface;
use SimpleSAML\Module\oidc\Server\RequestRules\Result;
+use SimpleSAML\Module\oidc\Server\ResponseModes\QueryResponseMode;
+use SimpleSAML\Module\oidc\Server\ResponseModes\ResponseModeInterface;
use SimpleSAML\Module\oidc\Services\LoggerService;
use SimpleSAML\Module\oidc\Utils\RequestParamsResolver;
use SimpleSAML\OpenID\Codebooks\HttpMethodsEnum;
@@ -30,14 +32,18 @@ public function __construct(
/**
* @inheritDoc
+ *
* @throws \Throwable
+ *
+ * @param ResponseModeInterface $responseMode
+ * @param HttpMethodsEnum[] $allowedServerRequestMethods
*/
public function checkRule(
ServerRequestInterface $request,
ResultBagInterface $currentResultBag,
LoggerService $loggerService,
array $data = [],
- bool $useFragmentInHttpErrorResponses = false,
+ ResponseModeInterface $responseMode = new QueryResponseMode(),
array $allowedServerRequestMethods = [HttpMethodsEnum::GET],
): ?ResultInterface {
$loggerService->debug('RedirectUriRule::checkRule');
diff --git a/src/Server/RequestRules/Rules/ClientRule.php b/src/Server/RequestRules/Rules/ClientRule.php
index ac6a1160..242c60d0 100644
--- a/src/Server/RequestRules/Rules/ClientRule.php
+++ b/src/Server/RequestRules/Rules/ClientRule.php
@@ -17,6 +17,8 @@
use SimpleSAML\Module\oidc\Server\RequestRules\Interfaces\ResultBagInterface;
use SimpleSAML\Module\oidc\Server\RequestRules\Interfaces\ResultInterface;
use SimpleSAML\Module\oidc\Server\RequestRules\Result;
+use SimpleSAML\Module\oidc\Server\ResponseModes\QueryResponseMode;
+use SimpleSAML\Module\oidc\Server\ResponseModes\ResponseModeInterface;
use SimpleSAML\Module\oidc\Services\LoggerService;
use SimpleSAML\Module\oidc\Utils\FederationCache;
use SimpleSAML\Module\oidc\Utils\FederationParticipationValidator;
@@ -53,6 +55,7 @@ public function __construct(
/**
* @inheritDoc
+ *
* @throws \JsonException
* @throws \League\OAuth2\Server\Exception\OAuthServerException
* @throws \Psr\SimpleCache\InvalidArgumentException
@@ -65,13 +68,16 @@ public function __construct(
* @throws \SimpleSAML\OpenID\Exceptions\RequestObjectException
* @throws \SimpleSAML\OpenID\Exceptions\TrustChainException
* @throws \SimpleSAML\OpenID\Exceptions\TrustMarkException
+ *
+ * @param ResponseModeInterface $responseMode
+ * @param HttpMethodsEnum[] $allowedServerRequestMethods
*/
public function checkRule(
ServerRequestInterface $request,
ResultBagInterface $currentResultBag,
LoggerService $loggerService,
array $data = [],
- bool $useFragmentInHttpErrorResponses = false,
+ ResponseModeInterface $responseMode = new QueryResponseMode(),
array $allowedServerRequestMethods = [HttpMethodsEnum::GET],
): ?ResultInterface {
$loggerService->debug('ClientRule::checkRule.');
diff --git a/src/Server/RequestRules/Rules/CodeChallengeMethodRule.php b/src/Server/RequestRules/Rules/CodeChallengeMethodRule.php
index 33d5f70a..f0e46c42 100644
--- a/src/Server/RequestRules/Rules/CodeChallengeMethodRule.php
+++ b/src/Server/RequestRules/Rules/CodeChallengeMethodRule.php
@@ -11,6 +11,8 @@
use SimpleSAML\Module\oidc\Server\RequestRules\Interfaces\ResultBagInterface;
use SimpleSAML\Module\oidc\Server\RequestRules\Interfaces\ResultInterface;
use SimpleSAML\Module\oidc\Server\RequestRules\Result;
+use SimpleSAML\Module\oidc\Server\ResponseModes\QueryResponseMode;
+use SimpleSAML\Module\oidc\Server\ResponseModes\ResponseModeInterface;
use SimpleSAML\Module\oidc\Services\LoggerService;
use SimpleSAML\Module\oidc\Utils\RequestParamsResolver;
use SimpleSAML\OpenID\Codebooks\HttpMethodsEnum;
@@ -29,13 +31,16 @@ public function __construct(
/**
* @throws \Throwable
* @throws \SimpleSAML\Module\oidc\Server\Exceptions\OidcServerException
+ *
+ * @param ResponseModeInterface $responseMode
+ * @param HttpMethodsEnum[] $allowedServerRequestMethods
*/
public function checkRule(
ServerRequestInterface $request,
ResultBagInterface $currentResultBag,
LoggerService $loggerService,
array $data = [],
- bool $useFragmentInHttpErrorResponses = false,
+ ResponseModeInterface $responseMode = new QueryResponseMode(),
array $allowedServerRequestMethods = [HttpMethodsEnum::GET],
): ?ResultInterface {
$loggerService->debug('CodeChallengeMethodRule::checkRule');
@@ -62,7 +67,7 @@ public function checkRule(
null,
$redirectUri,
$state,
- $useFragmentInHttpErrorResponses,
+ $responseMode,
);
}
diff --git a/src/Server/RequestRules/Rules/CodeChallengeRule.php b/src/Server/RequestRules/Rules/CodeChallengeRule.php
index feb37160..b55d79d6 100644
--- a/src/Server/RequestRules/Rules/CodeChallengeRule.php
+++ b/src/Server/RequestRules/Rules/CodeChallengeRule.php
@@ -9,6 +9,8 @@
use SimpleSAML\Module\oidc\Server\RequestRules\Interfaces\ResultBagInterface;
use SimpleSAML\Module\oidc\Server\RequestRules\Interfaces\ResultInterface;
use SimpleSAML\Module\oidc\Server\RequestRules\Result;
+use SimpleSAML\Module\oidc\Server\ResponseModes\QueryResponseMode;
+use SimpleSAML\Module\oidc\Server\ResponseModes\ResponseModeInterface;
use SimpleSAML\Module\oidc\Services\LoggerService;
use SimpleSAML\OpenID\Codebooks\HttpMethodsEnum;
use SimpleSAML\OpenID\Codebooks\ParamsEnum;
@@ -17,14 +19,18 @@ class CodeChallengeRule extends AbstractRule
{
/**
* @inheritDoc
+ *
* @throws \Throwable
+ *
+ * @param ResponseModeInterface $responseMode
+ * @param HttpMethodsEnum[] $allowedServerRequestMethods
*/
public function checkRule(
ServerRequestInterface $request,
ResultBagInterface $currentResultBag,
LoggerService $loggerService,
array $data = [],
- bool $useFragmentInHttpErrorResponses = false,
+ ResponseModeInterface $responseMode = new QueryResponseMode(),
array $allowedServerRequestMethods = [HttpMethodsEnum::GET],
): ?ResultInterface {
$loggerService->debug('CodeChallengeRule::checkRule');
@@ -50,7 +56,7 @@ public function checkRule(
null,
$redirectUri,
$state,
- $useFragmentInHttpErrorResponses,
+ $responseMode,
);
}
@@ -66,7 +72,7 @@ public function checkRule(
null,
$redirectUri,
$state,
- $useFragmentInHttpErrorResponses,
+ $responseMode,
);
}
diff --git a/src/Server/RequestRules/Rules/CodeVerifierRule.php b/src/Server/RequestRules/Rules/CodeVerifierRule.php
index 8b3767eb..d4bcc04a 100644
--- a/src/Server/RequestRules/Rules/CodeVerifierRule.php
+++ b/src/Server/RequestRules/Rules/CodeVerifierRule.php
@@ -9,6 +9,8 @@
use SimpleSAML\Module\oidc\Server\RequestRules\Interfaces\ResultBagInterface;
use SimpleSAML\Module\oidc\Server\RequestRules\Interfaces\ResultInterface;
use SimpleSAML\Module\oidc\Server\RequestRules\Result;
+use SimpleSAML\Module\oidc\Server\ResponseModes\QueryResponseMode;
+use SimpleSAML\Module\oidc\Server\ResponseModes\ResponseModeInterface;
use SimpleSAML\Module\oidc\Services\LoggerService;
use SimpleSAML\OpenID\Codebooks\HttpMethodsEnum;
use SimpleSAML\OpenID\Codebooks\ParamsEnum;
@@ -17,13 +19,16 @@ class CodeVerifierRule extends AbstractRule
{
/**
* @inheritDoc
+ *
+ * @param ResponseModeInterface $responseMode
+ * @param HttpMethodsEnum[] $allowedServerRequestMethods
*/
public function checkRule(
ServerRequestInterface $request,
ResultBagInterface $currentResultBag,
LoggerService $loggerService,
array $data = [],
- bool $useFragmentInHttpErrorResponses = false,
+ ResponseModeInterface $responseMode = new QueryResponseMode(),
array $allowedServerRequestMethods = [HttpMethodsEnum::GET],
): ?ResultInterface {
/** @var \SimpleSAML\Module\oidc\Entities\Interfaces\ClientEntityInterface $client */
diff --git a/src/Server/RequestRules/Rules/IdTokenHintRule.php b/src/Server/RequestRules/Rules/IdTokenHintRule.php
index 8feccbf2..dc481b22 100644
--- a/src/Server/RequestRules/Rules/IdTokenHintRule.php
+++ b/src/Server/RequestRules/Rules/IdTokenHintRule.php
@@ -11,6 +11,8 @@
use SimpleSAML\Module\oidc\Server\RequestRules\Interfaces\ResultBagInterface;
use SimpleSAML\Module\oidc\Server\RequestRules\Interfaces\ResultInterface;
use SimpleSAML\Module\oidc\Server\RequestRules\Result;
+use SimpleSAML\Module\oidc\Server\ResponseModes\QueryResponseMode;
+use SimpleSAML\Module\oidc\Server\ResponseModes\ResponseModeInterface;
use SimpleSAML\Module\oidc\Services\LoggerService;
use SimpleSAML\Module\oidc\Utils\RequestParamsResolver;
use SimpleSAML\OpenID\Codebooks\HttpMethodsEnum;
@@ -32,14 +34,18 @@ public function __construct(
/**
* @inheritDoc
+ *
* @throws \Throwable
+ *
+ * @param ResponseModeInterface $responseMode
+ * @param HttpMethodsEnum[] $allowedServerRequestMethods
*/
public function checkRule(
ServerRequestInterface $request,
ResultBagInterface $currentResultBag,
LoggerService $loggerService,
array $data = [],
- bool $useFragmentInHttpErrorResponses = false,
+ ResponseModeInterface $responseMode = new QueryResponseMode(),
array $allowedServerRequestMethods = [HttpMethodsEnum::GET],
): ?ResultInterface {
/** @var string|null $state */
diff --git a/src/Server/RequestRules/Rules/IssuerStateRule.php b/src/Server/RequestRules/Rules/IssuerStateRule.php
index 7ba9bf2d..962e94e9 100644
--- a/src/Server/RequestRules/Rules/IssuerStateRule.php
+++ b/src/Server/RequestRules/Rules/IssuerStateRule.php
@@ -8,6 +8,8 @@
use SimpleSAML\Module\oidc\Server\RequestRules\Interfaces\ResultBagInterface;
use SimpleSAML\Module\oidc\Server\RequestRules\Interfaces\ResultInterface;
use SimpleSAML\Module\oidc\Server\RequestRules\Result;
+use SimpleSAML\Module\oidc\Server\ResponseModes\QueryResponseMode;
+use SimpleSAML\Module\oidc\Server\ResponseModes\ResponseModeInterface;
use SimpleSAML\Module\oidc\Services\LoggerService;
use SimpleSAML\OpenID\Codebooks\HttpMethodsEnum;
use SimpleSAML\OpenID\Codebooks\ParamsEnum;
@@ -16,13 +18,16 @@ class IssuerStateRule extends AbstractRule
{
/**
* @inheritDoc
+ *
+ * @param ResponseModeInterface $responseMode
+ * @param HttpMethodsEnum[] $allowedServerRequestMethods
*/
public function checkRule(
ServerRequestInterface $request,
ResultBagInterface $currentResultBag,
LoggerService $loggerService,
array $data = [],
- bool $useFragmentInHttpErrorResponses = false,
+ ResponseModeInterface $responseMode = new QueryResponseMode(),
array $allowedServerRequestMethods = [HttpMethodsEnum::GET],
): ?ResultInterface {
$issuerState = $this->requestParamsResolver->getAsStringBasedOnAllowedMethods(
diff --git a/src/Server/RequestRules/Rules/MaxAgeRule.php b/src/Server/RequestRules/Rules/MaxAgeRule.php
index e5731a7f..1b02c085 100644
--- a/src/Server/RequestRules/Rules/MaxAgeRule.php
+++ b/src/Server/RequestRules/Rules/MaxAgeRule.php
@@ -12,6 +12,8 @@
use SimpleSAML\Module\oidc\Server\RequestRules\Interfaces\ResultBagInterface;
use SimpleSAML\Module\oidc\Server\RequestRules\Interfaces\ResultInterface;
use SimpleSAML\Module\oidc\Server\RequestRules\Result;
+use SimpleSAML\Module\oidc\Server\ResponseModes\QueryResponseMode;
+use SimpleSAML\Module\oidc\Server\ResponseModes\ResponseModeInterface;
use SimpleSAML\Module\oidc\Services\AuthenticationService;
use SimpleSAML\Module\oidc\Services\LoggerService;
use SimpleSAML\Module\oidc\Utils\RequestParamsResolver;
@@ -37,13 +39,16 @@ public function __construct(
* @throws \SimpleSAML\Error\NotFound
* @throws \SimpleSAML\Module\oidc\Server\Exceptions\OidcServerException
* @throws \Throwable
+ *
+ * @param ResponseModeInterface $responseMode
+ * @param HttpMethodsEnum[] $allowedServerRequestMethods
*/
public function checkRule(
ServerRequestInterface $request,
ResultBagInterface $currentResultBag,
LoggerService $loggerService,
array $data = [],
- bool $useFragmentInHttpErrorResponses = false,
+ ResponseModeInterface $responseMode = new QueryResponseMode(),
array $allowedServerRequestMethods = [HttpMethodsEnum::GET],
): ?ResultInterface {
$loggerService->debug('MaxAgeRule::checkRule');
@@ -80,7 +85,7 @@ public function checkRule(
null,
$redirectUri,
$state,
- $useFragmentInHttpErrorResponses,
+ $responseMode,
);
}
diff --git a/src/Server/RequestRules/Rules/PostLogoutRedirectUriRule.php b/src/Server/RequestRules/Rules/PostLogoutRedirectUriRule.php
index 258d8186..d0d4e8df 100644
--- a/src/Server/RequestRules/Rules/PostLogoutRedirectUriRule.php
+++ b/src/Server/RequestRules/Rules/PostLogoutRedirectUriRule.php
@@ -11,6 +11,8 @@
use SimpleSAML\Module\oidc\Server\RequestRules\Interfaces\ResultBagInterface;
use SimpleSAML\Module\oidc\Server\RequestRules\Interfaces\ResultInterface;
use SimpleSAML\Module\oidc\Server\RequestRules\Result;
+use SimpleSAML\Module\oidc\Server\ResponseModes\QueryResponseMode;
+use SimpleSAML\Module\oidc\Server\ResponseModes\ResponseModeInterface;
use SimpleSAML\Module\oidc\Services\LoggerService;
use SimpleSAML\Module\oidc\Utils\RequestParamsResolver;
use SimpleSAML\OpenID\Codebooks\HttpMethodsEnum;
@@ -28,14 +30,18 @@ public function __construct(
/**
* @inheritDoc
+ *
* @throws \Throwable
+ *
+ * @param ResponseModeInterface $responseMode
+ * @param HttpMethodsEnum[] $allowedServerRequestMethods
*/
public function checkRule(
ServerRequestInterface $request,
ResultBagInterface $currentResultBag,
LoggerService $loggerService,
array $data = [],
- bool $useFragmentInHttpErrorResponses = false,
+ ResponseModeInterface $responseMode = new QueryResponseMode(),
array $allowedServerRequestMethods = [HttpMethodsEnum::GET],
): ?ResultInterface {
/** @var string|null $state */
diff --git a/src/Server/RequestRules/Rules/PromptRule.php b/src/Server/RequestRules/Rules/PromptRule.php
index 8a994f45..9b708ab3 100644
--- a/src/Server/RequestRules/Rules/PromptRule.php
+++ b/src/Server/RequestRules/Rules/PromptRule.php
@@ -12,6 +12,8 @@
use SimpleSAML\Module\oidc\Server\Exceptions\OidcServerException;
use SimpleSAML\Module\oidc\Server\RequestRules\Interfaces\ResultBagInterface;
use SimpleSAML\Module\oidc\Server\RequestRules\Interfaces\ResultInterface;
+use SimpleSAML\Module\oidc\Server\ResponseModes\QueryResponseMode;
+use SimpleSAML\Module\oidc\Server\ResponseModes\ResponseModeInterface;
use SimpleSAML\Module\oidc\Services\AuthenticationService;
use SimpleSAML\Module\oidc\Services\LoggerService;
use SimpleSAML\Module\oidc\Utils\RequestParamsResolver;
@@ -38,13 +40,16 @@ public function __construct(
* @throws \SimpleSAML\Error\NotFound
* @throws \SimpleSAML\Module\oidc\Server\Exceptions\OidcServerException
* @throws \Throwable
+ *
+ * @param ResponseModeInterface $responseMode
+ * @param HttpMethodsEnum[] $allowedServerRequestMethods
*/
public function checkRule(
ServerRequestInterface $request,
ResultBagInterface $currentResultBag,
LoggerService $loggerService,
array $data = [],
- bool $useFragmentInHttpErrorResponses = false,
+ ResponseModeInterface $responseMode = new QueryResponseMode(),
array $allowedServerRequestMethods = [HttpMethodsEnum::GET],
): ?ResultInterface {
$loggerService->debug('PromptRule::checkRule');
@@ -78,7 +83,7 @@ public function checkRule(
$redirectUri,
null,
$state,
- $useFragmentInHttpErrorResponses,
+ $responseMode,
);
}
diff --git a/src/Server/RequestRules/Rules/RequestObjectRule.php b/src/Server/RequestRules/Rules/RequestObjectRule.php
index 81c05812..e4eab6e3 100644
--- a/src/Server/RequestRules/Rules/RequestObjectRule.php
+++ b/src/Server/RequestRules/Rules/RequestObjectRule.php
@@ -10,6 +10,8 @@
use SimpleSAML\Module\oidc\Server\RequestRules\Interfaces\ResultBagInterface;
use SimpleSAML\Module\oidc\Server\RequestRules\Interfaces\ResultInterface;
use SimpleSAML\Module\oidc\Server\RequestRules\Result;
+use SimpleSAML\Module\oidc\Server\ResponseModes\QueryResponseMode;
+use SimpleSAML\Module\oidc\Server\ResponseModes\ResponseModeInterface;
use SimpleSAML\Module\oidc\Services\LoggerService;
use SimpleSAML\Module\oidc\Utils\JwksResolver;
use SimpleSAML\Module\oidc\Utils\RequestParamsResolver;
@@ -29,13 +31,16 @@ public function __construct(
/**
* @throws \SimpleSAML\Module\oidc\Server\Exceptions\OidcServerException
* @throws \Throwable
+ *
+ * @param ResponseModeInterface $responseMode
+ * @param HttpMethodsEnum[] $allowedServerRequestMethods
*/
public function checkRule(
ServerRequestInterface $request,
ResultBagInterface $currentResultBag,
LoggerService $loggerService,
array $data = [],
- bool $useFragmentInHttpErrorResponses = false,
+ ResponseModeInterface $responseMode = new QueryResponseMode(),
array $allowedServerRequestMethods = [HttpMethodsEnum::GET],
): ?ResultInterface {
$loggerService->debug('RequestObjectRule::checkRule');
@@ -80,7 +85,7 @@ public function checkRule(
$redirectUri,
null,
$stateValue,
- $useFragmentInHttpErrorResponses,
+ $responseMode,
);
try {
@@ -91,7 +96,7 @@ public function checkRule(
$redirectUri,
null,
$stateValue,
- $useFragmentInHttpErrorResponses,
+ $responseMode,
);
}
diff --git a/src/Server/RequestRules/Rules/RequestedClaimsRule.php b/src/Server/RequestRules/Rules/RequestedClaimsRule.php
index 3a7d60b3..18388d64 100644
--- a/src/Server/RequestRules/Rules/RequestedClaimsRule.php
+++ b/src/Server/RequestRules/Rules/RequestedClaimsRule.php
@@ -9,6 +9,8 @@
use SimpleSAML\Module\oidc\Server\RequestRules\Interfaces\ResultBagInterface;
use SimpleSAML\Module\oidc\Server\RequestRules\Interfaces\ResultInterface;
use SimpleSAML\Module\oidc\Server\RequestRules\Result;
+use SimpleSAML\Module\oidc\Server\ResponseModes\QueryResponseMode;
+use SimpleSAML\Module\oidc\Server\ResponseModes\ResponseModeInterface;
use SimpleSAML\Module\oidc\Services\LoggerService;
use SimpleSAML\Module\oidc\Utils\ClaimTranslatorExtractor;
use SimpleSAML\Module\oidc\Utils\RequestParamsResolver;
@@ -28,13 +30,16 @@ public function __construct(
/**
* @throws \Throwable
+ *
+ * @param ResponseModeInterface $responseMode
+ * @param HttpMethodsEnum[] $allowedServerRequestMethods
*/
public function checkRule(
ServerRequestInterface $request,
ResultBagInterface $currentResultBag,
LoggerService $loggerService,
array $data = [],
- bool $useFragmentInHttpErrorResponses = false,
+ ResponseModeInterface $responseMode = new QueryResponseMode(),
array $allowedServerRequestMethods = [HttpMethodsEnum::GET],
): ?ResultInterface {
$loggerService->debug('RequestedClaimsRule::checkRule');
diff --git a/src/Server/RequestRules/Rules/RequiredNonceRule.php b/src/Server/RequestRules/Rules/RequiredNonceRule.php
index 16034d17..1839ca9c 100644
--- a/src/Server/RequestRules/Rules/RequiredNonceRule.php
+++ b/src/Server/RequestRules/Rules/RequiredNonceRule.php
@@ -9,6 +9,8 @@
use SimpleSAML\Module\oidc\Server\RequestRules\Interfaces\ResultBagInterface;
use SimpleSAML\Module\oidc\Server\RequestRules\Interfaces\ResultInterface;
use SimpleSAML\Module\oidc\Server\RequestRules\Result;
+use SimpleSAML\Module\oidc\Server\ResponseModes\QueryResponseMode;
+use SimpleSAML\Module\oidc\Server\ResponseModes\ResponseModeInterface;
use SimpleSAML\Module\oidc\Services\LoggerService;
use SimpleSAML\OpenID\Codebooks\HttpMethodsEnum;
use SimpleSAML\OpenID\Codebooks\ParamsEnum;
@@ -17,14 +19,18 @@ class RequiredNonceRule extends AbstractRule
{
/**
* @inheritDoc
+ *
* @throws \Throwable
+ *
+ * @param ResponseModeInterface $responseMode
+ * @param HttpMethodsEnum[] $allowedServerRequestMethods
*/
public function checkRule(
ServerRequestInterface $request,
ResultBagInterface $currentResultBag,
LoggerService $loggerService,
array $data = [],
- bool $useFragmentInHttpErrorResponses = false,
+ ResponseModeInterface $responseMode = new QueryResponseMode(),
array $allowedServerRequestMethods = [HttpMethodsEnum::GET],
): ?ResultInterface {
/** @var string $redirectUri */
@@ -45,7 +51,7 @@ public function checkRule(
null,
$redirectUri,
$state,
- $useFragmentInHttpErrorResponses,
+ $responseMode,
);
}
diff --git a/src/Server/RequestRules/Rules/RequiredOpenIdScopeRule.php b/src/Server/RequestRules/Rules/RequiredOpenIdScopeRule.php
index 5fa0dc86..53b62375 100644
--- a/src/Server/RequestRules/Rules/RequiredOpenIdScopeRule.php
+++ b/src/Server/RequestRules/Rules/RequiredOpenIdScopeRule.php
@@ -9,6 +9,8 @@
use SimpleSAML\Module\oidc\Server\RequestRules\Interfaces\ResultBagInterface;
use SimpleSAML\Module\oidc\Server\RequestRules\Interfaces\ResultInterface;
use SimpleSAML\Module\oidc\Server\RequestRules\Result;
+use SimpleSAML\Module\oidc\Server\ResponseModes\QueryResponseMode;
+use SimpleSAML\Module\oidc\Server\ResponseModes\ResponseModeInterface;
use SimpleSAML\Module\oidc\Services\LoggerService;
use SimpleSAML\OpenID\Codebooks\HttpMethodsEnum;
@@ -16,14 +18,18 @@ class RequiredOpenIdScopeRule extends AbstractRule
{
/**
* @inheritDoc
+ *
* @throws \Throwable
+ *
+ * @param ResponseModeInterface $responseMode
+ * @param HttpMethodsEnum[] $allowedServerRequestMethods
*/
public function checkRule(
ServerRequestInterface $request,
ResultBagInterface $currentResultBag,
LoggerService $loggerService,
array $data = [],
- bool $useFragmentInHttpErrorResponses = false,
+ ResponseModeInterface $responseMode = new QueryResponseMode(),
array $allowedServerRequestMethods = [HttpMethodsEnum::GET],
): ?ResultInterface {
$loggerService->debug('RequiredOpenIdScopeRule::checkRule.');
@@ -53,7 +59,7 @@ public function checkRule(
null,
$redirectUri,
$state,
- $useFragmentInHttpErrorResponses,
+ $responseMode,
);
}
} catch (\Throwable $e) {
diff --git a/src/Server/RequestRules/Rules/ResponseModeRule.php b/src/Server/RequestRules/Rules/ResponseModeRule.php
new file mode 100644
index 00000000..34c7a485
--- /dev/null
+++ b/src/Server/RequestRules/Rules/ResponseModeRule.php
@@ -0,0 +1,116 @@
+requestParamsResolver->getAllBasedOnAllowedMethods(
+ $request,
+ $allowedServerRequestMethods,
+ );
+
+ // response_mode requires client_id to be present
+ if (
+ !isset($requestParams[ParamsEnum::ClientId->value])
+ ) {
+ throw OidcServerException::invalidRequest('Missing client_id');
+ }
+
+ $reponseModeValue = isset($requestParams[ParamsEnum::ResponseMode->value]) ?
+ (string)$requestParams[ParamsEnum::ResponseMode->value] : null;
+ $loggerService->debug('ResponseModeRule: response_mode requestParams value: ' . ($reponseModeValue ?? 'null'));
+
+
+ // if response_mode is not set, we set the default
+ // default to 'code' if not set. Error will be thrown by ResponseTypeRule.
+ $responseType = isset($requestParams[ParamsEnum::ResponseType->value]) ?
+ (string)$requestParams[ParamsEnum::ResponseType->value] : 'code';
+ if (!$reponseModeValue) {
+ $reponseModeValue = str_contains($responseType, 'token') ? 'fragment' : 'query';
+ }
+
+ // Verify if response_mode is one of 'query', 'fragment', 'form_post'
+ if (
+ !in_array(
+ $reponseModeValue,
+ ['query', 'fragment', 'form_post'],
+ true,
+ )
+ ) {
+ throw OidcServerException::invalidRequest('Invalid response_mode');
+ }
+
+ // Validate whether response_mode is allowed by client configuration
+ /** @var \SimpleSAML\Module\oidc\Entities\Interfaces\ClientEntityInterface $client */
+ $client = $currentResultBag->getOrFail(ClientRule::class)->getValue();
+ $currentResultBag->getOrFail(ClientRedirectUriRule::class)->getValue();
+ $currentResultBag->getOrFail(StateRule::class)->getValue();
+
+ $allowedResponseModes = $client->getAllowedResponseModes();
+ if (!in_array($reponseModeValue, $allowedResponseModes, true)) {
+ throw OidcServerException::invalidRequest(
+ 'response_mode',
+ 'response_mode "' . $reponseModeValue . '" is not allowed for this client',
+ );
+ }
+
+ // Resolve ResponseModeStrategy
+ switch ($reponseModeValue) {
+ case 'query':
+ $responseMode = $this->queryResponseMode;
+ break;
+ case 'fragment':
+ $responseMode = $this->fragmentResponseMode;
+ break;
+ case 'form_post':
+ $responseMode = $this->formPostResponseMode;
+ break;
+ default:
+ throw OidcServerException::invalidRequest('Unsupported response_mode. How did we get here?');
+ }
+
+ return new Result($this->getKey(), $responseMode);
+ }
+}
diff --git a/src/Server/RequestRules/Rules/ResponseTypeRule.php b/src/Server/RequestRules/Rules/ResponseTypeRule.php
index 30acb5ad..1b71a93d 100644
--- a/src/Server/RequestRules/Rules/ResponseTypeRule.php
+++ b/src/Server/RequestRules/Rules/ResponseTypeRule.php
@@ -9,6 +9,8 @@
use SimpleSAML\Module\oidc\Server\RequestRules\Interfaces\ResultBagInterface;
use SimpleSAML\Module\oidc\Server\RequestRules\Interfaces\ResultInterface;
use SimpleSAML\Module\oidc\Server\RequestRules\Result;
+use SimpleSAML\Module\oidc\Server\ResponseModes\QueryResponseMode;
+use SimpleSAML\Module\oidc\Server\ResponseModes\ResponseModeInterface;
use SimpleSAML\Module\oidc\Services\LoggerService;
use SimpleSAML\OpenID\Codebooks\HttpMethodsEnum;
use SimpleSAML\OpenID\Codebooks\ParamsEnum;
@@ -17,13 +19,16 @@ class ResponseTypeRule extends AbstractRule
{
/**
* @inheritDoc
+ *
+ * @param ResponseModeInterface $responseMode
+ * @param HttpMethodsEnum[] $allowedServerRequestMethods
*/
public function checkRule(
ServerRequestInterface $request,
ResultBagInterface $currentResultBag,
LoggerService $loggerService,
array $data = [],
- bool $useFragmentInHttpErrorResponses = false,
+ ResponseModeInterface $responseMode = new QueryResponseMode(),
array $allowedServerRequestMethods = [HttpMethodsEnum::GET],
): ?ResultInterface {
$requestParams = $this->requestParamsResolver->getAllBasedOnAllowedMethods(
diff --git a/src/Server/RequestRules/Rules/ScopeOfflineAccessRule.php b/src/Server/RequestRules/Rules/ScopeOfflineAccessRule.php
index ee4188b2..fd41cdfe 100644
--- a/src/Server/RequestRules/Rules/ScopeOfflineAccessRule.php
+++ b/src/Server/RequestRules/Rules/ScopeOfflineAccessRule.php
@@ -9,6 +9,8 @@
use SimpleSAML\Module\oidc\Server\RequestRules\Interfaces\ResultBagInterface;
use SimpleSAML\Module\oidc\Server\RequestRules\Interfaces\ResultInterface;
use SimpleSAML\Module\oidc\Server\RequestRules\Result;
+use SimpleSAML\Module\oidc\Server\ResponseModes\QueryResponseMode;
+use SimpleSAML\Module\oidc\Server\ResponseModes\ResponseModeInterface;
use SimpleSAML\Module\oidc\Services\LoggerService;
use SimpleSAML\OpenID\Codebooks\HttpMethodsEnum;
@@ -16,14 +18,17 @@ class ScopeOfflineAccessRule extends AbstractRule
{
/**
* @inheritDoc
+ *
* @throws \Throwable
+ *
+ * @param ResponseModeInterface $responseMode
*/
public function checkRule(
ServerRequestInterface $request,
ResultBagInterface $currentResultBag,
LoggerService $loggerService,
array $data = [],
- bool $useFragmentInHttpErrorResponses = false,
+ ResponseModeInterface $responseMode = new QueryResponseMode(),
array $allowedServerRequestMethods = [HttpMethodsEnum::GET],
): ?ResultInterface {
$loggerService->debug('ScopeOfflineAccessRule::checkRule');
@@ -50,7 +55,7 @@ public function checkRule(
null,
$redirectUri,
$state,
- $useFragmentInHttpErrorResponses,
+ $responseMode,
);
}
diff --git a/src/Server/RequestRules/Rules/ScopeRule.php b/src/Server/RequestRules/Rules/ScopeRule.php
index bc6b753c..2587aaee 100644
--- a/src/Server/RequestRules/Rules/ScopeRule.php
+++ b/src/Server/RequestRules/Rules/ScopeRule.php
@@ -12,6 +12,8 @@
use SimpleSAML\Module\oidc\Server\RequestRules\Interfaces\ResultBagInterface;
use SimpleSAML\Module\oidc\Server\RequestRules\Interfaces\ResultInterface;
use SimpleSAML\Module\oidc\Server\RequestRules\Result;
+use SimpleSAML\Module\oidc\Server\ResponseModes\QueryResponseMode;
+use SimpleSAML\Module\oidc\Server\ResponseModes\ResponseModeInterface;
use SimpleSAML\Module\oidc\Services\LoggerService;
use SimpleSAML\Module\oidc\Utils\RequestParamsResolver;
use SimpleSAML\OpenID\Codebooks\HttpMethodsEnum;
@@ -29,14 +31,18 @@ public function __construct(
/**
* @inheritDoc
+ *
* @throws \Throwable
+ *
+ * @param ResponseModeInterface $responseMode
+ * @param HttpMethodsEnum[] $allowedServerRequestMethods
*/
public function checkRule(
ServerRequestInterface $request,
ResultBagInterface $currentResultBag,
LoggerService $loggerService,
array $data = [],
- bool $useFragmentInHttpErrorResponses = false,
+ ResponseModeInterface $responseMode = new QueryResponseMode(),
array $allowedServerRequestMethods = [HttpMethodsEnum::GET],
): ?ResultInterface {
$loggerService->debug('ScopeRule::checkRule.');
@@ -69,7 +75,7 @@ public function checkRule(
if ($scope instanceof ScopeEntityInterface === false) {
$loggerService->error('ScopeRule: Invalid scope: ' . $scopeItem);
- throw OidcServerException::invalidScope($scopeItem, $redirectUri, $state);
+ throw OidcServerException::invalidScope($scopeItem, $redirectUri, $state, $responseMode);
}
$loggerService->debug('ScopeRule: Valid scope: ' . $scopeItem);
$validScopes[] = $scope;
diff --git a/src/Server/RequestRules/Rules/StateRule.php b/src/Server/RequestRules/Rules/StateRule.php
index d60d31d7..8f337281 100644
--- a/src/Server/RequestRules/Rules/StateRule.php
+++ b/src/Server/RequestRules/Rules/StateRule.php
@@ -8,6 +8,8 @@
use SimpleSAML\Module\oidc\Server\RequestRules\Interfaces\ResultBagInterface;
use SimpleSAML\Module\oidc\Server\RequestRules\Interfaces\ResultInterface;
use SimpleSAML\Module\oidc\Server\RequestRules\Result;
+use SimpleSAML\Module\oidc\Server\ResponseModes\QueryResponseMode;
+use SimpleSAML\Module\oidc\Server\ResponseModes\ResponseModeInterface;
use SimpleSAML\Module\oidc\Services\LoggerService;
use SimpleSAML\OpenID\Codebooks\HttpMethodsEnum;
use SimpleSAML\OpenID\Codebooks\ParamsEnum;
@@ -16,13 +18,16 @@ class StateRule extends AbstractRule
{
/**
* @inheritDoc
+ *
+ * @param ResponseModeInterface $responseMode
+ * @param HttpMethodsEnum[] $allowedServerRequestMethods
*/
public function checkRule(
ServerRequestInterface $request,
ResultBagInterface $currentResultBag,
LoggerService $loggerService,
array $data = [],
- bool $useFragmentInHttpErrorResponses = false,
+ ResponseModeInterface $responseMode = new QueryResponseMode(),
array $allowedServerRequestMethods = [HttpMethodsEnum::GET],
): ?ResultInterface {
$loggerService->debug('StateRule::checkRule');
diff --git a/src/Server/RequestRules/Rules/UiLocalesRule.php b/src/Server/RequestRules/Rules/UiLocalesRule.php
index 3bbbd3c3..4561da7b 100644
--- a/src/Server/RequestRules/Rules/UiLocalesRule.php
+++ b/src/Server/RequestRules/Rules/UiLocalesRule.php
@@ -8,6 +8,8 @@
use SimpleSAML\Module\oidc\Server\RequestRules\Interfaces\ResultBagInterface;
use SimpleSAML\Module\oidc\Server\RequestRules\Interfaces\ResultInterface;
use SimpleSAML\Module\oidc\Server\RequestRules\Result;
+use SimpleSAML\Module\oidc\Server\ResponseModes\QueryResponseMode;
+use SimpleSAML\Module\oidc\Server\ResponseModes\ResponseModeInterface;
use SimpleSAML\Module\oidc\Services\LoggerService;
use SimpleSAML\OpenID\Codebooks\HttpMethodsEnum;
use SimpleSAML\OpenID\Codebooks\ParamsEnum;
@@ -16,13 +18,16 @@ class UiLocalesRule extends AbstractRule
{
/**
* @inheritDoc
+ *
+ * @param ResponseModeInterface $responseMode
+ * @param HttpMethodsEnum[] $allowedServerRequestMethods
*/
public function checkRule(
ServerRequestInterface $request,
ResultBagInterface $currentResultBag,
LoggerService $loggerService,
array $data = [],
- bool $useFragmentInHttpErrorResponses = false,
+ ResponseModeInterface $responseMode = new QueryResponseMode(),
array $allowedServerRequestMethods = [HttpMethodsEnum::GET],
): ?ResultInterface {
return new Result($this->getKey(), $this->requestParamsResolver->getBasedOnAllowedMethods(
diff --git a/src/Server/RequestTypes/AuthorizationRequest.php b/src/Server/RequestTypes/AuthorizationRequest.php
index 1278e9f9..bc969f10 100644
--- a/src/Server/RequestTypes/AuthorizationRequest.php
+++ b/src/Server/RequestTypes/AuthorizationRequest.php
@@ -6,6 +6,7 @@
use League\OAuth2\Server\RequestTypes\AuthorizationRequest as OAuth2AuthorizationRequest;
use SimpleSAML\Module\oidc\Codebooks\FlowTypeEnum;
+use SimpleSAML\Module\oidc\Server\ResponseModes\ResponseModeInterface;
class AuthorizationRequest extends OAuth2AuthorizationRequest
{
@@ -70,6 +71,8 @@ class AuthorizationRequest extends OAuth2AuthorizationRequest
*/
protected ?string $issuerState = null;
+ private ?ResponseModeInterface $responseMode = null;
+
public static function fromOAuth2AuthorizationRequest(
OAuth2AuthorizationRequest $oAuth2authorizationRequest,
): AuthorizationRequest {
@@ -162,6 +165,16 @@ public function getResponseType(): ?string
return $this->responseType;
}
+ public function setResponseMode(ResponseModeInterface $responseMode): void
+ {
+ $this->responseMode = $responseMode;
+ }
+
+ public function getResponseMode(): ?ResponseModeInterface
+ {
+ return $this->responseMode;
+ }
+
/**
* Check if access token should be issued in authorization response (implicit flow, hybrid flow...).
* @return bool
diff --git a/src/Server/ResponseModes/FormPostResponseMode.php b/src/Server/ResponseModes/FormPostResponseMode.php
new file mode 100644
index 00000000..48da84fd
--- /dev/null
+++ b/src/Server/ResponseModes/FormPostResponseMode.php
@@ -0,0 +1,35 @@
+simpleSAMLConfiguration = $simpleSAMLConfiguration;
+ }
+
+ public function buildResponse(string $redirectUri, array $params): AbstractResponseType
+ {
+ $template = new Template($this->simpleSAMLConfiguration, 'oidc:formpost.twig');
+ $template->data = [
+ 'redirectUri' => $redirectUri,
+ 'params' => $params,
+ ];
+ $html = $template->getContents(); // renders to a string
+
+ $response = new HtmlResponse();
+ $response->setHtml($html);
+ return $response;
+ }
+}
diff --git a/src/Server/ResponseModes/FragmentResponseMode.php b/src/Server/ResponseModes/FragmentResponseMode.php
new file mode 100644
index 00000000..b8e40652
--- /dev/null
+++ b/src/Server/ResponseModes/FragmentResponseMode.php
@@ -0,0 +1,20 @@
+setRedirectUri($redirectUri . $separator . http_build_query($params));
+
+ return $response;
+ }
+}
diff --git a/src/Server/ResponseModes/QueryResponseMode.php b/src/Server/ResponseModes/QueryResponseMode.php
new file mode 100644
index 00000000..2a379447
--- /dev/null
+++ b/src/Server/ResponseModes/QueryResponseMode.php
@@ -0,0 +1,20 @@
+setRedirectUri($redirectUri . $separator . http_build_query($params));
+
+ return $response;
+ }
+}
diff --git a/src/Server/ResponseModes/ResponseModeInterface.php b/src/Server/ResponseModes/ResponseModeInterface.php
new file mode 100644
index 00000000..529e4824
--- /dev/null
+++ b/src/Server/ResponseModes/ResponseModeInterface.php
@@ -0,0 +1,12 @@
+html = $html;
+ }
+
+ /**
+ * @param ResponseInterface $response
+ *
+ * @return ResponseInterface
+ */
+ public function generateHttpResponse(ResponseInterface $response)
+ {
+ $response->getBody()->write($this->html);
+
+ return $response->withStatus(200)->withHeader('Content-Type', 'text/html');
+ }
+}
diff --git a/src/Services/Container.php b/src/Services/Container.php
index d03173b5..566f094c 100644
--- a/src/Services/Container.php
+++ b/src/Services/Container.php
@@ -92,12 +92,16 @@
use SimpleSAML\Module\oidc\Server\RequestRules\Rules\RequestObjectRule;
use SimpleSAML\Module\oidc\Server\RequestRules\Rules\RequiredNonceRule;
use SimpleSAML\Module\oidc\Server\RequestRules\Rules\RequiredOpenIdScopeRule;
+use SimpleSAML\Module\oidc\Server\RequestRules\Rules\ResponseModeRule;
use SimpleSAML\Module\oidc\Server\RequestRules\Rules\ResponseTypeRule;
use SimpleSAML\Module\oidc\Server\RequestRules\Rules\ScopeOfflineAccessRule;
use SimpleSAML\Module\oidc\Server\RequestRules\Rules\ScopeRule;
use SimpleSAML\Module\oidc\Server\RequestRules\Rules\StateRule;
use SimpleSAML\Module\oidc\Server\RequestRules\Rules\UiLocalesRule;
use SimpleSAML\Module\oidc\Server\ResourceServer;
+use SimpleSAML\Module\oidc\Server\ResponseModes\FormPostResponseMode;
+use SimpleSAML\Module\oidc\Server\ResponseModes\FragmentResponseMode;
+use SimpleSAML\Module\oidc\Server\ResponseModes\QueryResponseMode;
use SimpleSAML\Module\oidc\Server\ResponseTypes\TokenResponse;
use SimpleSAML\Module\oidc\Server\TokenIssuers\RefreshTokenIssuer;
use SimpleSAML\Module\oidc\Server\Validators\BearerTokenValidator;
@@ -424,6 +428,11 @@ public function __construct()
);
$this->services[AuthenticatedOAuth2ClientResolver::class] = $authenticatedOAuth2ClientResolver;
+ $queryResponseMode = new QueryResponseMode();
+ $fragmentResponseMode = new FragmentResponseMode();
+ // FormPostResponseMode renders a template, so it requires the configuration.
+ $formPostResponseMode = new FormPostResponseMode($simpleSAMLConfiguration);
+
$requestRules = [
new StateRule($requestParamsResolver, $helpers),
new ClientRule(
@@ -440,6 +449,13 @@ public function __construct()
),
new ClientRedirectUriRule($requestParamsResolver, $helpers, $moduleConfig),
new RequestObjectRule($requestParamsResolver, $helpers, $jwksResolver),
+ new ResponseModeRule(
+ $requestParamsResolver,
+ $helpers,
+ $queryResponseMode,
+ $fragmentResponseMode,
+ $formPostResponseMode,
+ ),
new PromptRule($requestParamsResolver, $helpers, $authSimpleFactory, $authenticationService, $sspBridge),
new MaxAgeRule($requestParamsResolver, $helpers, $authSimpleFactory, $authenticationService, $sspBridge),
new ScopeRule($requestParamsResolver, $helpers, $scopeRepository),
diff --git a/src/Services/OpMetadataService.php b/src/Services/OpMetadataService.php
index 91537d7f..5b3eaa48 100644
--- a/src/Services/OpMetadataService.php
+++ b/src/Services/OpMetadataService.php
@@ -100,6 +100,8 @@ private function initMetadata(): void
$this->metadata[ClaimsEnum::ClaimsSupported->value] = $claimsSupported;
}
+ $this->metadata[ClaimsEnum::ResponseModesSupported->value] = ['query', 'fragment', 'form_post'];
+
// https://openid.net/specs/openid-4-verifiable-credential-issuance-1_0.html#name-oauth-20-authorization-serv
// OPTIONAL
// pre-authorized_grant_anonymous_access_supported // TODO mivanci Make configurable
diff --git a/src/Utils/Routes.php b/src/Utils/Routes.php
index ab37629d..68791e1e 100644
--- a/src/Utils/Routes.php
+++ b/src/Utils/Routes.php
@@ -53,7 +53,7 @@ public function newResponse(
}
public function newJsonResponse(
- mixed $data = null,
+ array|null $data = null,
int $status = 200,
array $headers = [],
bool $json = false,
diff --git a/templates/clients/includes/form.twig b/templates/clients/includes/form.twig
index 51b1a869..1926a7b0 100644
--- a/templates/clients/includes/form.twig
+++ b/templates/clients/includes/form.twig
@@ -150,6 +150,15 @@
{% endif %}
+
+ {{ form.response_modes_allowed.control | raw }}
+
+ {% if form.response_modes_allowed.hasErrors %}
+
+ {% endif %}
+