Custom WebserviceUserProvider and FOSAuthServerBundle

169 views Asked by At

I'm using an SF2.8 API based on this tutorial https://gist.github.com/tjamps/11d617a4b318d65ca583 except i'm using MongoDB.

When a FOSUser (created on my DB A with oAuth tables) is connected to my API, i don't have all infos what i need because there are an other database.

I found a SF doc which explain how to custom symfony default authentication by replacing the default FOS User provider with a custom user provider.

So I decided to create the same architecture on this doc : http://symfony.com/doc/2.8/security/custom_provider.html

Before asking my oAuth token in /oauth/v2/token by HTTP Post request, my overrided loadUserByUsername method call an external API and instanciate a WebserviceUser which contain a user companies's collection in addition to having basic fields like username, password, salt etc. needed to connect.

After loadUserByUsername call, oAuth try to flush the generated accesstoken to the connected user into DB, but an exception is thrown because the User document to persist in AccessToken document is a AppBundle\Security\User\WebserviceUser instead of AppBundle\Document\User (child of FOSUser Document) so the mapping fail while persisting.

I got this :

The class 'AppBundle\Security\User\WebserviceUser' was not found in the chain configured namespaces AppBundle\Document, FOS\UserBundle\Document, FOS\OAuthServerBundle\Document (500 Internal Server Error)

Did I do something wrong ?

EDIT : My new loadUserByUsername method :

public function loadUserByUsername($username)
{
    $apiUser = $this->manager->getRepository('AppBundle:User')->findOneByUsername($username);

    if (is_null($apiUser)) {
        throw new UsernameNotFoundException(
            sprintf('Username "%s" does not exist.', $username)
        );
    }

    $userData = $this->client->httpGetList("user", ['filter_usrMail' => $apiUser->getEmail()]);
    $userData = $userData[array_keys($userData)[0]];

    $companies = isset($userData['usrCompany']) ? $userData['usrCompany'] : [];

    if ($userData) {
        $role = isset($userData['usrRole']) ? [$userData['usrRole']] : ['ROLE_USER'];

        $user = new WebserviceUser($apiUser->getUsername(), $apiUser->getPassword(), $apiUser->getSalt(), $apiUser->getRoles());
        $user->setCompanies($companies);
        $user->setApiUsername($apiUser->getUsername());

        return $user;
    }

    throw new UsernameNotFoundException(
        sprintf('Username "%s" does not exist.', $username)
    );
}

fos_oauth_server yml conf :

db_driver:           mongodb
client_class:        AppBundle\Document\Client
access_token_class:  AppBundle\Document\AccessToken
refresh_token_class: AppBundle\Document\RefreshToken
auth_code_class:     AppBundle\Document\AuthCode
service:
    user_provider: app.webservice_user_provider

services.yml conf :

app.webservice_user_provider:
    class: AppBundle\Security\User\WebserviceUserProvider
    arguments: ['@my_communicator.client', '@session', '@doctrine.odm.mongodb.document_manager', '%session_refresh_ttl%']

security.yml conf :

  encoders:
        AppBundle\Security\User\WebserviceUser: bcrypt
        FOS\UserBundle\Model\UserInterface: bcrypt
    providers:
        webservice:
            id: app.webservice_user_provider
        #in_memory:
        #    memory: ~

        fos_userbundle:
            id: fos_user.user_provider.username

    role_hierarchy:
        ROLE_ADMIN: ROLE_USER

    firewalls:
        oauth_token:                                   # Everyone can access the access token URL.
            pattern: ^/oauth/v2/token
            security: false

        api:
            pattern: ^\/api(?!\/doc|\/v[0-9][\.0-9]*\/core(\/createaccount|\/clients)) # All URLs are protected (except api doc and api create account)
            fos_oauth: true                            # OAuth2 protected resource
            stateless: true                            # Do no set session cookies
            anonymous: false                           # Anonymous access is not allowed
            access_denied_handler: app.listener.access_denied.handler

        apidoc:
            pattern: ^\/api\/doc
            anonymous: false
            security: false

    access_control:
        - { path: ^\/api\/v[0-9][\.0-9]*\/(?!(admin|core)), roles: ROLE_USER }
        - { path: ^\/api\/v[0-9][\.0-9]*\/(admin|core)(?!(\/createaccount|\/clients)), roles: ROLE_ADMIN }
        - { path: ^\/api\/v[0-9][\.0-9]*\/core(\/createaccount|\/clients), roles: IS_AUTHENTICATED_ANONYMOUSLY, ips: [127.0.0.1, localhost, ::1] }
        - { path: ^\/api\/v[0-9][\.0-9]*\/core(\/createaccount|\/clients), roles: ROLE_NO_ACCESS }

    access_decision_manager:
        strategy: unanimous
0

There are 0 answers