oauth2-bundle
oauth2-bundle copied to clipboard
Support for new AuthenticatorManager feature introduced with symfony 5.1+
Hello folks,
actually I am integrating your bundle in my symfony 5.1+ application and stumbled over an incompatibilty. When combining your bundle with a bundle which already depends on the new AuthenticatorManager feature and enabled that feature in the security.yaml an error occurs.
Cannot configure AuthenticatorManager as "oauth2" authentication does not support it, set "security.enable_authenticator_manager" to `false`.
More informations about that feature and configuration example: https://symfony.com/doc/current/security/experimental_authenticators.html
Are there any plans to support that feature in the near future?
Hi there, while working on the current branch, I can get an implementation working with this authenticator:
<?php
namespace App\Security;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Http\Authenticator\AuthenticatorInterface;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
use Symfony\Component\Security\Http\Authenticator\Passport\Credentials\CustomCredentials;
use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
use Symfony\Component\Security\Http\Authenticator\Passport\PassportInterface;
use Symfony\Component\Security\Http\Authenticator\Passport\UserPassportInterface;
use Trikoder\Bundle\OAuth2Bundle\Security\Guard\Authenticator\OAuth2Authenticator as TrikoderOAuth2Authenticator;
class OAuth2Authenticator implements AuthenticatorInterface
{
private TrikoderOAuth2Authenticator $decorated;
private UserProviderInterface $userProvider;
public function __construct(TrikoderOAuth2Authenticator $decorated, UserProviderInterface $userProvider)
{
$this->decorated = $decorated;
$this->userProvider = $userProvider;
}
public function supports(Request $request): ?bool
{
return $this->decorated->supports($request);
}
public function authenticate(Request $request): PassportInterface
{
return new Passport(
new UserBadge(
$this->decorated->getCredentials($request),
fn ($id) => $this->decorated->getUser($id, $this->userProvider)
),
new CustomCredentials(
fn ($credentials, $user) => $this->decorated->checkCredentials($credentials, $user),
$this->decorated->getCredentials($request)
)
);
}
public function createAuthenticatedToken(PassportInterface $passport, string $firewallName): TokenInterface
{
if (!$passport instanceof UserPassportInterface) {
throw new \RuntimeException('Must be supplied with a UserPassport');
}
return $this->decorated->createAuthenticatedToken($passport->getUser(), $firewallName);
}
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
{
return $this->decorated->onAuthenticationSuccess($request, $token, $firewallName);
}
public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response
{
return $this->decorated->onAuthenticationFailure($request, $exception);
}
}
And adding this to the firewall (instead of oauth2: true
):
custom_authenticators:
- App\Security\OAuth2Authenticator
And then this to the services.yml
file. You may need different parameters depending on your firewall setup:
App\Security\OAuth2Authenticator:
arguments:
$decorated: '@Trikoder\Bundle\OAuth2Bundle\Security\Guard\Authenticator\OAuth2Authenticator'
$userProvider: '@security.user.provider.concrete.any_user'
Works well enough for the client_credentials
grant type. Haven't tested any others.
Worked on a PR for this issue https://github.com/trikoder/oauth2-bundle/issues/289