How to Build a JSON Authentication Endpoint
===========================================
In this entry, you'll build a JSON endpoint to log in your users. When the
user logs in, you can load your users from anywhere - like the database.
See :ref:`security-user-providers` for details.
First, enable the JSON login under your firewall:
.. configuration-block::
.. code-block:: yaml
# config/packages/security.yaml
security:
# ...
firewalls:
main:
anonymous: lazy
json_login:
check_path: /login
.. code-block:: xml
.. code-block:: php
// config/packages/security.php
$container->loadFromExtension('security', [
'firewalls' => [
'main' => [
'anonymous' => 'lazy',
'json_login' => [
'check_path' => '/login',
],
],
],
]);
.. tip::
The ``check_path`` can also be a route name (but cannot have mandatory
wildcards - e.g. ``/login/{foo}`` where ``foo`` has no default value).
The next step is to configure a route in your app matching this path:
.. configuration-block::
.. code-block:: php-annotations
// src/Controller/SecurityController.php
// ...
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
class SecurityController extends AbstractController
{
/**
* @Route("/login", name="login", methods={"POST"})
*/
public function login(Request $request)
{
$user = $this->getUser();
return $this->json([
'username' => $user->getUsername(),
'roles' => $user->getRoles(),
]);
}
}
.. code-block:: yaml
# config/routes.yaml
login:
path: /login
controller: App\Controller\SecurityController::login
methods: POST
.. code-block:: xml
.. code-block:: php
// config/routes.php
use App\Controller\SecurityController;
use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator;
return function (RoutingConfigurator $routes) {
$routes->add('login', '/login')
->controller([SecurityController::class, 'login'])
->methods(['POST'])
;
};
Now, when you make a ``POST`` request, with the header ``Content-Type: application/json``,
to the ``/login`` URL with the following JSON document as the body, the security
system intercepts the request and initiates the authentication process:
.. code-block:: json
{
"username": "dunglas",
"password": "MyPassword"
}
Symfony takes care of authenticating the user with the submitted username and
password or triggers an error in case the authentication process fails. If the
authentication is successful, the controller defined earlier will be executed.
If the JSON document has a different structure, you can specify the path to
access the ``username`` 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
# config/packages/security.yaml
security:
# ...
firewalls:
main:
anonymous: lazy
json_login:
check_path: login
username_path: security.credentials.login
password_path: security.credentials.password
.. code-block:: xml
.. code-block:: php
// config/packages/security.php
$container->loadFromExtension('security', [
'firewalls' => [
'main' => [
'anonymous' => 'lazy',
'json_login' => [
'check_path' => 'login',
'username_path' => 'security.credentials.login',
'password_path' => 'security.credentials.password',
],
],
],
]);