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
22class 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}