src/BackendBundle/Security/Authenticator/OAuth2Authenticator.php line 45

Open in your IDE?
  1. <?php
  2. namespace App\BackendBundle\Security\Authenticator;
  3. use Psr\Log\LoggerInterface;
  4. use Symfony\Component\HttpFoundation\Request;
  5. use Symfony\Component\HttpFoundation\RequestStack;
  6. use Symfony\Component\HttpFoundation\Response;
  7. use Symfony\Component\HttpFoundation\RedirectResponse;
  8. use Symfony\Component\HttpFoundation\Session\SessionInterface;
  9. use Symfony\Component\Routing\RouterInterface;
  10. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  11. use Symfony\Component\Security\Core\Exception\AuthenticationException;
  12. use Symfony\Component\Security\Core\Exception\CustomUserMessageAuthenticationException;
  13. use Symfony\Component\Security\Core\Security;
  14. use Symfony\Component\Security\Http\Authenticator\AbstractLoginFormAuthenticator;
  15. use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
  16. use Symfony\Component\Security\Http\Authenticator\Passport\Credentials\PasswordCredentials;
  17. use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
  18. use Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPassport;
  19. class OAuth2Authenticator extends AbstractLoginFormAuthenticator {
  20.     private LoggerInterface $logger;
  21.     private RequestStack $requestStack;
  22.     private RouterInterface $router;
  23.     private SessionInterface $session;
  24.     private $sessionOAuthKey 'oauth2_session_username';
  25.     private $sessionEmail 'oauth2_session_email';
  26.     public function __construct(LoggerInterface $loggerRouterInterface $routerRequestStack $requestStack) {
  27.         $this->logger $logger;
  28.         $this->requestStack $requestStack;
  29.         $this->session $this->requestStack->getSession();
  30.         $this->router $router;
  31.     }
  32.     public function supports(Request $request): bool {
  33.         /*
  34.          * Important !!!
  35.          * The sessionOAuthKey contains the username after login success and 
  36.          * the symfony authenticator is called before the AuthorizationRequestResolverListener
  37.          * which access the TokenStorage
  38.          */
  39.         if ($this->session->has($this->sessionOAuthKey)) {
  40.             return true;
  41.         }
  42.         if (!$request->isMethod('POST')) {
  43.             return false;
  44.         }
  45.         $loginUrl $this->router->generate('oauth2_login'); // need to create url without parameter
  46.         $fullPath $request->getBaseUrl() . $request->getPathInfo();
  47.         if ($loginUrl !== $fullPath) {
  48.             return false;
  49.         }
  50.         return true;
  51.     }
  52.     protected function getLoginUrl(Request $request): string {
  53.         $parameters $request->query->all();
  54.         return $this->router->generate('oauth2_login'$parameters);
  55.     }
  56.     public function authenticate(Request $request): Passport {
  57.         $userIdentifier $this->session->get($this->sessionOAuthKey);
  58.         if (empty($userIdentifier)) {
  59.             return $this->passportLoginForm($request);
  60.         } else {
  61.             return new SelfValidatingPassport(new UserBadge($userIdentifier));
  62.         }
  63.     }
  64.     private function passportLoginForm(Request $request) {
  65.         $email $request->request->get('email''');
  66.         $plaintextPassword $request->request->get('password''');
  67.         if (empty($email) || empty($plaintextPassword)) {
  68.             throw new CustomUserMessageAuthenticationException('Benutzername oder Passwort wurden nicht ausgefüllt.');
  69.         }
  70.         $request->getSession()->set($this->sessionEmail$email);
  71.         return new Passport(new UserBadge($email), new PasswordCredentials($plaintextPassword));
  72.     }
  73.     public function onAuthenticationSuccess(Request $requestTokenInterface $tokenstring $firewallName): ?Response {
  74.         $request->getSession()->remove(Security::AUTHENTICATION_ERROR);
  75.         if ($this->session->has($this->sessionOAuthKey)) {
  76.             // on success, let the request continue
  77.             return null;
  78.         }
  79.         /* get username and set in session */
  80.         $userName $token->getUser()->getUsername();
  81.         $this->session->set($this->sessionOAuthKey$userName);
  82.         /* redirect back to oauth2 server */
  83.         $parameters $request->query->all();
  84.         $url $this->router->generate('oauth2_authorize'$parameters);
  85.         return new RedirectResponse($url);
  86.     }
  87.     public function onAuthenticationFailure(Request $requestAuthenticationException $exception): Response {
  88.         if ($request->hasSession()) {
  89.             $request->getSession()->set(Security::AUTHENTICATION_ERROR$exception);
  90.         }
  91.         $this->session->remove($this->sessionOAuthKey);
  92.         $parameters $request->query->all();
  93.         $url $this->router->generate('oauth2_login'$parameters);
  94.         return new RedirectResponse($url);
  95.     }
  96. }