Lines
78.37%
29 / 37
Methods
83.33%
5 / 6
Classes
0.00%
0 / 1
| Name | Lines | Methods | CRAP | ||||
|---|---|---|---|---|---|---|---|
| __construct | 100.00% | 1 / 1 | 100.00% | 1 / 1 | 1 | ||
| supports | 100.00% | 1 / 1 | 100.00% | 1 / 1 | 1 | ||
| authenticate | 27.27% | 3 / 11 | 0.00% | 0 / 1 | 10.15 | ||
| onAuthenticationSuccess | 100.00% | 6 / 6 | 100.00% | 1 / 1 | 2 | ||
| onAuthenticationFailure | 100.00% | 7 / 7 | 100.00% | 1 / 1 | 1 | ||
| getUser | 100.00% | 11 / 11 | 100.00% | 1 / 1 | 2 | ||
| 22 | class GoogleIdentityAuthenticator extends AbstractAuthenticator | |
| 23 | { | |
| 24 | use TargetPathTrait; | |
| 25 | ||
| 26 | public function __construct( | |
| 27 | private readonly GoogleIdTokenVerifierInterface $idTokenVerifier, | |
| 28 | private readonly UserRepository $userRepository, | |
| 29 | private readonly EntityManagerInterface $entityManager, | |
| 30 | private readonly UrlGeneratorInterface $urlGenerator, | |
| 31 | ) { | |
| 32 | } | |
| 33 | ||
| 34 | #[\Override] | |
| 35 | public function supports(Request $request): bool | |
| 36 | { | |
| 37 | return '/connect/google/verify' === $request->getPathInfo(); | |
| 38 | } | |
| 39 | ||
| 40 | #[\Override] | |
| 41 | public function authenticate(Request $request): Passport | |
| 42 | { | |
| 43 | $idToken = (string) $request->request->get('credential'); | |
| 44 | ||
| 45 | if ('' === $idToken || '0' === $idToken) { | |
| 46 | throw new AuthenticationException('Missing credentials :('); | |
| 47 | } | |
| 48 | ||
| 49 | $payload = $this->idTokenVerifier->verify($idToken); | |
| 50 | ||
| 51 | if (null === $payload) { | |
| 52 | throw new AuthenticationException('Invalid ID token :('); | |
| 53 | } | |
| 54 | ||
| 55 | $user = $this->getUser(new GoogleUser($payload)); | |
| 56 | ||
| 57 | return new SelfValidatingPassport( | |
| 58 | new UserBadge($user->getUserIdentifier()), | |
| 59 | [new RememberMeBadge()], | |
| 60 | ); | |
| 61 | } | |
| 62 | ||
| 63 | #[\Override] | |
| 64 | public function onAuthenticationSuccess( | |
| 65 | Request $request, | |
| 66 | TokenInterface $token, | |
| 67 | string $firewallName | |
| 68 | ): RedirectResponse { | |
| 69 | if ($targetPath = $this->getTargetPath( | |
| 70 | $request->getSession(), | |
| 71 | $firewallName | |
| 72 | ) | |
| 73 | ) { | |
| 74 | return new RedirectResponse($targetPath); | |
| 75 | } | |
| 76 | ||
| 77 | return new RedirectResponse($this->urlGenerator->generate('app_default')); | |
| 78 | } | |
| 79 | ||
| 80 | #[\Override] | |
| 81 | public function onAuthenticationFailure( | |
| 82 | Request $request, | |
| 83 | AuthenticationException $exception | |
| 84 | ): RedirectResponse { | |
| 85 | $message = \strtr( | |
| 86 | $exception->getMessageKey(), | |
| 87 | $exception->getMessageData() | |
| 88 | ); | |
| 89 | ||
| 90 | /** | |
| 91 | * @var Session $session | |
| 92 | */ | |
| 93 | $session = $request->getSession(); | |
| 94 | $session->getFlashBag()->add('danger', $message); | |
| 95 | ||
| 96 | return new RedirectResponse($this->urlGenerator->generate('app_login')); | |
| 97 | } | |
| 98 | ||
| 99 | private function getUser(GoogleUser $googleUser): User | |
| 100 | { | |
| 101 | $user = $this->userRepository->findOneBy( | |
| 102 | ['googleId' => $googleUser->getId()] | |
| 103 | ); | |
| 104 | ||
| 105 | if (null !== $user) { | |
| 106 | return $user; | |
| 107 | } | |
| 108 | ||
| 109 | // Link to existing account with same email, or register a new user | |
| 110 | $user = $this->userRepository->findOneBy(['identifier' => $googleUser->getEmail()]) | |
| 111 | ?? new User()->setIdentifier((string) $googleUser->getEmail()); | |
| 112 | ||
| 113 | $user->setGoogleId((string) $googleUser->getId()); | |
| 114 | ||
| 115 | $this->entityManager->persist($user); | |
| 116 | $this->entityManager->flush(); | |
| 117 | ||
| 118 | return $user; | |
| 119 | } | |
| 120 | } |