Skip to content

Commit 3ab4092

Browse files
committed
Access Token Documentation
1 parent a4ae76a commit 3ab4092

File tree

2 files changed

+191
-0
lines changed

2 files changed

+191
-0
lines changed

security.rst

+9
Original file line numberDiff line numberDiff line change
@@ -1202,6 +1202,15 @@ website.
12021202

12031203
You can learn all about this authenticator in :doc:`/security/login_link`.
12041204

1205+
Access Tokens
1206+
~~~~~~~~~~~~~
1207+
1208+
Access Tokens are often used in API contexts.
1209+
The user will receive a token from an authorization server
1210+
which authenticates them.
1211+
1212+
You can learn all about this authenticator in :doc:`/security/access_token`.
1213+
12051214
X.509 Client Certificates
12061215
~~~~~~~~~~~~~~~~~~~~~~~~~
12071216

security/access_token.rst

+182
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
.. index::
2+
single: Security; Access Token
3+
4+
How to use Access Token Authentication
5+
======================================
6+
7+
Access tokens are commonly used in API contexts. The access token is obtained
8+
through an authorization server (or similar) whose role is to verify the user identity
9+
and receive consent before the token is issued.
10+
11+
Access Tokens can be of any kind: opaque strings, Json Web Tokens (JWT) or SAML2 (XML structures).
12+
Please refer to the `RFC6750`_: *The OAuth 2.0 Authorization Framework: Bearer Token Usage*.
13+
14+
Using the Access Token Authenticator
15+
------------------------------------
16+
17+
This guide assumes you have setup security and have created a user object
18+
in your application. Follow :doc:`the main security guide </security>` if
19+
this is not yet the case.
20+
21+
1) Configure the Access Token Authenticator
22+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
23+
24+
To use the access token authenticator, you must configure a ``token_handler``.
25+
The token handler retrieves the user identifier from the token.
26+
In order to get the user identifier, implementations may need to load and validate
27+
the token (e.g. revocation, expiration time, digital signature...).
28+
29+
.. configuration-block::
30+
31+
.. code-block:: yaml
32+
33+
# config/packages/security.yaml
34+
security:
35+
firewalls:
36+
main:
37+
access_token:
38+
token_handler: App\Security\AccessTokenHandler
39+
40+
This handler shall implement the interface
41+
:class:`Symfony\\Component\\Security\\Http\\AccessToken\\AccessTokenHandlerInterface`.
42+
In the following example, the handler will retrieve the token from a database
43+
using a fictive repository.
44+
45+
.. configuration-block::
46+
47+
.. code-block:: php
48+
49+
// src/Security/AccessTokenHandler.php
50+
namespace App\Security;
51+
52+
use App\Repository\AccessTokenRepository;
53+
use Symfony\Component\Security\Http\AccessToken\AccessTokenHandlerInterface;
54+
55+
class AccessTokenHandler implements AccessTokenHandlerInterface
56+
{
57+
public function __construct(
58+
private readonly AccessTokenRepository $repository
59+
) {
60+
}
61+
62+
public function getUserIdentifierFrom(string $token): string
63+
{
64+
$accessToken = $this->repository->findOneByValue($token);
65+
if ($accessToken === null || !$accessToken->isValid()) {
66+
throw new BadCredentialsException('Invalid credentials.');
67+
}
68+
69+
return $accessToken->getUserId();
70+
}
71+
}
72+
73+
.. caution::
74+
75+
It is important to check the token is valid.
76+
For instance, in the example we verify the token has not expired.
77+
With self-contained access tokens such as JWT, the handler is required to
78+
verify the digital signature and understand all claims,
79+
especially ``sub``, ``iat``, ``nbf`` and ``exp``.
80+
81+
Customizing the Authenticator
82+
-----------------------------
83+
84+
1) Access Token Extractors
85+
86+
By default, the access token is read from the request header parameter ``Authorization`` with the scheme ``Bearer``.
87+
You can change the behavior and send the access token through different ways.
88+
89+
This authenticator provides services able to extract the access token as per the RFC6750:
90+
91+
- ``header`` or ``security.access_token_extractor.header``: the token is sent through the request header. Usually ``Authorization`` with the ``Bearer`` scheme.
92+
- ``query_string`` or ``security.access_token_extractor.query_string``: the token is part of the query string. Usually ``access_token``.
93+
- ``request_body`` or ``security.access_token_extractor.request_body``: the token is part of the request body during a POST request. Usually ``access_token``.
94+
95+
.. caution::
96+
97+
Because of the security weaknesses associated with the URI method,
98+
including the high likelihood that the URL containing the access token will be logged,
99+
methods ````query_string```` and ``request_body`` **SHOULD NOT** be used unless it is impossible
100+
to transport the access token in the request header field.
101+
102+
Also, you can also create a custom extractor. The class shall implement the interface
103+
:class:`Symfony\\Component\\Security\\Http\\AccessToken\\AccessTokenExtractorInterface`.
104+
105+
.. configuration-block::
106+
107+
.. code-block:: yaml
108+
109+
# config/packages/security.yaml
110+
security:
111+
firewalls:
112+
main:
113+
header_token:
114+
token_handler: App\Security\AccessTokenHandler
115+
token_extractors: 'my_custom_access_token_extractor'
116+
117+
It is possible to set multiple extractors.
118+
In this case, **the order is important**: the first in the list is called first.
119+
120+
.. configuration-block::
121+
122+
.. code-block:: yaml
123+
124+
# config/packages/security.yaml
125+
security:
126+
firewalls:
127+
main:
128+
header_token:
129+
token_handler: App\Security\AccessTokenHandler
130+
token_extractors:
131+
- 'header'
132+
- 'request_body'
133+
- 'query_string'
134+
- 'my_custom_access_token_extractor'
135+
136+
2) Customizing the Success Handler
137+
138+
Sometimes, the default success handling does not fit your use-case (e.g.
139+
when you need to generate and return additional response header parameters).
140+
To customize how the success handler behaves, create your own handler as a class that implements
141+
:class:`Symfony\\Component\\Security\\Http\\Authentication\\AuthenticationSuccessHandlerInterface`::
142+
143+
// src/Security/Authentication/AuthenticationSuccessHandler.php
144+
namespace App\Security\Authentication;
145+
146+
use Symfony\Component\HttpFoundation\JsonResponse;
147+
use Symfony\Component\HttpFoundation\Request;
148+
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
149+
use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
150+
151+
class AuthenticationSuccessHandler implements AuthenticationSuccessHandlerInterface
152+
{
153+
public function onAuthenticationSuccess(Request $request, TokenInterface $token): JsonResponse
154+
{
155+
$user = $token->getUser();
156+
$userApiToken = $user->getApiToken();
157+
158+
return new JsonResponse(['apiToken' => $userApiToken]);
159+
}
160+
}
161+
162+
Then, configure this service ID as the ``success_handler``:
163+
164+
.. configuration-block::
165+
166+
.. code-block:: yaml
167+
168+
# config/packages/security.yaml
169+
security:
170+
firewalls:
171+
main:
172+
header_token:
173+
token_handler: App\Security\AccessTokenHandler
174+
success_handler: App\Security\Authentication\AuthenticationSuccessHandler
175+
176+
.. tip::
177+
178+
If you want to customize the default failure handling, use the
179+
``failure_handler`` option and create a class that implements
180+
:class:`Symfony\\Component\\Security\\Http\\Authentication\\AuthenticationFailureHandlerInterface`.
181+
182+
.. _`RFC6750`: https://datatracker.ietf.org/doc/html/rfc6750

0 commit comments

Comments
 (0)