vendor/league/oauth2-server-bundle/src/Security/Authenticator/OAuth2Authenticator.php line 106

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace League\Bundle\OAuth2ServerBundle\Security\Authenticator;
  4. use League\Bundle\OAuth2ServerBundle\Security\Authentication\Token\OAuth2Token;
  5. use League\Bundle\OAuth2ServerBundle\Security\Exception\OAuth2AuthenticationException;
  6. use League\Bundle\OAuth2ServerBundle\Security\Exception\OAuth2AuthenticationFailedException;
  7. use League\Bundle\OAuth2ServerBundle\Security\Passport\Badge\ScopeBadge;
  8. use League\Bundle\OAuth2ServerBundle\Security\User\NullUser;
  9. use League\OAuth2\Server\Exception\OAuthServerException;
  10. use League\OAuth2\Server\ResourceServer;
  11. use Symfony\Bridge\PsrHttpMessage\HttpMessageFactoryInterface;
  12. use Symfony\Component\HttpFoundation\Request;
  13. use Symfony\Component\HttpFoundation\Response;
  14. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  15. use Symfony\Component\Security\Core\Exception\AuthenticationException;
  16. use Symfony\Component\Security\Core\User\UserInterface;
  17. use Symfony\Component\Security\Core\User\UserProviderInterface;
  18. use Symfony\Component\Security\Http\Authenticator\AuthenticatorInterface;
  19. use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
  20. use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
  21. use Symfony\Component\Security\Http\Authenticator\Passport\PassportInterface;
  22. use Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPassport;
  23. use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
  24. /**
  25.  * @author Mathias Arlaud <mathias.arlaud@gmail.com>
  26.  */
  27. final class OAuth2Authenticator implements AuthenticatorInterfaceAuthenticationEntryPointInterface
  28. {
  29.     /**
  30.      * @psalm-suppress UndefinedTrait
  31.      * @psalm-suppress MethodSignatureMismatch
  32.      */
  33.     use ForwardCompatAuthenticatorTrait;
  34.     /**
  35.      * @var HttpMessageFactoryInterface
  36.      */
  37.     private $httpMessageFactory;
  38.     /**
  39.      * @var ResourceServer
  40.      */
  41.     private $resourceServer;
  42.     /**
  43.      * @var UserProviderInterface
  44.      */
  45.     private $userProvider;
  46.     /**
  47.      * @var string
  48.      */
  49.     private $rolePrefix;
  50.     public function __construct(
  51.         HttpMessageFactoryInterface $httpMessageFactory,
  52.         ResourceServer $resourceServer,
  53.         UserProviderInterface $userProvider,
  54.         string $rolePrefix
  55.     ) {
  56.         $this->httpMessageFactory $httpMessageFactory;
  57.         $this->resourceServer $resourceServer;
  58.         $this->userProvider $userProvider;
  59.         $this->rolePrefix $rolePrefix;
  60.     }
  61.     public function supports(Request $request): ?bool
  62.     {
  63.         return === strpos($request->headers->get('Authorization'''), 'Bearer ');
  64.     }
  65.     public function start(Request $requestAuthenticationException $authException null): Response
  66.     {
  67.         return new Response(''401, ['WWW-Authenticate' => 'Bearer']);
  68.     }
  69.     /**
  70.      * {@inheritdoc}
  71.      *
  72.      * @return Passport
  73.      */
  74.     public function doAuthenticate(Request $request/* : Passport */
  75.     {
  76.         try {
  77.             $psr7Request $this->resourceServer->validateAuthenticatedRequest($this->httpMessageFactory->createRequest($request));
  78.         } catch (OAuthServerException $e) {
  79.             throw OAuth2AuthenticationFailedException::create('The resource server rejected the request.'$e);
  80.         }
  81.         /** @var string $userIdentifier */
  82.         $userIdentifier $psr7Request->getAttribute('oauth_user_id''');
  83.         /** @var string $accessTokenId */
  84.         $accessTokenId $psr7Request->getAttribute('oauth_access_token_id');
  85.         /** @var list<string> $scopes */
  86.         $scopes $psr7Request->getAttribute('oauth_scopes', []);
  87.         /** @var string $oauthClientId */
  88.         $oauthClientId $psr7Request->getAttribute('oauth_client_id''');
  89.         $userLoader = function (string $userIdentifier): UserInterface {
  90.             if ('' === $userIdentifier) {
  91.                 return new NullUser();
  92.             }
  93.             if (!method_exists($this->userProvider'loadUserByIdentifier')) {
  94.                 /** @psalm-suppress DeprecatedMethod */
  95.                 return $this->userProvider->loadUserByUsername($userIdentifier);
  96.             }
  97.             return $this->userProvider->loadUserByIdentifier($userIdentifier);
  98.         };
  99.         $passport = new SelfValidatingPassport(new UserBadge($userIdentifier$userLoader), [
  100.             new ScopeBadge($scopes),
  101.         ]);
  102.         $passport->setAttribute('accessTokenId'$accessTokenId);
  103.         $passport->setAttribute('oauthClientId'$oauthClientId);
  104.         return $passport;
  105.     }
  106.     /**
  107.      * @return OAuth2Token
  108.      *
  109.      * @psalm-suppress DeprecatedClass
  110.      */
  111.     public function createAuthenticatedToken(PassportInterface $passportstring $firewallName): TokenInterface
  112.     {
  113.         if (!$passport instanceof Passport) {
  114.             throw new \RuntimeException(sprintf('Cannot create a OAuth2 authenticated token. $passport should be a %s'Passport::class));
  115.         }
  116.         $token $this->createToken($passport$firewallName);
  117.         $token->setAuthenticated(true);
  118.         return $token;
  119.     }
  120.     /**
  121.      * @return OAuth2Token
  122.      */
  123.     public function createToken(Passport $passportstring $firewallName): TokenInterface
  124.     {
  125.         /** @var string $accessTokenId */
  126.         $accessTokenId $passport->getAttribute('accessTokenId');
  127.         /** @var ScopeBadge $scopeBadge */
  128.         $scopeBadge $passport->getBadge(ScopeBadge::class);
  129.         /** @var string $oauthClientId */
  130.         $oauthClientId $passport->getAttribute('oauthClientId''');
  131.         $token = new OAuth2Token($passport->getUser(), $accessTokenId$oauthClientId$scopeBadge->getScopes(), $this->rolePrefix);
  132.         if (method_exists(AuthenticatorInterface::class, 'createAuthenticatedToken') && !method_exists(AuthenticatorInterface::class, 'createToken')) {
  133.             // symfony 5.4 only
  134.             /** @psalm-suppress TooManyArguments */
  135.             $token->setAuthenticated(truefalse);
  136.         }
  137.         return $token;
  138.     }
  139.     public function onAuthenticationSuccess(Request $requestTokenInterface $tokenstring $firewallName): ?Response
  140.     {
  141.         return null;
  142.     }
  143.     public function onAuthenticationFailure(Request $requestAuthenticationException $exception): ?Response
  144.     {
  145.         if ($exception instanceof OAuth2AuthenticationException) {
  146.             return new Response($exception->getMessage(), $exception->getStatusCode(), $exception->getHeaders());
  147.         }
  148.         throw $exception;
  149.     }
  150. }