10

I am not new to symfony by any means, but I've always used FOSUserBundle which by default prevents one from having 2 different login forms for authenticating two different user types..

I have two entities, one is Admins and the other is Users. Admins will only be able to login in the administration area and likewise users will only be able to login via the front end.

I've followed: http://symfony.com/doc/2.1/book/security.html which also lead me to http://symfony.com/doc/2.1/cookbook/security/entity_provider.html

My security.yml is:

jms_security_extra:
    secure_all_services: false
    expressions: true

security:
    encoders:
        Symfony\Component\Security\Core\User\User: sha512
        Fm\AdminBundle\Entity\Admins: sha512
        Fm\MainBundle\Entity\Users: 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, admin]
        in_memory:
            memory:
                users:
                    user:  { password: userpass, roles: [ 'ROLE_USER' ] }
                    admin: { password: adminpass, roles: [ 'ROLE_ADMIN' ] }

        admin:
            entity: { class: Fm\AdminBundle\Entity\Admins, property: username }


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

        alogin:
            pattern:  ^/admin/login
            security: false
        login:
            pattern:  ^/login
            security: false
        secured_area:
            pattern:    ^/admin
            anonymous: false
            provider: chain_provider
            switch_user: true
            form_login:
                check_path: /admin/login_check
                login_path: /admin/login
            logout:
                path:   /admin/logout
                target: /admin
        members_area:
            pattern: ^/
            anonymous: false
            form_login: ~
            logout:
                path: /logout
                target: /
            #anonymous: ~
            #http_basic:
            #    realm: "Secured Demo Area"

    access_control:
        - { path: ^/admin/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/admin/, roles: ROLE_ADMIN }

In my routes I have defined the routes as in the docs: (defaults to /admin/login and /admin/login_check because of my main routing include where /admin is set)

_admin_login:
    pattern:   /login
    defaults:  { _controller: FmAdminBundle:Security:login }

_admin_login_check:
    pattern:   /login_check

The error that I am getting in the browser is:

Unable to find the controller for path "/admin/login_check". Maybe you forgot to add the matching route in your routing configuration?

The stack trace is telling me: WARNING - Unable to look for the controller as the "_controller" parameter is missing

AND

ERROR - Symfony\Component\HttpKernel\Exception\NotFoundHttpException: Unable to find the controller for path "/admin/login_check". Maybe you forgot to add the matching route in your routing configuration? (uncaught exception) at /var/www/mysite.dev/symfony/app/bootstrap.php.cache line 1419

Justin
  • 2,131
  • 4
  • 24
  • 41
  • 2
    This is a simple regex-problem. Try `^/admin/login$` in your alogin-firewall to prevent login_check from not being behind a firewall. edit: The same goes for login of coure – dbrumann Mar 12 '13 at 16:33
  • That 'seems' to work, though i believe in my security.yml having the ` provider: chain_provider` should make it so that i can use the in_memory and the admin providers (as that's whats listed)... if i put in the username admin with the password admin pass -- it redirects back to the login screen with an error of "Bad Credentials" (i have no users in the database at the moment). Any ideas? – Justin Mar 12 '13 at 16:39
  • Are you sure you used the correct password, it should be `adminpass`, not `admin pass`. Also, check your logs for messages from Symfony's Security-component to see if everything works as expected. – dbrumann Mar 12 '13 at 16:44
  • it was because of the sha512 on one of the things... I changed that to just a single iteration sha and encoded the password and it's working... Problem now, is that after i login it redirects me to domain.com/login instead of domain.com/admin – Justin Mar 12 '13 at 16:48

2 Answers2

11

For implementing multiple login in symfony 2XX, try the following code

Security.yml

security:
    encoders:
        Symfony\Component\Security\Core\User\User: plaintext
        Company\AngularBundle\Entity\User: plaintext
        Company\AngularBundle\Entity\Admin: plaintext

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

    providers:
       users:
           entity: { class: CompanyAngularBundle:User, property: username }
       admin:
           entity: { class: CompanyAngularBundle:Admin, property: username }

    firewalls:
        admin_secured_area:
            pattern:   ^/admin
            anonymous: ~
            provider: admin
            form_login:
                login_path: /admin/login
                check_path: /admin/login_check
                default_target_path: /admin

        user_secured_area:
            pattern:   ^/
            anonymous: ~
            provider: users
            form_login:
                login_path: login
                check_path: login_check
                default_target_path: /home

routing.yml

login_check:
    path: /login_check
admin_login_check:
   path: /admin/login_check

Twig file

Action of login form should be like this
<form action="{{ path('login_check') }}" method="post">

Action of admin/login form should be like this
<form action="{{ path('admin_login_check') }}" method="post">
Binu V Pillai
  • 268
  • 1
  • 6
  • 13
  • 3
    Newbie mistake/gotcha: Note that if you have ^/ and ^/admin, the more specific pattern (^/admin) must be above the more general pattern ^/ in the file or else it won't take precedence since ^/ can still match ^/admin - at least, that's what finally made this work in my app where I also have a ^/ pattern in security.yml and I didn't realize that's how yml deals with regex precedence. – Mick Jan 15 '17 at 00:38
  • how did u solve that i have problem with the pattern. – Dev M Sep 16 '17 at 08:36
3

The problem is that after logging into the "secured_area" firewall you get redirect to "/" which is behind the "members_area" firewall. You can't access "members_area" with your credentials from "secured_area" (at least not by default). Read the details on http://symfony.com/doc/current/reference/configuration/security.html#reference-security-firewall-context .

If you have a look at the security configuration (http://symfony.com/doc/current/reference/configuration/security.html) you can see that the default_target_path for form_login is "/". Just change this to /admin:

security:
    ...

    firewalls:
    ...
        secured_area:
            pattern:    ^/admin
            ...
            form_login:
                check_path: /admin/login_check
                login_path: /admin/login
                default_target_path: /admin
            logout:
    ...

The alternative is to share the context as described in the first link (http://symfony.com/doc/current/reference/configuration/security.html#reference-security-firewall-context).

hacfi
  • 756
  • 3
  • 7