HyderA
HyderA

Reputation: 21401

Symfony: Multiple firewall contexts - User being forwarded to the wrong context

I've got a login for the frontend (which is optional), and another login for the admin panel, which is mandatory.

When a user goes to fe_login, they can login to the frontend context. This is okay!

When they go to admin_login, they should be able to login to the admin context. This is not okay

The issue is that when I go to /admin, I get redirected to fe_login when I should be redirected to admin_login

Here's my security.yml:

security:
    encoders:
        App\FrontendBundle\Controller\UserController:
            algorithm: bcrypt
        App\AdminBundle\Controller\UserController:
            algorithm: bcrypt
        App\Entity\User:
            algorithm: bcrypt
    providers:
        administrators:
            entity: { class: AppEntity:User, property: username }

    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false
        admin:
            pattern: ^/admin
            form_login:
                login_path: admin_login
                check_path: admin_auth
                csrf_provider: form.csrf_provider
            logout:
                path: admin_logout
                target: admin_login
        frontend:
            anonymous: ~
            form_login:
                login_path: fe_login
                check_path: fe_auth
                csrf_provider: form.csrf_provider
                always_use_default_target_path: true
                default_target_path: fe_landing
            logout:
                path: fe_logout
                target: fe_landing
        login:
            pattern: ^/admin/login
            anonymous: ~

        default:
            anonymous: ~
    access_control:
        - { path: ^/admin/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/admin, roles: [ROLE_ADMIN,ROLE_MANAGER,ROLE_DRIVER,ROLE_PARTNER] }

Any idea what I am doing wrong?

Upvotes: 7

Views: 1322

Answers (3)

Sehael
Sehael

Reputation: 3736

You have some firewalls that seem unnecessary. Let's simplify your firewall config:

firewalls:
    dev:
        pattern: ^/(_(profiler|wdt)|css|images|js)/
        security: false
    admin:
        pattern: ^/admin
        form_login:
            login_path: admin_login
            check_path: admin_auth
            csrf_provider: form.csrf_provider
        logout:
            path: admin_logout
            target: admin_login
        anonymous: ~
    frontend:
        pattern: ^/
        anonymous: ~
        form_login:
            login_path: fe_login
            check_path: fe_auth
            csrf_provider: form.csrf_provider
            always_use_default_target_path: true
            default_target_path: fe_landing
        logout:
            path: fe_logout
            target: fe_landing

access_control:
    # allow unauthenticated to access admin login
    - { path: ^/admin/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
    # restrict admin access
    - { path: ^/admin, roles: [ROLE_ADMIN,ROLE_MANAGER,ROLE_DRIVER,ROLE_PARTNER] }
    # allow unauthenticated to access front end login
    - { path: ^/fe/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
    # restrict front end access
    - { path: ^/fe, roles: ROLE_USER } # or whatever the role is of your frontend user
    # allow all other pages to be viewed by unauthenticated users
    - { path: ^/, roles: IS_AUTHENTICATED_ANONYMOUSLY }

This config makes it so that all pages under /fe require front end authorization and all pages under /admin require admin authorization. And all other pages are not protected at all. You can adjust that however you want.

The order of the access_control is important. As soon as a rule is matched, it does not try to match any further entries. This config should work so that the correct login is displayed. However, it does not appear that you are using a different user provider for each firewall. So when you are logging in, the application will use the same provider for both logins. This may or may not be what you intend, but I thought I would point it out. If you do want a different user provider for each login, just add the provider: ProviderName to each firewall.

Upvotes: 1

jrmgx
jrmgx

Reputation: 729

I'm not quite sure about the reason, but you must now that security.yml must be a really clear file in order to avoid miss configuration (which would lead in security issues)

So, regarding your file:

  • it misses the pattern key on the frontend section: I would add pattern: ^/
  • the frontend login path could be specified as you did for the backend one
  • the order of your rules make me think something is not correct

This is a version you should test:

security:
    encoders:
        App\FrontendBundle\Controller\UserController:
            algorithm: bcrypt
        App\AdminBundle\Controller\UserController:
            algorithm: bcrypt
        App\Entity\User:
            algorithm: bcrypt

    providers:
        administrators:
            entity: { class: AppEntity:User, property: username }

    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false
        login_admin:
            pattern: ^/admin/login
            anonymous: ~
        admin:
            pattern: ^/admin
            form_login:
                login_path: admin_login
                check_path: admin_auth
                csrf_provider: form.csrf_provider
            logout:
                path: admin_logout
                target: admin_login
        login_frontend:
            pattern: ^/login # you should adapt this to your app
            anonymous: ~
        frontend:
            pattern: ^/
            anonymous: ~
            form_login:
                login_path: fe_login
                check_path: fe_auth
                csrf_provider: form.csrf_provider
                always_use_default_target_path: true
                default_target_path: fe_landing
            logout:
                path: fe_logout
                target: fe_landing

    access_control:
        - { path: ^/admin/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/admin, roles: [ROLE_ADMIN,ROLE_MANAGER,ROLE_DRIVER,ROLE_PARTNER] }

Upvotes: 2

COil
COil

Reputation: 7606

Here is my security.yml, but as I said it is for Symfony2.0, may be you will find a hint.

security:
    encoders:

### ...

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

providers:
    fos_userbundle:
        id: fos_user.user_manager
    admin_adminbundle:
        id: custom_admin_manager_id

firewalls:
    dev:
        pattern:  ^/(_(profiler|wdt)|css|images|js)/
        security: false

    admin:
        pattern: ^/admin/

        form_login:
            check_path:         /admin/check-login
            login_path:         /admin/login
            provider:           admin_adminbundle
            csrf_provider:      form.csrf_provider
            post_only:          true
            success_handler:    login_success_handler
            failure_handler:    admin_login_failure_handler
            username_parameter: login_username
            password_parameter: login_password
            remember_me:        false
        logout:
            path:               /admin/logout
            target:             /admin/login
        anonymous: true

    frontend:
        pattern: ^/

        form_login:
            check_path:         /frontend/check-login
            login_path:         /frontend/login
            provider:           fos_userbundle
            csrf_provider:      form.csrf_provider
            post_only:          true
            success_handler:    login_success_handler
            failure_handler:    login_failure_handler
            username_parameter: login_username
            password_parameter: login_password
        logout:
            path:               /frontend/logout
            success_handler:    logout_success_handler
        anonymous: true

access_control:
    - { path: ^/frontend/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/admin/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }

Upvotes: 3

Related Questions