Skip to content

JSON authentication listener docs #7081

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Dec 14, 2016
229 changes: 229 additions & 0 deletions security/json_login_setup.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
How to Build a JSON Authentication Endpoint
===========================================

.. tip::

If you are storing users in some sort of a database, then you should consider
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it really relevant here ? IMHO it does not have specifically much to do with the current article :/

using `FOSUserBundle`_, which helps you build your ``User`` object and gives
you many routes and controllers for common tasks like login, registration and
forgot password.

In this entry, you'll build a JSON endpoint to log in your users. Of course, when the
user logs in, you can load your users from anywhere - like the database.
See :ref:`security-user-providers` for details.

First, enable form login under your firewall:

.. configuration-block::

.. code-block:: yaml

# app/config/security.yml
security:
# ...

firewalls:
main:
anonymous: ~
json_login:
check_path: login

.. code-block:: xml

<!-- app/config/security.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<srv:container xmlns="http://symfony.com/schema/dic/security"
xmlns:srv="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services
http://symfony.com/schema/dic/services/services-1.0.xsd">

<config>
<firewall name="main">
<anonymous />
<json-login check-path="login" />
</firewall>
</config>
</srv:container>

.. code-block:: php

// app/config/security.php
$container->loadFromExtension('security', array(
'firewalls' => array(
'main' => array(
'anonymous' => null,
'json_login' => array(
'check_path' => 'login',
),
),
),
));

.. tip::

The ``check_path`` can also be route names (but cannot have mandatory wildcards - e.g.
``/login/{foo}`` where ``foo`` has no default value).

Create a new ``SecurityController`` inside a bundle::

// src/AppBundle/Controller/SecurityController.php
namespace AppBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;

class SecurityController extends Controller
{
}

Next, configure the route that you earlier used under your ``json_login``
configuration (``login``):

.. configuration-block::

.. code-block:: php-annotations

// src/AppBundle/Controller/SecurityController.php

// ...
use Symfony\Component\HttpFoundation\Request;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;

class SecurityController extends Controller
{
/**
* @Route("/login", name="login")
*/
public function loginAction(Request $request)
{
}
}

.. code-block:: yaml

# app/config/routing.yml
login:
path: /login
defaults: { _controller: AppBundle:Security:login }

.. code-block:: xml

<!-- app/config/routing.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<routes xmlns="http://symfony.com/schema/routing"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/routing
http://symfony.com/schema/routing/routing-1.0.xsd">

<route id="login" path="/login">
<default key="_controller">AppBundle:Security:login</default>
</route>
</routes>

.. code-block:: php

// app/config/routing.php
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\Route;

$collection = new RouteCollection();
$collection->add('login', new Route('/login', array(
'_controller' => 'AppBundle:Security:login',
)));

return $collection;

Great!

Don't let this controller confuse you. As you'll see in a moment, when the
user submits the form, the security system automatically handles the form
submission for you. If the user submits an invalid username or password,
this controller reads the form submission error from the security system,
so that it can be displayed back to the user.

In other words the security system itself takes care of checking the submitted
username and password and authenticating the user.

And that's it! When you submit a ``POST`` request to the ``/login`` URL with
the following JSON document as body, the security system will automatically
check the user's credentials and either authenticate the user or throw an error::

.. code-block:: json
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For some reason, this block does not render well: http://pr-7081-acxnhhi-6qmocelev2lwe.eu.platform.sh/security/json_login_setup.html

(probably because of the double colon L.149)


{
"login": "dunglas",
"password": "MyPassword"
}

If the JSON document has a different structure, you can specify the path to
access to the user and password properties using the ``username_path`` and
``password_path`` keys (they default respectively to ``username`` and ``password``).

For example, if the JSON document has the following structure:

.. code-block:: json

{
"security": {
"credentials": {
"login": "dunglas",
"password": "MyPassword"
}
}
}

The security configuration should be:

.. configuration-block::

.. code-block:: yaml

# app/config/security.yml
security:
# ...

firewalls:
main:
anonymous: ~
json_login:
check_path: login
username_path: security.credentials.login
password_path: security.credentials.password

.. code-block:: xml

<!-- app/config/security.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<srv:container xmlns="http://symfony.com/schema/dic/security"
xmlns:srv="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services
http://symfony.com/schema/dic/services/services-1.0.xsd">

<config>
<firewall name="main">
<anonymous />
<json-login check-path="login"
username-path="security.credentials.login"
password-path="security.credentials.password" />
</firewall>
</config>
</srv:container>

.. code-block:: php

// app/config/security.php
$container->loadFromExtension('security', array(
'firewalls' => array(
'main' => array(
'anonymous' => null,
'json_login' => array(
'check_path' => 'login',
'username_path' => 'security.credentials.login',
'password_path' => 'security.credentials.password',
),
),
),
));

.. _`FOSUserBundle`: https://github.com/FriendsOfSymfony/FOSUserBundle