oauth2-server-bundle icon indicating copy to clipboard operation
oauth2-server-bundle copied to clipboard

firewall requires a user provider but none was defined

Open ghost opened this issue 1 year ago • 15 comments

Bundle setup docs https://github.com/thephpleague/oauth2-server-bundle/blob/58d4b11a5f75dd049d613871e6a3a3a367cbd976/docs/basic-setup.md does not say anything about setting a user provider for a firewall. I get exception Uncaught PHP Exception Symfony\Component\Config\Definition\Exception\InvalidConfigurationException: ""api" firewall requires a user provider but none was defined." at MissingUserProvider.php line 31

My security.yaml (same as in docs):

security:
    firewalls:
        api_token:
            pattern: ^/token$
            security: false
        api:
            pattern: ^/api
            security: true
            stateless: true
            oauth2: true

ghost avatar Jul 16 '24 19:07 ghost

Are you using client-credentials for authentication? I've had a similar issue due to changes that have been made in oauth2-server. Before oauth2-server version 9.0.0 the subject field in the JWT token was empty when using client credentials. This commit add a change that will fill the client id in the subject field. When the subject field is empty in the JWT this code will return a NullUser object and not call the user provider, but because this field is not empty anymore after version 9.0.0 the user provider is now being called and throws an error. I think the oauth2-server-bundle should provide a user provider for this or return the NullUser in some other way. The oauth2-server-bundle 0.9.0 upgrade broke our client-credentials flow without it being a mayor release :(

bartholdbos avatar Sep 10 '24 11:09 bartholdbos

Also experiencing the issue with client credentials that @bartholdbos is describing. Our tests started failing when updating to 0.9.0 because the UserInterface::createFromPayload was called, and no payload was passed with the JWT array and only the Client ID as the UserName.

This breaking change was not documented in the Release notes and there is no documentation on what should be done to resolve this issue. Any help would be appreciated. For now will stay it at 0.8.0 until there is a resolution

Ardenexal avatar Oct 01 '24 07:10 Ardenexal

It seems that previously NullUser (League\Bundle\OAuth2ServerBundle\Security\User\NullUser) was used, since $userIdentifier ($psr7Request->getAttribute('oauth_user_id', '') from OAuth2Authenticator) was empty string, - that's because 'sub' claim of jwt token was never set (at the point BearerTokenValidator::validateAuthorization it is empty string)

Hence, it looks like a fix for claim attribute, but it's definitely necessary to have some user provider.

rela589n avatar Oct 03 '24 15:10 rela589n

In my opinion, since we already have user identifier, it would be better if league library used some InMemoryUser (or even dedicated Oauth2User) containing that identifier

rela589n avatar Oct 03 '24 15:10 rela589n

Same problem here, @bartholdbos perfectly explained it. I can't understand how the issue went unnoticed since the change is so breaking. As for resolution: Problem with own user provider is that all SF user providers has to implement Symfony\Component\Security\Core\User\UserProviderInterface which in turn forces you to return class implementing Symfony\Component\Security\Core\User\UserInterface in loadUserByIdentifier method. IMHO the way to go is to make Client class implement UserInterface and then just use standard EntityUserProvider. For now I got it working by creating my own client class and setting it in config to be used in place of original Client:

namespace App\Entity;

use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
use League\Bundle\OAuth2ServerBundle\Model\AbstractClient;
use Symfony\Component\Security\Core\User\UserInterface;

#[ORM\Entity]
class Oauth2Client extends AbstractClient implements UserInterface
{
    #[ORM\Id]
    #[ORM\Column(type: Types::STRING, length: 32)]
    protected string $identifier;

    public function getRoles(): array
    {
        return [];
    }

    public function eraseCredentials()
    {

    }

    public function getUserIdentifier(): string
    {
        return $this->identifier;
    }
}
security:
    providers:
        ...
        oauth2_server_bundle:
            entity:
                class: App\Entity\Oauth2Client
                property: identifier
league_oauth2_server:
    client:
        classname: App\Entity\Oauth2Client

And then use oauth2_server_bundle provider in firewall that requires oauth2.

Would be nice if this was not needed!

maciekstary avatar Oct 04 '24 12:10 maciekstary

/cc @ajgarlag

chalasr avatar Oct 04 '24 19:10 chalasr

@maciekstary, I'm just wondering if it won't create the confusion that Oauth2Client::getRoles() method doesn't return any roles, since there are ROLE_OAUTH2_* roles created by the library. The point how oauth roles currently work under the hood is still a mystery to me

rela589n avatar Oct 05 '24 14:10 rela589n

@rela589n Good point. What I can only say is that in previous implementation authenticator used League\Bundle\OAuth2ServerBundle\Security\User\NullUser class and it's getRoles method returns empty array, too.

maciekstary avatar Oct 07 '24 07:10 maciekstary

Sorry, but I'm pretty busy these days.

Can anyone provide a reproducer? I'd need a minimal Symfony app working with league/oauth2-server-bundle:0.8 without a user provider.

ajgarlag avatar Oct 07 '24 12:10 ajgarlag

Hi, I've tried to prepare a reproducer (based on https://github.com/dwgebler/OAuth2ServerDemo), available here https://github.com/krkabol/OAuth_reproducer. Includes a test client, but sorry as new in Symfony, from some weird reason the /authorize route does not works :) - hopefully you are able to fix it easily yourself.

I have a similar non-public and when upgrade to 0.9, it falls..

EDIT: SSH key included for instant usage, it is not an unwanted leak

krkabol avatar Oct 10 '24 12:10 krkabol

@krkabol thanks. I'll try it ASAP.

ajgarlag avatar Oct 10 '24 16:10 ajgarlag

The reproducer provided by @krkabol was not using client-credentials. It did not fail with the Uncaught PHP Exception Symfony\Component\Config\Definition\Exception\InvalidConfigurationException: ""api" firewall requires a user provider but none was defined." at MissingUserProvider.php line 31 message.

The problem with that repository was reported in #200. I've opened #201 to fix documentation.

I still need a reproducer for the original error reported in this issue.

ajgarlag avatar Oct 15 '24 07:10 ajgarlag

@ajgarlag I'm not sure if you still need a reproducer for this issue but here's one https://github.com/fxbt/oauth2-client-credentials

When you generate a client credentials token with league/oauth2-server-bundle:0.8, you can call / and get a response. When updating to 0.9 and doing the same process, you'll get a Bad credentials. error

fxbt avatar Jan 15 '25 13:01 fxbt

@fxbt Thanks, but I've not been able to execute the reproducer.

I've submitted some issues in the reproducer repository.

Let's continue the discussion there until we can reproduce the problem.

ajgarlag avatar Jan 16 '25 08:01 ajgarlag

@ghost I've been able to reproduce the Bad credentials problem (reported in #207 too) using the reproducer app provided by @fxbt, but I was unable to make the app work with version 0.8 without defining a user provider. Can you make a PR in that repository to reproduce your problem?

ajgarlag avatar Jan 21 '25 07:01 ajgarlag