How to set a login form for admins and another for other users using FOSUserBundle?

David Morales picture David Morales · Jun 21, 2013 · Viewed 7.4k times · Source

When having a backend for admin users, it is interesting to have a login form, and at the same time having a normal login form for normal users in the public area of our website.

Is that possible using FOSUserBundle? How can it be done "the Symfony2" way?

Answer

David Morales picture David Morales · Jun 21, 2013

First we need to configure some special routes for the admin area:

admin_login:
    pattern:  /admin/login
    defaults: { _controller: FOSUserBundle:Security:login }

admin_login_check:
    pattern:  /admin/login_check
    defaults: { _controller: FOSUserBundle:Security:check }

admin_logout:
    pattern:  /admin/logout
    defaults: { _controller: FOSUserBundle:Security:logout }

Next configure a special firewall for the admin area using these routes, and define them to be anonymously accessed:

firewalls:
  ...
  admin:
    pattern:            /admin/(.*)
    form_login:
      provider:       fos_userbundle
      login_path:     admin_login
      check_path:     admin_login_check
      default_target_path: yourproject_admin_default_index
    logout:
      path:           admin_logout
      target:         admin_login
    anonymous:        true
    context:          application

  main:
    pattern: ^/
    form_login:
      provider:      fos_userbundle
      csrf_provider: form.csrf_provider
    context:         application
    ...

access_control:
  ...
  - { path: ^/admin/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
  - { path: ^/admin/logout$, role: IS_AUTHENTICATED_ANONYMOUSLY }
  - { path: ^/admin/login_check$, role: IS_AUTHENTICATED_ANONYMOUSLY }
  - { path: ^/admin/, role: ROLE_ADMIN }

Ok! We have just separated our login system in two parts: admin and main.

Let's override the SecurityController. For that we will need to create a custom bundle which parent is FOSUserBundle (check the doc for that). In this new bundle, create the controller:

<?php

namespace YourProject\UserBundle\Controller;

use FOS\UserBundle\Controller\SecurityController as BaseController;

/**
 * {@inheritDoc}
 */
class SecurityController extends BaseController
{
    /**
     * {@inheritDoc}
     */
    public function renderLogin(array $data)
    {
        $requestAttributes = $this->container->get('request')->attributes;

        if ('admin_login' === $requestAttributes->get('_route')) {
            $template = sprintf('AdminBundle:Security:login.html.twig');
        } else {
            $template = sprintf('FOSUserBundle:Security:login.html.twig');
        }

        return $this->container->get('templating')->renderResponse($template, $data);
    }
}

That's it! Now you can write your AdminBundle:Security:login.html.twig :)

NOTE: Don't forget to use the admin routes in your admin area! (in the login form action, the logout link, etc)