getRequestUri(), '/api/')) { if (str_contains($request->getRequestUri(), '/api/doc')) { return false; } if ($request->headers->has(self::HEADER_USERNAME) && $request->headers->has(self::HEADER_TOKEN)) { @trigger_error('You are using deprecated API access, please upgrade your APP to use API tokens instead.', E_USER_DEPRECATED); return true; } } return false; } private function getCredentials(Request $request): array { $apiUser = $request->headers->get(self::HEADER_USERNAME); if (null === $apiUser || '' === $apiUser) { throw new CustomUserMessageAuthenticationException('Authentication required, missing user header: ' . self::HEADER_USERNAME); } $apiToken = $request->headers->get(self::HEADER_TOKEN); if (null === $apiToken || '' === $apiToken) { throw new CustomUserMessageAuthenticationException('Authentication required, missing token header: ' . self::HEADER_TOKEN); } return [ 'username' => $apiUser, 'password' => $apiToken ]; } public function authenticate(Request $request): Passport { $credentials = $this->getCredentials($request); $checkCredentials = function (?string $presentedPassword, User $user) { if ('' === $presentedPassword) { throw new BadCredentialsException('The presented password cannot be empty.'); } if (null === $user->getApiToken()) { throw new BadCredentialsException('The user has no activated API account.'); } if ($this->passwordHasherFactory->getPasswordHasher($user)->verify($user->getApiToken(), $presentedPassword)) { return true; } throw new BadCredentialsException('The presented password is invalid.'); }; $passport = new Passport( new UserBadge($credentials['username'], [$this->userProvider, 'loadUserByIdentifier']), new CustomCredentials($checkCredentials, $credentials['password']) ); $passport->addBadge(new ApiTokenUpgradeBadge($credentials['password'], $this->userProvider)); return $passport; } public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response { return null; } public function onAuthenticationFailure(Request $request, AuthenticationException $exception): Response { $data = [ 'message' => $exception instanceof CustomUserMessageAuthenticationException ? $exception->getMessage() : 'Invalid credentials' ]; return new JsonResponse($data, Response::HTTP_FORBIDDEN); } }