Los JSON Web Tokens son una forma muy práctica de asegurar nuestras APIs.
En esta charla veremos cuáles son sus propiedades fundamentales, cómo trabajar con ellos y qué opciones tenemos en Symfony, tanto con librerías, como con LexikJWTAuthenticationBundle y su uso del componente Guard.
3. Programo en Limenius
Casi todos los proyectos
necesitan una API
Hacemos aplicaciones a medida
con Symfony y React
JWT es una buena herramienta
para asegurarlas
13. Problemas con Cookies
Problemas con CORS
Implementación no natural en algunos clientes
Hay que protegerse contra CSRF
Requiere una gestión de sesión y pensar en cómo escalar
Mantienen un estado (sesión)
14. Estado en REST
[…] communication must be stateless in nature, […], such that
each request from client to server must contain all of the
information necessary to understand the request, and
cannot take advantage of any stored context on the
server. Session state is therefore kept entirely on the client.
15. Cómo siempre, hay razones
Requiere una gestión de sesión, y pensar en cómo escalar
¿Qué hacer con un balanceador de carga?
¿Dónde guardar las sesiones?
23. JWT solo es un formato de tokens
Pero muchas veces decimos “usar JWT”
Para referirnos a una forma de trabajar con ellos
https://www.flickr.com/photos/tokencompany/8073379662
52. Registered claims
jti
iss
aud
sub
iat
exp
nbf
Id del token: String
Issuer (emisor): StringOrUri
Audiencia: StringOrUri
Subject (tema): StringOrUri
Cuándo se creó: NumericDate
Cuándo expira: NumericDate
Tiempo hasta válidez: NumericDate
94. Eventos
JWT_CREATED: Añadir/quitar datos a claims.
JWT_DECODED: Validaciones extra.
JWT_AUTHENTICATED: Añadir datos al token de Symfony.
AUTHENTICATION_FAILURE
JWT_INVALID
JWT_NOT_FOUND
JWT_EXPIRED
}Cambiar respuestas.
AUTHENTICATION_SUCCESS
95. Añadir/quitar datos a payload
class JWTCreatedListener
{
public function onJWTCreated(JWTCreatedEvent $event)
{
$payload = $event->getData();
$user = $event->getUser();
if ($user->canOrder()) {
$payload['aud'] = ‘pedidos';
}
$event->setData($payload);
}
}
96. Comprobaciones extra
class JWTDecodedListener
{
public function onJWTDecoded(JWTDecodedEvent $event)
{
$payload = $event->getPayload();
if (!isset($payload['aud'])
|| $payload['aud'] !== 'pedidos') {
$event->markAsInvalid();
}
}
}
97. Añadir atributo API a Token Sf
class JWTAuthenticatedListener
{
public function onJWTAuthenticated(JWTAuthenticatedEvent $event)
{
$token = $event->getToken();
$token->setAttribute('api', true);
}
}
public function pagesAction(Request $request)
{
if ($this->get(‘security.token_storage')
->getToken()
->getAttribute(‘api')) {
return new JsonResponse('hola usuario de api');
}
}
98. ¿Qué pasa si quiero…?
Tener diferentes estrategias en distintos firewalls
Hacer algo muy particular
114. La interfaz GuardAuthenticator
interface GuardAuthenticatorInterface
{
public function getCredentials(Request $request);
public function getUser($credentials, UserProviderInterface $userProvider);
public function checkCredentials($credentials, UserInterface $user);
public function createAuthenticatedToken(UserInterface $user, $providerKey);
public function onAuthenticationFailure(Request $request,AuthenticationException $exception);
public function onAuthenticationSuccess(Request $request,TokenInterface $token, $providerKey);
public function supportsRememberMe();
}