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

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