Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for new AuthenticatorManager feature introduced with symfony 5.1+ #249

Open
pixelfantasy opened this issue Dec 3, 2020 · 2 comments

Comments

@pixelfantasy
Copy link

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?

@nathansalter
Copy link

nathansalter commented Jan 13, 2021

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.

@ricohumme
Copy link

Worked on a PR for this issue #289

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants