Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 259
David Morales Avatar asked Jun 21 '13 17:06

David Morales


2 Answers

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)

like image 162
David Morales Avatar answered Oct 20 '22 01:10

David Morales


Regarding to the approved answer, I made some adjustments in my Symfony 3.2.8 project in order to work correctly.

Instead of $requestAttributes = $this->container->get('request')->attributes; in the Security Controller, I used $requestAttributes = $this->container->get('request_stack')->getCurrentRequest();.

like image 37
Kiriakos Papachristou Avatar answered Oct 19 '22 23:10

Kiriakos Papachristou