diff --git a/src/Exception/OAuthServerException.php b/src/Exception/OAuthServerException.php index 8e628baa..60e42a6b 100644 --- a/src/Exception/OAuthServerException.php +++ b/src/Exception/OAuthServerException.php @@ -294,14 +294,9 @@ class OAuthServerException extends Exception $payload = $this->getPayload(); - if ($this->redirectUri !== null) { - if ($useFragment === true) { - $this->redirectUri .= (strstr($this->redirectUri, '#') === false) ? '#' : '&'; - } else { - $this->redirectUri .= (strstr($this->redirectUri, '?') === false) ? '?' : '&'; - } - - return $response->withStatus(302)->withHeader('Location', $this->redirectUri . http_build_query($payload)); + $redirectUri = $this->getRedirectUri($useFragment); + if ($redirectUri !== null) { + return $response->withStatus(302)->withHeader('Location', $redirectUri); } foreach ($headers as $header => $content) { @@ -359,6 +354,31 @@ class OAuthServerException extends Exception return $this->redirectUri !== null; } + /** + * Returns the redirectUri with all necessary args. + * + * Null will be returned if the exception doesn't contain the redirectUri. + * + * @param bool $useFragment True if errors should be in the URI fragment instead of query string + * + * @return string|null + */ + public function getRedirectUri(bool $useFragment = false): ?string + { + if ($this->redirectUri === null) { + return null; + } + + $redirectUri = $this->redirectUri; + if ($useFragment) { + $redirectUri .= strpos($this->redirectUri, '#') === false ? '#' : '&'; + } else { + $redirectUri .= strpos($this->redirectUri, '?') === false ? '?' : '&'; + } + + return $redirectUri . http_build_query($this->getPayload()); + } + /** * Returns the HTTP status code to send when the exceptions is output. * diff --git a/tests/Exception/OAuthServerExceptionTest.php b/tests/Exception/OAuthServerExceptionTest.php index eb2b2ad3..2016c631 100644 --- a/tests/Exception/OAuthServerExceptionTest.php +++ b/tests/Exception/OAuthServerExceptionTest.php @@ -71,6 +71,14 @@ class OAuthServerExceptionTest extends TestCase $exceptionWithRedirect = OAuthServerException::accessDenied('some hint', 'https://example.com/error'); $this->assertTrue($exceptionWithRedirect->hasRedirect()); + $this->assertSame( + 'https://example.com/error?error=access_denied&error_description=The+resource+owner+or+authorization+server+denied+the+request.&hint=some+hint&message=The+resource+owner+or+authorization+server+denied+the+request.', + $exceptionWithRedirect->getRedirectUri() + ); + $this->assertSame( + 'https://example.com/error#error=access_denied&error_description=The+resource+owner+or+authorization+server+denied+the+request.&hint=some+hint&message=The+resource+owner+or+authorization+server+denied+the+request.', + $exceptionWithRedirect->getRedirectUri(true) + ); } public function testDoesNotHaveRedirect() @@ -78,6 +86,7 @@ class OAuthServerExceptionTest extends TestCase $exceptionWithoutRedirect = OAuthServerException::accessDenied('Some hint'); $this->assertFalse($exceptionWithoutRedirect->hasRedirect()); + $this->assertNull($exceptionWithoutRedirect->getRedirectUri()); } public function testHasPrevious()