Question

I'm trying to crate a chain provider for login form in my Symfony2 application (version 2.3) - this is my security Yaml:

jms_security_extra:
    secure_all_services: false
    expressions: true

security:
    encoders:
    Symfony\Component\Security\Core\User\User: plaintext
    FOS\UserBundle\Model\UserInterface: sha512

    role_hierarchy:
    ROLE_ADMIN:       ROLE_USER
    ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]

    providers:
    chain_provider:
        chain:
        providers: [in_memory, fos_userbundle]
    fos_userbundle:
        id: fos_user.user_provider.username
    in_memory:
        memory:
        users:
            admin: { password: god, roles: [ 'ROLE_ADMIN' ] }

    firewalls:
    main:
        pattern: ^/
        form_login:
        provider: chain_provider
        csrf_provider: form.csrf_provider
        logout:       true
        anonymous:    true
        security: true

    access_control:
    - { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
    #- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY, requires_channel: https }
    - { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/admin/, role: ROLE_ADMIN }
    - { path: ^/group/, role: ROLE_ADMIN }

As you can see, I'm using FOSUserBundle (great stuff btw).

The problem is that after I login with in_memory admin user, I can't get to the /profile/ URL. I'm getting this error msg:

AccessDeniedHttpException: This user does not have access to this section

I found a cause to this - the problem is in FOS\UserBundle\Controller\ProfileController class:

public function showAction()
{
    $user = $this->container->get('security.context')->getToken()->getUser();
    if (!is_object($user) || !$user instanceof UserInterface) {
        throw new AccessDeniedException('This user does not have access to this section.');
    }

    return $this->container->get('templating')->renderResponse('FOSUserBundle:Profile:show.html.'.$this->container->getParameter('fos_user.template.engine'), array('user' => $user));
}

The Controller is checking if $user object is an instance of UserInterface, which is not, because it is instance of Symfony\Component\Security\Core\User\User (plaintext encoder class).

I tried to change encoder configuration to this:

security:
    encoders:
    Symfony\Component\Security\Core\User\UserInterface: plaintext

But it didn't work. I found that the User class is hardcoded in numerous places with the Symfony engine.

So my question is: how to change that behaviour from security yaml? Am I missing something?

Was it helpful?

Solution 2

Sorry, but you cant see the profile of memory user's. Profile is made only for FOS users. Thats why it must implement FOS\UserBundle\Model\UserInterface.

OTHER TIPS

PHP documentation:

instanceof is smart enough to know that a class that implements an interface is an instance of the interface

Symfony\Component\Security\Core\User\UserInterface implements AdvancedUserInterface which implements UserInterface.

Your problem is not the typeof check in FOS\UserBundle\Controller\ProfileController but a wrong firewall configuration or the in-memory user not receiving it's roles correctly!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top