<?php
declare(strict_types=1);
namespace App\EventListener;
use Throwable;
use App\Entity\User;
use App\Exception\ApiException;
use League\OAuth2\Server\RequestAccessTokenEvent;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpKernel\Exception\HttpException;
use League\Bundle\OAuth2ServerBundle\Event\UserResolveEvent;
use Symfony\Component\Security\Http\Event\LoginFailureEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use FOS\RestBundle\View\View;
// https://github.com/thephpleague/oauth2-server-bundle/blob/master/docs/basic-setup.md
// openssl genrsa -out private.key 2048
// openssl rsa -in private.key -pubout -out public.key
// bin/console league:oauth2-server:create-client mobile
// bin/console league:oauth2-server:update-client 1528bea9771237d8d0eb83e32f653a3a --add-grant-type=refresh_token
// bin/console league:oauth2-server:update-client 1528bea9771237d8d0eb83e32f653a3a --add-grant-type=client_credentials
// bin/console league:oauth2-server:update-client 1528bea9771237d8d0eb83e32f653a3a --add-grant-type=password
final class Oauth2AuthExceptionListener implements EventSubscriberInterface
{
public function __construct()
{
}
public function onUserAuthFailed(RequestAccessTokenEvent $event): void
{
// do something
}
public function onClientAuthFailed(RequestAccessTokenEvent $event): void
{
// do something
throw new AccessDeniedException('Access Denied');
}
public function onLoginFailure(LoginFailureEvent $event)
{
//if($event->getException() instanceof Throwable) {
// throw $event;
// }
//$event->getException()->getCode();
//throw new ApiException($event->getException()->getCode(), $event->getException()->getMessage(), $event->getException());
//dd($event); die ("ok!");
//throw new AccessDeniedException($event->getException()->getMessage(), $event->getException());
// https://stackoverflow.com/questions/53139957/return-jsonresponse-when-i-use-an-authtokenauthenticator-symfony-3
// Skip if request is not an API-request
$request = $event->getRequest();
if (strpos($request->getPathInfo(), '/api/') !== 0 && strpos($request->getPathInfo(), '/oauth/') !== 0) {
return;
}
// API / OAuth route only
$exception = $event->getException();
$statusCode = $this->getStatusCodeFromException($exception);
$error = [
'code' => $statusCode,
//'error' => $this->getErrorTypeFromException($exception),
// Warning! Passing the exception message without checks is insecure.
// This will potentially leak sensitive information.
// Do not use this in production!
'message' => $exception->getMessage(),
];
$response = new JsonResponse($error, $statusCode);
$event->setResponse($response);
}
public static function getSubscribedEvents()
{
return [
LoginFailureEvent::class => 'onLoginFailure',
];
}
private function getStatusCodeFromException(\Throwable $exception): int
{
if ($exception instanceof HttpException) {
return $exception->getStatusCode();
}
if ($exception instanceof HttpExceptionInterface) {
return $exception->getStatusCode();
}
return 500;
}
private function getErrorTypeFromException(\Throwable $exception): string
{
$parts = explode('\\', get_class($exception));
return end($parts);
}
}