diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/security_authenticator_access_token.php b/src/Symfony/Bundle/SecurityBundle/Resources/config/security_authenticator_access_token.php index 66716b23ad89..bf9655307c56 100644 --- a/src/Symfony/Bundle/SecurityBundle/Resources/config/security_authenticator_access_token.php +++ b/src/Symfony/Bundle/SecurityBundle/Resources/config/security_authenticator_access_token.php @@ -42,6 +42,7 @@ null, null, ]) + ->call('setTranslator', [service('translator')->ignoreOnInvalid()]) ->set('security.authenticator.access_token.chain_extractor', ChainAccessTokenExtractor::class) ->abstract() diff --git a/src/Symfony/Component/Security/Http/Authenticator/AccessTokenAuthenticator.php b/src/Symfony/Component/Security/Http/Authenticator/AccessTokenAuthenticator.php index 40494f1e606a..b26f76fc36cf 100644 --- a/src/Symfony/Component/Security/Http/Authenticator/AccessTokenAuthenticator.php +++ b/src/Symfony/Component/Security/Http/Authenticator/AccessTokenAuthenticator.php @@ -84,6 +84,9 @@ public function onAuthenticationFailure(Request $request, AuthenticationExceptio if (null !== $this->translator) { $errorMessage = $this->translator->trans($exception->getMessageKey(), $exception->getMessageData(), 'security'); + if (preg_match('/[^\x00-\x7F]/', $errorMessage)) { + trigger_deprecation('symfony/security-http', '6.4', 'Using non-ASCII characters in the error message is deprecated. Use ASCII characters only.'); + } } else { $errorMessage = strtr($exception->getMessageKey(), $exception->getMessageData()); } diff --git a/src/Symfony/Component/Security/Http/Tests/Authenticator/AccessTokenAuthenticatorTest.php b/src/Symfony/Component/Security/Http/Tests/Authenticator/AccessTokenAuthenticatorTest.php index 5ee4869b431a..e5d6e66ff79c 100644 --- a/src/Symfony/Component/Security/Http/Tests/Authenticator/AccessTokenAuthenticatorTest.php +++ b/src/Symfony/Component/Security/Http/Tests/Authenticator/AccessTokenAuthenticatorTest.php @@ -13,6 +13,7 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Security\Core\Exception\BadCredentialsException; use Symfony\Component\Security\Core\User\InMemoryUser; use Symfony\Component\Security\Core\User\InMemoryUserProvider; @@ -22,6 +23,7 @@ use Symfony\Component\Security\Http\Authenticator\AccessTokenAuthenticator; use Symfony\Component\Security\Http\Authenticator\FallbackUserLoader; use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge; +use Symfony\Contracts\Translation\TranslatorInterface; class AccessTokenAuthenticatorTest extends TestCase { @@ -36,6 +38,82 @@ protected function setUp(): void $this->userProvider = new InMemoryUserProvider(['test' => ['password' => 's$cr$t']]); } + public function testOnAuthenticationFailureWithTranslatorTranslatesErrorMessage() + { + $request = Request::create('/test'); + + $this->accessTokenExtractor + ->expects($this->once()) + ->method('extractAccessToken') + ->with($request) + ->willReturn(null); + + $authenticator = new AccessTokenAuthenticator( + $this->accessTokenHandler, + $this->accessTokenExtractor, + $this->userProvider, + ); + + $translator = $this->createMock(TranslatorInterface::class); + $translator + ->expects($this->once()) + ->method('trans') + ->with('Invalid credentials.') + ->willReturn('Credenciales invalidas.'); + + $authenticator->setTranslator($translator); + + $response = null; + try { + $authenticator->authenticate($request); + } catch (BadCredentialsException $e) { + $response = $authenticator->onAuthenticationFailure($request, $e); + } + $this->assertInstanceOf(Response::class, $response); + $this->assertSame('Bearer error="invalid_token",error_description="Credenciales invalidas."', $response->headers->get('WWW-Authenticate')); + } + + /** + * @group legacy + * + * @expectedDeprecation Since symfony/security-http 6.4: Using non-ASCII characters in the error message is deprecated. Use ASCII characters only. + */ + public function testOnAuthenticationFailureWithTranslatorThrowsDeprecationWhenTranslatedMessageContainsNonAscii() + { + $request = Request::create('/test'); + + $this->accessTokenExtractor + ->expects($this->once()) + ->method('extractAccessToken') + ->with($request) + ->willReturn(null); + + $authenticator = new AccessTokenAuthenticator( + $this->accessTokenHandler, + $this->accessTokenExtractor, + $this->userProvider, + ); + + $nonAsciiString = 'Credenciales inválidas.'; + $translator = $this->createMock(TranslatorInterface::class); + $translator + ->expects($this->once()) + ->method('trans') + ->with('Invalid credentials.') + ->willReturn($nonAsciiString); + + $authenticator->setTranslator($translator); + + $response = null; + try { + $authenticator->authenticate($request); + } catch (BadCredentialsException $e) { + $response = $authenticator->onAuthenticationFailure($request, $e); + } + $this->assertInstanceOf(Response::class, $response); + $this->assertSame('Bearer error="invalid_token",error_description="Credenciales inválidas."', $response->headers->get('WWW-Authenticate')); + } + public function testAuthenticateWithoutAccessToken() { $this->expectException(BadCredentialsException::class);