You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I am developing a REST API with API Platform and I am finishing implementing OAuth with Google but I am getting the error that the title says. I have seen this problem in other threads but in my case and since it is an API, I do not have a front-end to redirect yet, but I don't know if that is really the problem.
I have divided my implementation into 3 classes: Client > Service > Controller. Below I leave the code and my configuration. (I will skip the class imports to not make it so long).
CLIENT
class GoogleClient
{
private Google $client;
public function __construct(
string $clientId,
string $clientSecret)
{
$this->client = new Google([
'clientId' => $clientId,
'clientSecret' => $clientSecret,
'redirectUri' => 'http://localhost:250/api/v1/users/google/oauth',
]);
}
/**
* @throws IdentityProviderException
*/
public function getAccessToken(string $grant = 'authorization_code', array $options = []): AccessToken
{
return $this->client->getAccessToken($grant, $options);
}
public function getUserInfo(AccessToken $accessToken): array
{
$resourceOwner = $this->client->getResourceOwner($accessToken);
return $resourceOwner->toArray();
}
}
SERVICE
The "authorize" function is the function that is responsible for checking if a user exists in the database. If it does not exist, it creates it and in any case, returns a JSON token with which to authenticate.
class GoogleService extends OAuth2Authenticator implements AuthenticationEntrypointInterface
{
private ClientRegistry $clientRegistry;
private EncoderService $encoderService;
private GoogleClient $googleClient;
private JWTTokenManagerInterface $JWTTokenManager;
private UserRepository $userRepository;
public function __construct(
ClientRegistry $clientRegistry,
EncoderService $encoderService,
GoogleClient $googleClient,
JWTTokenManagerInterface $JWTTokenManager,
UserRepository $userRepository
)
{
$this->clientRegistry = $clientRegistry;
$this->encoderService = $encoderService;
$this->googleClient = $googleClient;
$this->JWTTokenManager = $JWTTokenManager;
$this->userRepository = $userRepository;
}
/**
* @throws OptimisticLockException
* @throws ORMException
*/
public function authorize(string $code): string
{
try {
$accessToken = $this->googleClient->getAccessToken('authorization_code', ['code' => $code]);
$userProfile = $this->googleClient->getUserInfo($accessToken);
} catch (Exception $exception) {
throw new BadRequestHttpException(sprintf('Google error. Message: %s', $exception->getMessage()));
}
$googleEmail = $userProfile['email'] ?? null;
$googleName = $userProfile['name'] ?? null;
if (null === $googleEmail) {
throw new BadRequestHttpException('Google account without E-Mail.');
}
try {
$user = $this->userRepository->findOneByEmailOrFail($googleEmail);
} catch (UserNotFoundException) {
$user = $this->createUser($googleName, $googleEmail);
}
return $this->JWTTokenManager->create($user);
}
/**
* @throws OptimisticLockException
* @throws ORMException
*/
private function createUser(string $name, string $email): User
{
$user = new User($name, $email);
$user->setPassword($this->encoderService->generateEncodedPassword($user, \sha1(\uniqid())));
$user->setActive(true);
$user->setToken(null);
$this->userRepository->save($user);
return $user;
}
public function supports(Request $request): ?bool
{
return $request->attributes->get('_route') === 'google_oauth';
}
public function authenticate(Request $request): SelfValidatingPassport
{
$client = $this->clientRegistry->getClient('google');
$accessToken = $this->fetchAccessToken($client);
return new SelfValidatingPassport(
new UserBadge($accessToken->getToken(), function() use ($accessToken, $client) {
return $client->fetchUserFromToken($accessToken);
})
);
}
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?JsonResponse
{
$user = $token->getUser();
$userToken = $this->JWTTokenManager->create($user);
return new JsonResponse(
['token' => $userToken]
);
}
public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?JsonResponse
{
$message = strtr($exception->getMessageKey(), $exception->getMessageData());
return new JsonResponse(
$message, Response::HTTP_INTERNAL_SERVER_ERROR
);
}
public function start(Request $request, AuthenticationException $authException = null): ?JsonResponse
{
$message = strtr($authException->getMessageKey(), $authException->getMessageData());
return new JsonResponse(
$message, Response::HTTP_FORBIDDEN
);
}
}
CONTROLLER
#[AsController]
class Authorization
{
private GoogleService $googleService;
public function __construct(GoogleService $googleService)
{
$this->googleService = $googleService;
}
public function __invoke(Request $request): JsonResponse
{
$code = $request->query->get('code');
if (!$code) {
return new JsonResponse(
['error' => 'Authorization code not provided.'],
Response::HTTP_FORBIDDEN
);
}
try {
$token = $this->googleService->authorize($code);
return new JsonResponse(
['token' => $token]
);
} catch (ORMException $exception) {
return new JsonResponse(
['error' => $exception->getMessage()],
Response::HTTP_INTERNAL_SERVER_ERROR
);
}
}
}
The truth is that I don't know what I'm doing wrong and I don't know where to look anymore. This is the first time I have implemented a system like this and I don't see where the error could be.
Thanks in advance.
The text was updated successfully, but these errors were encountered:
Hello.
I am developing a REST API with API Platform and I am finishing implementing OAuth with Google but I am getting the error that the title says. I have seen this problem in other threads but in my case and since it is an API, I do not have a front-end to redirect yet, but I don't know if that is really the problem.
I have divided my implementation into 3 classes: Client > Service > Controller. Below I leave the code and my configuration. (I will skip the class imports to not make it so long).
CLIENT
SERVICE
The "authorize" function is the function that is responsible for checking if a user exists in the database. If it does not exist, it creates it and in any case, returns a JSON token with which to authenticate.
CONTROLLER
SECURITY.YAML
KNPU_OAUTH2_CLIENT.YAML
GOOGLE CLOUD CONSOLE ROUTES
The truth is that I don't know what I'm doing wrong and I don't know where to look anymore. This is the first time I have implemented a system like this and I don't see where the error could be.
Thanks in advance.
The text was updated successfully, but these errors were encountered: