1

I'v searching for hours and i did not find really how can we override login template for user and the admin side.

I'v created an admin firewall in security.yml

  firewalls:
    admin:
      pattern: /admin(.*)
      form_login:
        provider: fos_userbundle
        csrf_provider: form.csrf_provider
        login_path: /admin/login
        check_path: /admin/login_check
        default_target_path: /admin
      logout:
        path: /admin/logout
        target: /
      anonymous: true

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

Now i want to create a login form.

As i understand, we have to create an login action (because if we don't symfony2 throws a route not found exception).

Routing for admin login:

admin_login:
    pattern: /admin/login
    defaults: { _controller: CSCommonBundle:Admin/Default:login }

Controller for showing login page:

public function loginAction()
{
    return $this->render('CSCommonBundle:Admin/Login:login.html.twig');
}

And the login form:

<form class="form-signin" action="/admin/login_check" method="post">
    <h2 class="form-signin-heading">Giriş Yapın</h2>
    <div class="login-wrap">
        <input type="text" name="_username" id="username" class="form-control" placeholder="{% trans %}Kullanıcı Adı{% endtrans %} / {% trans %}E-Posta{% endtrans %}" autofocus>
        <input type="password" name="_password" id="password" class="form-control" placeholder="{% trans %}Şifre{% endtrans %}">
        <label class="checkbox">
            <input type="checkbox" id="remember_me" name="_remembe_me" value="on"> Beni Hatırla
        </label>
        <button class="btn btn-lg btn-login btn-block" type="submit">{% trans %}Giriş Yap{% endtrans %}</button>
    </div>
</form>

Now, i have a few questions about;

  1. How can we get login errors?
  2. Is creating login forms like this, works with fosuserbundle?
  3. Can we create another login pages for other user types?
  4. Giving form /admin/login_check (same as in security.yml) is healty?

Please explain these to me. I'm lost and stuck at this.

Canser Yanbakan
  • 3,780
  • 3
  • 39
  • 65

1 Answers1

2

I would highly recommend persuing the FOSUserBundle documentation to do this correctly. The controller to render your login action should actually be the FOSUserBundle SecurityControlle loginAction. This will handle logging in correctly from a security perspective and will also handle your login error messaging for you.

1.I believe FOSUserBundle uses flash messaging for the login errors so you would need to implement this in your template.

2.I would recommend checking out FOS' documentation, they lay out exactly how to create a new form to use instead of their form. https://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/Resources/doc/overriding_templates.md

3.Yes you can. I have done this in the past by extending the default FOSUserBundle SecurityController and overriding the renderLogin() method. https://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/Controller/SecurityController.php. This will allow you to specify different login templates. For example, you could add a check to see what route the user is heading to like this:

protected function renderLogin(array $data) {

    // get target path
    if ( $this->getSession()->get( '_security.main.target_path' ) ) {
        $targetPath = $this->getSession()->get( '_security.main.target_path' );
    } else {
        $targetPath = $this->get('router')->generate( 'default_route' );
    }

    $template = 'AcmeBundle:Security:loginOne.html.twig';

    // if admin
    if( strstr( $targetPath, '/admin' ) !== false ) {
        $template = 'AcmeBundle:Security:loginTwo.html.twig';
    }

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

I would recommend using a master form and using Twig blocks that you can override in all your other login forms, that way your only changing the skin of the form and not the entire form markup itself. If you do extend the security controller you may need to re-create the login routes that are in Resources/config/routing/security.xml to use it.

4.Yes, this is ok, but there are routes for this. I would not hard-code your login_check path in the form but create a route and generate that. To the client it's the same url but it will be easier to maintain. The default FOS route for the check is 'fos_user_security_check'. You should also use the route in your security.yml file instead of hardcoding the path. This way you can change the path simply by changing the routes.

This should allow you to use different templates for an admin login vs. a front end login without re-creating the whole form and security controller. Let FOS manage the security, just extend and override what you need.

joe42
  • 657
  • 4
  • 12
  • Thank you for explanation. But Fos documentation about overriding templates is not efficient. Can you show me an example? – Canser Yanbakan Jan 27 '14 at 20:22
  • Sure, overriding templates requires you to create a new file in app/Resources, for login it would be app/Resources/FOSUserBundle/views/Security/login.html.twig. If you are going to use multiple templates though, one for admin and one for front end users, then you wouldn't need to override the defaut template, instead override the security controller itself and just render your own template wherever you put it. Just be mindful to keep the same markup they use since login_check uses those input names. – joe42 Jan 27 '14 at 20:26
  • What are the names of form elements? I'm really confused. There is no really working example of this. – Canser Yanbakan Jan 27 '14 at 20:32
  • See the FOS login form here as a reference for what yours should look like. https://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/Resources/views/Security/login.html.twig The elements are _username, _password, _remember_me, _submit, and _csrf_token if you are using CSRF. – joe42 Jan 27 '14 at 20:34
  • See? {{ path("fos_user_security_check") }} But my secury check path is admin/login_check. And csrf token? There is no csrf token available because there is no form auto-created by symfony. – Canser Yanbakan Jan 27 '14 at 20:42
  • You could either change the path in the login form to match the same path in security.yml or set security.yml to use the fos login check path, but they do need to match. The CSRF token is generated by the FOS SecurityController and verified by the firewall if you have csrf protection enabled in security.yml (that's what the csrf_provider: form.csrf_provider line in security.yml is for). – joe42 Jan 27 '14 at 21:17