Asegurando APIs en Symfony con JWT

138
de Symfony 30 junio - 1 julio 2017 Castellón ASEGURANDO APIS EN SYMFONY CON JWT Nacho Martín

Transcript of Asegurando APIs en Symfony con JWT

Page 1: Asegurando APIs en Symfony con JWT

deSymfony 30 junio - 1 julio 2017 Castellón

ASEGURANDO APIS EN SYMFONY CON JWTNacho Martín

Page 2: Asegurando APIs en Symfony con JWT

deSymfony

¡Muchas gracias a nuestros patrocinadores!

Page 3: Asegurando APIs en Symfony con JWT

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

Page 4: Asegurando APIs en Symfony con JWT

Por qué es esto necesario

Page 5: Asegurando APIs en Symfony con JWT

Por qué es esto necesario

¿Por qué no está todo inventado?

Page 6: Asegurando APIs en Symfony con JWT
Page 7: Asegurando APIs en Symfony con JWT

Esta charla va de alivios

Page 8: Asegurando APIs en Symfony con JWT

Esta charla va de alivios

Page 9: Asegurando APIs en Symfony con JWT

Autenticación con Cookies

Cliente (navegador) Servidor

BD

POST /login_check

username: "nacho", password: "patata"

Page 10: Asegurando APIs en Symfony con JWT

Autenticación con Cookies

Cliente (navegador) Servidor

BD

Obtiene usuario Verifica credenciales

Guarda sesión

Page 11: Asegurando APIs en Symfony con JWT

Autenticación con Cookies

Cliente (navegador) Servidor

BD

Envía cookie al cliente

Set-Cookie: PHPSESSIONID=HOLA…

Page 12: Asegurando APIs en Symfony con JWT

Autenticación con Cookies

Cliente (navegador) Servidor

BD

Usa cookie para identificarse

Cookie: PHPSESSIONID=HOLA

Page 13: Asegurando APIs en Symfony con JWT

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)

Page 14: Asegurando APIs en Symfony con JWT

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.

Page 15: Asegurando APIs en Symfony con JWT

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?

Page 16: Asegurando APIs en Symfony con JWT
Page 17: Asegurando APIs en Symfony con JWT

Alternativas para APIs

Page 18: Asegurando APIs en Symfony con JWT
Page 19: Asegurando APIs en Symfony con JWT

Junio 2012

Page 20: Asegurando APIs en Symfony con JWT

JSON Web Tokens (JWT)

Page 21: Asegurando APIs en Symfony con JWT

JOSEJSON Object Signing and Encryption{ JWT

JWAJWSJWEJWK

Page 22: Asegurando APIs en Symfony con JWT

JOSEJSON Object Signing and Encryption{ JWT

JWAJWSJWEJWK

Page 23: Asegurando APIs en Symfony con JWT

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

Page 24: Asegurando APIs en Symfony con JWT

Autenticación con JWT

Cliente (navegador) Servidor

BD

POST /login_check

username: "nacho", password: "patata"

Page 25: Asegurando APIs en Symfony con JWT

Autenticación con JWT

Cliente (navegador) Servidor

BD

Obtiene usuario Verifica credenciales

Guarda sesión?

Page 26: Asegurando APIs en Symfony con JWT

Autenticación con JWT

Cliente (navegador) Servidor

BD

Envía token al cliente

{“token”:"tomaUnToken"}

Page 27: Asegurando APIs en Symfony con JWT

Autenticación con JWT

Cliente (navegador) Servidor

BD

Usa token para identificarse

Authorization: Bearer tomaUnToken

Page 28: Asegurando APIs en Symfony con JWT

Uso en JavaScript

fetch(baseUrl + '/admin/api/recipes', { method: 'POST', headers: { 'Accept': 'application/json', 'Content-Type': 'application/json', 'Authorization': 'Bearer '+token, }, body: JSON.stringify( data )})

Page 29: Asegurando APIs en Symfony con JWT

Almacenamiento en JavaScript

window.localStorage.setItem('access_token', token)

window.localStorage.getItem('access_token')

Page 30: Asegurando APIs en Symfony con JWT

Almacenamiento en JavaScript

window.localStorage.setItem('access_token', token)

window.localStorage.getItem('access_token')

Ya no tenemos CSRF, ahora ojo con ataques XSS

Page 31: Asegurando APIs en Symfony con JWT

El famoso token

eyJhbGciOiJSUzI1NiJ9.eyJyb2xlcyI6WyJST0xFX1VTRVIiXSwidXNlcm5hbWUiOiJuYWNobyIsImlhdCI6MTQ5ODE0MjA3Niw

iZXhwIjoxNDk4MTQ1Njc2fQ

Page 32: Asegurando APIs en Symfony con JWT

eyJhbGciOiJSUzI1NiJ9.eyJyb2xlcyI6WyJST0xFX1VTRVIiXSwidXNlcm5hbWUiOiJuYWNobyIsImlhdCI6MTQ5ODE0MjA3Niw

iZXhwIjoxNDk4MTQ1Njc2fQ

El famoso token

Page 33: Asegurando APIs en Symfony con JWT

eyJhbGciOiJSUzI1NiJ9.eyJyb2xlcyI6WyJST0xFX1VTRVIiXSwidXNlcm5hbWUiOiJuYWNobyIsImlhdCI6MTQ5ODE0MjA3Niw

iZXhwIjoxNDk4MTQ1Njc2fQ

Hay un puntoEl famoso token

Page 34: Asegurando APIs en Symfony con JWT

El famoso token

eyJhbGciOiJSUzI1NiJ9.eyJyb2xlcyI6WyJST0xFX1VTRVIiXSwidXNlcm5hbWUiOiJuYWNobyIsImlhdCI6MTQ5ODE0MjA3Niw

iZXhwIjoxNDk4MTQ1Njc2fQ

Page 35: Asegurando APIs en Symfony con JWT

El famoso token

eyJhbGciOiJSUzI1NiJ9.eyJyb2xlcyI6WyJST0xFX1VTRVIiXSwidXNlcm5hbWUiOiJuYWNobyIsImlhdCI6MTQ5ODE0MjA3Niw

iZXhwIjoxNDk4MTQ1Njc2fQ

{“alg":"none"}

{ “username":"nacho", “iat":1498142076, “exp”:1498145676 }

Page 36: Asegurando APIs en Symfony con JWT

Base64Url

eyJhbGciOiJSUzI1NiJ9{“alg":"none"}

No está cifrado (todos lo pueden leer) Solo está codificado

Esto solo sirve para que pueda viajar en URLs Y en cualquier sitio donde puedan viajar strings

Page 37: Asegurando APIs en Symfony con JWT

Base64Url{ “username":"nacho", “iat":1498142076, “exp”:1498145676 }

¿Me puedo fiar de esto?

Page 38: Asegurando APIs en Symfony con JWT

Base64Url{ “username":"nacho", “iat":1498142076, “exp”:1498145676 }

¿Me puedo fiar de esto?

Page 39: Asegurando APIs en Symfony con JWT

El token completo

eyJhbGciOiJSUzI1NiJ9.eyJyb2xlcyI6WyJST0xFX1VTRVIiXSwidXNlcm5hbWUiOiJuYWNobyIsImlhdCI6MTQ5ODE0MjA3NiwiZXhwIjoxNDk4MTQ1Njc2fQ.jomtnO16Tik6jxU_0HmsXFxbUSyBoNTu8RVSbQ9jEKUfYEFTG8QZrsSpNl5uzlXf-

hP2zx1YmPTow1jXGyoFjV6Nk1e7pFlw2s8fSrIZpT2ZFBuVPefKhSWXYoSUHGZWtMFMU-yghnWA6tlFD5UcJiDQ3ZlUCbLxOlDdygUoC841aR9R87otefdQUEKY_faGq1Tl-

KxJfjndG4HENgC7M52JaX5xFKmOlI1mKXqDvVOrCTil3yOcqxQv94SZjqhG5V7NLaaslMDXVl4fzJC-WWE_Eo0xzfOSxMAZ7NBEvha207pjl8FAszQDZ0uuqxfPLqb4QnpALnFAGip4hlu28wRccAsWJQ6uSYtClrE9Kwt7Vlo4PrPX3zqMb_YaRI1QUco6qjj2AsCf18-0f5XvgqrwSoU_73w4pgsj7rUyft9mwe3tiUYCoUP_dKFJfcz_ofHScpsWfFJ4lD4TIzpKf1LfLFwRUcpQuJdR

K8-1C_x5dJILrO2fSKZbxFCq_-zB2UHmbH8eFQQYxIpS4eDjFDZTeFLOzruapM10taDQ8buGOyVUx9vwTJoWq9dFuqVAdhFc9h6iXNy0QzI46uvN-

en1n6KVsKTfaLecvCYhIIt32Z5mYD3YgDEeRnLZ5TIgykiVNL9SZCGphzv6h5MEs_xQyDo6XOsu92tPtbqyvI4

Page 40: Asegurando APIs en Symfony con JWT

El token completo

eyJhbGciOiJSUzI1NiJ9.eyJyb2xlcyI6WyJST0xFX1VTRVIiXSwidXNlcm5hbWUiOiJuYWNobyIsImlhdCI6MTQ5ODE0MjA3NiwiZXhwIjoxNDk4MTQ1Njc2fQ.jomtnO16Tik6jxU_0HmsXFxbUSyBoNTu8RVSbQ9jEKUfYEFTG8QZrsSpNl5uzlXf-

hP2zx1YmPTow1jXGyoFjV6Nk1e7pFlw2s8fSrIZpT2ZFBuVPefKhSWXYoSUHGZWtMFMU-yghnWA6tlFD5UcJiDQ3ZlUCbLxOlDdygUoC841aR9R87otefdQUEKY_faGq1Tl-

KxJfjndG4HENgC7M52JaX5xFKmOlI1mKXqDvVOrCTil3yOcqxQv94SZjqhG5V7NLaaslMDXVl4fzJC-WWE_Eo0xzfOSxMAZ7NBEvha207pjl8FAszQDZ0uuqxfPLqb4QnpALnFAGip4hlu28wRccAsWJQ6uSYtClrE9Kwt7Vlo4PrPX3zqMb_YaRI1QUco6qjj2AsCf18-0f5XvgqrwSoU_73w4pgsj7rUyft9mwe3tiUYCoUP_dKFJfcz_ofHScpsWfFJ4lD4TIzpKf1LfLFwRUcpQuJdR

K8-1C_x5dJILrO2fSKZbxFCq_-zB2UHmbH8eFQQYxIpS4eDjFDZTeFLOzruapM10taDQ8buGOyVUx9vwTJoWq9dFuqVAdhFc9h6iXNy0QzI46uvN-

en1n6KVsKTfaLecvCYhIIt32Z5mYD3YgDEeRnLZ5TIgykiVNL9SZCGphzv6h5MEs_xQyDo6XOsu92tPtbqyvI4

header.claims.signature

Page 41: Asegurando APIs en Symfony con JWT

Pero sí está firmado (los intermediarios no lo pueden modificar sin que nos enteremos)

No está cifrado

Page 42: Asegurando APIs en Symfony con JWT

Header

{ “typ”:”JWT”, “alg”:”RS256” }

Page 43: Asegurando APIs en Symfony con JWT

Header

{ “typ”:”JWT”, “alg”:”RS256” }

Tipo de token

Page 44: Asegurando APIs en Symfony con JWT

Header

{ “typ”:”JWT”, “alg”:”RS256” }

Tipo de token

Algoritmo de hashing

Page 45: Asegurando APIs en Symfony con JWT

¿Qué algoritmo usar?

JWA (rfc7518)

Page 46: Asegurando APIs en Symfony con JWT

Diferencia simétrico/asimétrico

Simétrico: usamos la misma clave para firmar y validar.

Asimétrico: usamos distintas claves para firmar y validar.

Page 47: Asegurando APIs en Symfony con JWT

RS256 RS384 RS512

Algoritmos

HS256 HS384 HS512

ES256 ES384 ES512

HMAC ECDSA RSA

PS256 PS384 PS348

RSASSA-PSS

none

Page 48: Asegurando APIs en Symfony con JWT

RS256 RS384 RS512

Algoritmos

HS256 HS384 HS512

ES256 ES384 ES512

HMAC ECDSA RSA

PS256 PS384 PS348

RSASSA-PSS

none

Simétrico

Page 49: Asegurando APIs en Symfony con JWT

RS256 RS384 RS512

Algoritmos

HS256 HS384 HS512

ES256 ES384 ES512

HMAC ECDSA RSA

PS256 PS384 PS348

RSASSA-PSS

none

Simétrico Asimétricos

Page 50: Asegurando APIs en Symfony con JWT

RS256 RS384 RS512

Algoritmos

HS256 HS384 HS512

ES256 ES384 ES512

HMAC ECDSA

RS256 RS384 RS512

RSA

PS256 PS384 PS348

RSASSA-PSS

none

Simétrico Asimétricos

Page 51: Asegurando APIs en Symfony con JWT

Claims

{ “username":"nacho", “iat":1498142076, “exp”:1498145676 }

Page 52: Asegurando APIs en Symfony con JWT

Registered claimsjti

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

Page 53: Asegurando APIs en Symfony con JWT

Custom claims

{ “username":"nacho", “iat":1498142076, “exp”:1498145676 }

Podemos añadir lo que queramos.

Solo hay que tener en cuenta: Ser conciso.

Los datos no van cifrados (el cliente los ve).

Page 54: Asegurando APIs en Symfony con JWT

Firma

Signature = algoritmo(payload, key)

Payload = Base64URL(headers)+ ”.”+ Base64URL(claims)

JWS (rfc7515)

Page 55: Asegurando APIs en Symfony con JWT

JWT.IO

Page 56: Asegurando APIs en Symfony con JWT

Importante: Usar TLS (“SSL”)

Page 57: Asegurando APIs en Symfony con JWT

Ventajas de JWT

Page 58: Asegurando APIs en Symfony con JWT

Caso: Mi app en JavaScript se ve distinta dependiendo del rol del usuario

Page 59: Asegurando APIs en Symfony con JWT

Con Cookies

Cliente Servidor

BD

Cookie: PHPSESSIONID=HOLA

Page 60: Asegurando APIs en Symfony con JWT

Con Cookies

Cliente Servidor

BD

Cookie: PHPSESSIONID=HOLA

Tengo una cookie pero no sé qué usuario soy ni qué permisos tengo

Page 61: Asegurando APIs en Symfony con JWT

Con Cookies

Cliente Servidor

BD

Cookie: PHPSESSIONID=HOLA

Page 62: Asegurando APIs en Symfony con JWT

Con Cookies

Cliente Servidor

BD

Cookie: PHPSESSIONID=HOLA

Obtener usuario

Page 63: Asegurando APIs en Symfony con JWT

Con Cookies

Cliente Servidor

BD

Cookie: PHPSESSIONID=HOLA

Obtener usuario

Page 64: Asegurando APIs en Symfony con JWT

Con Cookies

Cliente Servidor

BD

Cookie: PHPSESSIONID=HOLA

Obtener usuario

Page 65: Asegurando APIs en Symfony con JWT

Con Cookies

Cliente Servidor

BD

Cookie: PHPSESSIONID=HOLA

Obtener usuario

Page 66: Asegurando APIs en Symfony con JWT

Con Cookies

Cliente Servidor

BD

Cookie: PHPSESSIONID=HOLA

Obtener usuario

Y ahora mostramos

Page 67: Asegurando APIs en Symfony con JWT

Con JWT

Cliente Servidor

BD

Token: ejh9…

Page 68: Asegurando APIs en Symfony con JWT

Con JWT

Cliente Servidor

BD

Token: ejh9…

{ “username":"nacho", “iat":1498142076, “exp”:1498145676 }

Page 69: Asegurando APIs en Symfony con JWT

Con JWT

Cliente Servidor

BD

Token: ejh9…

{ “username":"nacho", “iat":1498142076, “exp”:1498145676 }

Tenemos todos los datos

Page 70: Asegurando APIs en Symfony con JWT

Con JWT

Cliente

Token: ejh9…

{ “username":"nacho", “iat":1498142076, “exp”:1498145676 }

Tenemos todos los datos

Page 71: Asegurando APIs en Symfony con JWT

MicroserviciosAuth

Clave privada y pública

ConsultaClave pública

ClienteClave pública

PedidosClave pública

Page 72: Asegurando APIs en Symfony con JWT

MicroserviciosAuth

Clave privada y pública

ConsultaClave pública

ClienteClave pública

PedidosClave pública

{ “aud”:”consulta", }

Page 73: Asegurando APIs en Symfony con JWT

MicroserviciosAuth

Clave privada y pública

ConsultaClave pública

ClienteClave pública

PedidosClave pública

{ “aud”:”consulta", }

Page 74: Asegurando APIs en Symfony con JWT

MicroserviciosAuth

Clave privada

Consulta

ClienteClave pública

Clave pública

Pedidos

Gateway

Page 75: Asegurando APIs en Symfony con JWT

Soporte en PHP

Page 76: Asegurando APIs en Symfony con JWT
Page 77: Asegurando APIs en Symfony con JWT
Page 78: Asegurando APIs en Symfony con JWT

lcobucci/jwt

Page 79: Asegurando APIs en Symfony con JWT

Crear tokensuse Lcobucci\JWT\Builder;use Lcobucci\JWT\Signer\Keychain;use Lcobucci\JWT\Signer\Rsa\Sha256;

$signer = new Sha256();$keychain = new Keychain();$privateKey = $keychain->getPrivateKey('file://path');

$token = (new Builder())->setIssuer('http://example.com') ->setAudience('http://example.org') ->setId('4f1g23a12aa', true) ->setIssuedAt(time()) ->setNotBefore(time() + 60) ->setExpiration(time() + 3600) ->set('uid', 1) ->sign($signer, $privateKey) ->getToken();

Page 80: Asegurando APIs en Symfony con JWT

Validar tokensuse Lcobucci\JWT\Signer\Keychain;use Lcobucci\JWT\Signer\Rsa\Sha256;use Lcobucci\JWT\ValidationData;

$signer = new Sha256();$keychain = new Keychain();$publicKey = $keychain->getPublicKey('file://path');

$data = new ValidationData();$data->setIssuer('http://example.com');$data->setAudience('http://example.org');$data->setId('4f1g23a12aa');

$token->validate($data);$token->verify($signer, $publicKey);

Page 81: Asegurando APIs en Symfony con JWT

LexikJWTAuthenticationBundle

Page 82: Asegurando APIs en Symfony con JWT

Instalación

composer require lexik/jwt-authentication-bundle

$bundles = array( // ... new Lexik\Bundle\JWTAuthenticationBundle\LexikJWTAuthenticationBundle(), // ...);

app/config/AppKernel.php

Page 83: Asegurando APIs en Symfony con JWT

Crear claves

$ openssl genrsa -out var/jwt/private.pem -aes256 4096 $ openssl rsa -pubout -in app/jwt/private.pem -out var/jwt/public.pem

Page 84: Asegurando APIs en Symfony con JWT

Crear claves

$ openssl genrsa -out var/jwt/private.pem -aes256 4096 $ openssl rsa -pubout -in app/jwt/private.pem -out var/jwt/public.pem

Clave privada

Page 85: Asegurando APIs en Symfony con JWT

Crear claves

$ openssl genrsa -out var/jwt/private.pem -aes256 4096 $ openssl rsa -pubout -in app/jwt/private.pem -out var/jwt/public.pem

Clave privada

Clave pública

Page 86: Asegurando APIs en Symfony con JWT

Configuraciónapp/config/parameters.yml

app/config/config.yml

lexik_jwt_authentication: private_key_path: %jwt_private_key_path% public_key_path: %jwt_public_key_path% pass_phrase: %jwt_key_pass_phrase% token_ttl: %jwt_token_ttl%

parameters: jwt_private_key_path: '%kernel.root_dir%/../var/jwt/private.pem' jwt_public_key_path: '%kernel.root_dir%/../var/jwt/public.pem' jwt_key_pass_phrase: patata jwt_token_ttl: 3600

Page 87: Asegurando APIs en Symfony con JWT

Configuraciónapp/config/parameters.yml

app/config/config.yml

lexik_jwt_authentication: private_key_path: %jwt_private_key_path% public_key_path: %jwt_public_key_path% pass_phrase: %jwt_key_pass_phrase% token_ttl: %jwt_token_ttl% encoder: service: lexik_jwt_authentication.encoder.lcobucci

parameters: jwt_private_key_path: '%kernel.root_dir%/../var/jwt/private.pem' jwt_public_key_path: '%kernel.root_dir%/../var/jwt/public.pem' jwt_key_pass_phrase: patata jwt_token_ttl: 3600

Page 88: Asegurando APIs en Symfony con JWT

Configuraciónapp/config/parameters.yml

app/config/config.yml

lexik_jwt_authentication: private_key_path: %jwt_private_key_path% public_key_path: %jwt_public_key_path% pass_phrase: %jwt_key_pass_phrase% token_ttl: %jwt_token_ttl% encoder: service: lexik_jwt_authentication.encoder.lcobucci

parameters: jwt_private_key_path: '%kernel.root_dir%/../var/jwt/private.pem' jwt_public_key_path: '%kernel.root_dir%/../var/jwt/public.pem' jwt_key_pass_phrase: patata jwt_token_ttl: 3600

Probablemente será default en algún punto

Page 89: Asegurando APIs en Symfony con JWT

firewalls: login: pattern: ^/api/login stateless: true anonymous: true form_login: check_path: /api/login_check success_handler: lexik_jwt_authentication.handler.authentication_success failure_handler: lexik_jwt_authentication.handler.authentication_failure require_previous_session: false

api: pattern: ^/api stateless: true guard: authenticators: - lexik_jwt_authentication.jwt_token_authenticator

Security configapp/config/security.yml

Page 90: Asegurando APIs en Symfony con JWT

firewalls: login: pattern: ^/api/login stateless: true anonymous: true form_login: check_path: /api/login_check success_handler: lexik_jwt_authentication.handler.authentication_success failure_handler: lexik_jwt_authentication.handler.authentication_failure require_previous_session: false

api: pattern: ^/api stateless: true guard: authenticators: - lexik_jwt_authentication.jwt_token_authenticator

Security configapp/config/security.yml

No asigna cookies

Page 91: Asegurando APIs en Symfony con JWT

Routing config

app/config/routing.ymlapi_login_check: path: /api/login_check

Page 92: Asegurando APIs en Symfony con JWT
Page 93: Asegurando APIs en Symfony con JWT

Extender el bundle

Page 94: Asegurando APIs en Symfony con JWT

EventosJWT_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

Page 95: Asegurando APIs en Symfony con JWT

Añadir/quitar datos a payloadclass JWTCreatedListener{ public function onJWTCreated(JWTCreatedEvent $event) { $payload = $event->getData(); $user = $event->getUser(); if ($user->canOrder()) { $payload['aud'] = ‘pedidos'; }

$event->setData($payload); }}

Page 96: Asegurando APIs en Symfony con JWT

Comprobaciones extraclass JWTDecodedListener{ public function onJWTDecoded(JWTDecodedEvent $event) { $payload = $event->getPayload();

if (!isset($payload['aud']) || $payload['aud'] !== 'pedidos') { $event->markAsInvalid(); } }}

Page 97: Asegurando APIs en Symfony con JWT

Añadir atributo API a Token Sfclass 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'); }}

Page 98: Asegurando APIs en Symfony con JWT

¿Qué pasa si quiero…?

Tener diferentes estrategias en distintos firewalls Hacer algo muy particular

Page 99: Asegurando APIs en Symfony con JWT

Security

Page 100: Asegurando APIs en Symfony con JWT

AuthenticationProviderInterface

Security

Page 101: Asegurando APIs en Symfony con JWT

AuthenticationProviderInterface

UserProvider

Security

Page 102: Asegurando APIs en Symfony con JWT

AuthenticationEntryPointInterface

AuthenticationProviderInterface

UserProvider

Security

Page 103: Asegurando APIs en Symfony con JWT

AuthenticationListener

AuthenticationEntryPointInterface

AuthenticationProviderInterface

UserProvider

Security

Page 104: Asegurando APIs en Symfony con JWT

AuthenticationListener

AuthenticationEntryPointInterface

AuthenticationProviderInterface

UserProvider

Security

Events

Page 105: Asegurando APIs en Symfony con JWT

AuthenticationListener

AuthenticationEntryPointInterface

AuthenticationProviderInterface

UserProvider

Security

EventsUserInterface

Page 106: Asegurando APIs en Symfony con JWT

AuthenticationListener

AuthenticationEntryPointInterface

AuthenticationProviderInterface

AbstractToken

UserProvider

Security

EventsUserInterface

Page 107: Asegurando APIs en Symfony con JWT

AuthenticationListener

AuthenticationEntryPointInterface

AuthenticationProviderInterface

AbstractToken

UserProvider

Security

VotersEvents

UserInterface

Page 108: Asegurando APIs en Symfony con JWT

UserProvider

Page 109: Asegurando APIs en Symfony con JWT

UserProvider

Page 110: Asegurando APIs en Symfony con JWT

👌

Page 111: Asegurando APIs en Symfony con JWT

AuthenticationListener

AuthenticationEntryPointInterface

AuthenticationProviderInterface

AbstractToken

UserProvider

Security

VotersEvents

UserInterface

Page 112: Asegurando APIs en Symfony con JWT

Guard💂

Page 113: Asegurando APIs en Symfony con JWT

👌

Page 114: Asegurando APIs en Symfony con JWT

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();}

Page 115: Asegurando APIs en Symfony con JWT

La interfaz GuardAuthenticatorgetCredentials

getUser

checkCredentials

createAuthenticatedToken

onAuthenticationFailure

onAuthenticationSuccess

supportsRememberMe

Page 116: Asegurando APIs en Symfony con JWT

La interfaz GuardAuthenticatorgetCredentials

getUser

checkCredentials

createAuthenticatedToken

onAuthenticationFailure

onAuthenticationSuccess

supportsRememberMe

Validar token

Page 117: Asegurando APIs en Symfony con JWT

La interfaz GuardAuthenticatorgetCredentials

getUser

checkCredentials

createAuthenticatedToken

onAuthenticationFailure

onAuthenticationSuccess

supportsRememberMe

Validar token

Obtener usuario a partir de JWT

Page 118: Asegurando APIs en Symfony con JWT

La interfaz GuardAuthenticatorgetCredentials

getUser

checkCredentials

createAuthenticatedToken

onAuthenticationFailure

onAuthenticationSuccess

supportsRememberMe

Validar token

Obtener usuario a partir de JWT

true

Page 119: Asegurando APIs en Symfony con JWT

La interfaz GuardAuthenticatorgetCredentials

getUser

checkCredentials

createAuthenticatedToken

onAuthenticationFailure

onAuthenticationSuccess

supportsRememberMe

Validar token

Obtener usuario a partir de JWT

true

Crear token de Symfony (no JWT)

Page 120: Asegurando APIs en Symfony con JWT

La interfaz GuardAuthenticatorgetCredentials

getUser

checkCredentials

createAuthenticatedToken

onAuthenticationFailure

onAuthenticationSuccess

supportsRememberMe

Devolver respuesta adecuada

Validar token

Obtener usuario a partir de JWT

true

Crear token de Symfony (no JWT)

Page 121: Asegurando APIs en Symfony con JWT

La interfaz GuardAuthenticatorgetCredentials

getUser

checkCredentials

createAuthenticatedToken

onAuthenticationFailure

onAuthenticationSuccess

supportsRememberMe

No hacer nada

Devolver respuesta adecuada

Validar token

Obtener usuario a partir de JWT

true

Crear token de Symfony (no JWT)

Page 122: Asegurando APIs en Symfony con JWT

La interfaz GuardAuthenticatorgetCredentials

getUser

checkCredentials

createAuthenticatedToken

onAuthenticationFailure

onAuthenticationSuccess

supportsRememberMe false

No hacer nada

Devolver respuesta adecuada

Validar token

Obtener usuario a partir de JWT

true

Crear token de Symfony (no JWT)

Page 123: Asegurando APIs en Symfony con JWT

La interfaz GuardAuthenticatorgetCredentials

getUser

checkCredentials

createAuthenticatedToken

onAuthenticationFailure

onAuthenticationSuccess

supportsRememberMe false

No hacer nada

Devolver respuesta adecuada

Validar token

Obtener usuario a partir de JWT

true

Crear token de Symfony (no JWT)

Page 124: Asegurando APIs en Symfony con JWT

JWTTokenAuthenticator

use Lexik\Bundle\JWTAuthenticationBundle\Security\Guard\JWTTokenAuthenticator as BaseAuthenticator;

class MiTokenAuthenticator extends BaseAuthenticator{}

security: # ... firewalls: # ... otra_api: pattern: ^/otraapi stateless: true guard: authenticators: - app.mi_token_authenticator

Page 125: Asegurando APIs en Symfony con JWT

FAQ

Page 126: Asegurando APIs en Symfony con JWT

Oauth vs JWT? Oauth + JWT?

Page 127: Asegurando APIs en Symfony con JWT

Usos fuera de headers

token_extractors: authorization_header: enabled: true prefix: Bearer name: Authorization cookie: enabled: false name: BEARER query_parameter: enabled: false name: bearer

Page 128: Asegurando APIs en Symfony con JWT

Cuántos datos caben en un token?

https://www.flickr.com/photos/highwaysagency/6008275527

Page 129: Asegurando APIs en Symfony con JWT

Invalidar tokens

Page 130: Asegurando APIs en Symfony con JWT

Enlaces con caducidad

$user = $this->getUser();$jwtManager = $this->get('lexik_jwt_authentication.jwt_manager');$token2 = $jwtManager->create($user);

<a href="{{ path('reset_password', {'bearer':authToken.credentials}) }}”> Reset password</a>

Controlador

Vista

Page 131: Asegurando APIs en Symfony con JWT

Renovar tokens

👌

Page 132: Asegurando APIs en Symfony con JWT

Impersonar usuarios en APIs

👌

Page 133: Asegurando APIs en Symfony con JWT

Impersonar usuarios en APIs

HEADER:X-Switch-User: johndoe

Page 134: Asegurando APIs en Symfony con JWT

Requests a otros dominios

👌

Page 135: Asegurando APIs en Symfony con JWT

Ejemplo de uso con React

Page 136: Asegurando APIs en Symfony con JWT
Page 137: Asegurando APIs en Symfony con JWT
Page 138: Asegurando APIs en Symfony con JWT

¡Gracias!@nacmartin

[email protected]

http://limenius.com Formación, consultoría

y desarrollo de proyectos