ODCTour18LAD
#RESTSecurity @otaviojava @tomitribe
Stateless Microservice Security
via JWT and MicroProfile
∙ Otávio Santana @otaviojava
∙ Tomitribe
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
Otávio Santana
∙Senior Software Engineer at Tomitribe
∙Java Champion & Developer Champion
∙Duke’s Choice Award 2016 y 2017
∙Apache and Eclipse Commiter
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
“Lo mejor de los standares es que terminas
teniendo muchas opciones por escoger.”
- Andrew S. Tanenbaum
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
“Lo mejor de los standares es que terminas
teniendo muchas opciones por escogerThe nice
thing about standards is
you have so many to choose from.”
- Andrew S. Tanenbaum
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
Opciones de seguridad para
Microservicios
● Más allá de Basic Auth
● Teoría de OAuth 2.0
● Introducción a JWT
● Eclipse Microprofile
● Demo
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD Línea Base
1000 usuarios
x 3 TPS
4 saltos
3000 TPS
frontend
12000
TPS
backend
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
Basic Auth
(y sus problemas)
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
Mensaje en Basic Auth
POST /painter/color/object HTTP/1.1
Host: localhost:8443
Authorization: Basic c25vb3B5OnBhc3M=
User-Agent: curl/7.43.0
Accept: */*
Content-Type: application/json
Content-Length: 45
{"color":{"b":255,"g":0,"name":"blue","r":0}}
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD Basic Auth
Password Sent
3000 TPS
(HTTP+SSL)
username+password
Base64 (no auth)
(LDAP)
12000
TPS
(HTTP)
3000 TPS
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD Basic Auth
Password Sent
3000 TPS
(HTTP+SSL)
username+password
Base64
username+password
Base64
15000 TPS
(LDAP)
Password Sent
12000
TPS
(HTTP)
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD Basic Auth
Password Sent
3000 TPS
(HTTP+SSL)
username+password
Base64
Lista Blanca
de IP
3000 TPS
(LDAP)
12000
TPS
(HTTP)
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
“Dame toda la
información del
salario de José.” “No se quien
eres,
…
pero por
supuesto!”
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD Ataque de fuerza bruta: Basic Auth
Password
válidos
3000
TPS
(HTTP+SSL)
Lista
Blanca IP
9000 TPS
(LDAP)
12000
TPS
(HTTP)
Passwords
inválidos
6000
TPS
(HTTP+SSL)
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
OAuth 2.0
(y sus problemas)
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
OAuth 2 - Password Grant
(LDAP)
(Repositorio
de Token)
Verificación
de
Password
Generación de
Token
Post /oauth2/token
Host: api.superbliz.io
User-Agent: curl/7.43.0
Accept: */*
Content-Type: application/x-www-form-urlencoded
Content-Length: 54
grand_type=password&username=snoopy&password=woodstock
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
OAuth 2 - Password Grant
(LDAP)
Verificación
de
Password
Generación de
Token
(Repositorio
de Token)
Post /oauth2/token
Host: api.superbliz.io
User-Agent: curl/7.43.0
Accept: */*
Content-Type: application/x-www-form-urlencoded
Content-Length: 54
grand_type=password&username=snoopy&password=woodstock
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
Mensaje OAuth 2.0
POST /painter/color/object HTTP/1.1
Host: api.superbiz.io
Authorization: Bearer 2YotnFZFEjr1zCsicMWpAA
User-Agent: curl/7.43.0
Accept: */*
Content-Type: application/json
Content-Length: 45
{"color":{"r":0,"g":0,"b":255,"name":"blue"}}
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
Mensaje OAuth 2.0
POST /painter/color/palette HTTP/1.1
Host: api.superbiz.io
Authorization: Bearer 2YotnFZFEjr1zCsicMWpAA
User-Agent: curl/7.43.0
Accept: */*
Content-Type: application/json
Content-Length: 45
{"color":{"r":0,"g":255,"b":0,"name":"green"}}
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
Mensaje OAuth 2.0
POST /painter/color/select HTTP/1.1
Host: api.superbiz.io
Authorization: Bearer 2YotnFZFEjr1zCsicMWpAA
User-Agent: curl/7.43.0
Accept: */*
Content-Type: application/json
Content-Length: 44
{"color":{"r":255,"g":0,"b":0,"name":"red"}}
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
Mensaje OAuth 2.0
POST /painter/color/fill HTTP/1.1
Host: api.superbiz.io
Authorization: Bearer 2YotnFZFEjr1zCsicMWpAA
User-Agent: curl/7.43.0
Accept: */*
Content-Type: application/json
Content-Length: 49
{"color":{"r":0,"g":255,"b":255,"name":"yellow"}}
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
Mensaje OAuth 2.0
POST /painter/color/stroke HTTP/1.1
Host: api.superbiz.io
Authorization: Bearer 2YotnFZFEjr1zCsicMWpAA
User-Agent: curl/7.43.0
Accept: */*
Content-Type: application/json
Content-Length: 49
{"color":{"r":255,"g":200,"b":255,"name":"orange"}}
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
OAuth 2 - Refresh Grant
(LDAP)
Verificación
Password
Generación
Token
(Repositorio
de Token)
Post /oauth2/token
Host: api.superbliz.io
User-Agent: curl/7.43.0
Accept: */*
Content-Type: application/x-www-form-urlencoded
Content-Length: 54
grand_type=password&username=snoopy&password=woodstock
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
OAuth 2 - Refresh Grant
(LDAP)
Verificación
Password
Generación
Token
(Repositorio
de Token)
Post /oauth2/token
Host: api.superbliz.io
User-Agent: curl/7.43.0
Accept: */*
Content-Type: application/x-www-form-urlencoded
Content-Length: 54
grand_type=password&username=snoopy&password=woodstock
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
Par anterior
∙ Access Token 2YotnFZFEjr1zCsicMWpAA
∙ Refresh Token tGzv3JOkF0XG5Qx2TlKWIA
Nuevo Par
∙ Access Token
6Fe4jd7TmdE5yW2q0y6W2w
∙ Refresh Token hyT5rw1QNh5Ttg2hdtR54e
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
Mensaje OAuth 2.0
POST /painter/color/palette HTTP/1.1
Host: api.superbiz.io
Authorization: Bearer 6Fe4jd7TmdE5yW2q0y6W2w
User-Agent: curl/7.43.0
Accept: */*
Content-Type: application/json
Content-Length: 46
{"color":{"r":0,"g":255,"b":0,"name":"green"}}
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
Mensaje OAuth 2.0
POST /painter/color/select HTTP/1.1
Host: api.superbiz.io
Authorization: Bearer 6Fe4jd7TmdE5yW2q0y6W2w
User-Agent: curl/7.43.0
Accept: */*
Content-Type: application/json
Content-Length: 44
{"color":{"r":255,"g":0,"b":0,"name":"red"}}
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
Mensaje OAuth 2.0
POST /painter/color/fill HTTP/1.1
Host: api.superbiz.io
Authorization: Bearer 6Fe4jd7TmdE5yW2q0y6W2w
User-Agent: curl/7.43.0
Accept: */*
Content-Type: application/json
Content-Length: 49
{"color":{"r":0,"g":255,"b":255,"name":"yellow"}}
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
¿Qué hemos logrado?
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
Ahora tenemos más passwords
(al menos tus dispositivos los tienen)
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
Terminología de nuevo…
∙ Password Grant???
∙ Logging in
∙ Token?
∙ Un password ligeramente ofuscado
∙ Equivalente a un HTTP session ID mejorado levemente
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD OAuth 2
Request enviados
(Authorization: Bearer …)
3000 TPS
(HTTP+SSL)
3000 TPS
(Verificacione
s
de tokens)
Password enviados
(post oauth2/token …)
1000/daily
(HTTP+SSL)
OAuth 2
(LDAP)
4 saldos
12000
TPS
backend
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
“Quién es
6Fe4jd7TmdE5y
W2q0y6W2w
???????”
“No tengo idea.
Pregúntale al
servidor de
tokens.”
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD OAuth 2
Tokens enviados
3000 TPS
(HTTP+SSL)
3000 TPS
(verificación
token)
Password
Envidados
1000/daily
(HTTP+SSL)
OAuth 2
(LDAP)
12000
TPS
(Verificación
token)
8
Saldos
24000 TPS
backend
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD OAuth 2
3000 TPS
(Verificación
token)
(LDAP)
12000
TPS
(Verificación
token)
55%
del tráfico total
Tokens enviados
3000 TPS
(HTTP+SSL)
Password
Envidados
1000/daily
(HTTP+SSL)
OAuth 2
8
Saldos
24000 TPS
backend
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD OAuth 2
Puntero Puntero
Estado
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
Access Token
Puntero de Acceso?
Llave primaria de Acceso?
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
OAuth 2.0
Algoritmo de intercambio de
passwords de alta frecuencia?
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
OAuth 2.0
+
JSon Web Tokens (JWT)
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
JSon Web Token
∙ Pronunciado “YOT”
∙ JSON map con data de usuario
∙ Códificado Base64
∙ Firmado digitalmente (RSA-SHA256, HMAC-SHA512, etc)
∙ Mecanismo de expiración
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
Previamente un Access Token
∙ 6Fe4jd7TmdE5yW2q0y6W2w
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
Access Token ahora (JWT)
∙ eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbi10eXBlIjoi
YWNjZXNzLXRva2VuIiwidXNlcm5hbWUiOiJzbm9vcHkiLCJhb
mltYWwiOiJiZWFnbGUiLCJpc3MiOiJodHRwczovL2RlbW8uc3V
wZXJiaXouY29tL29hdXRoMi90b2tlbiIsInNjb3BlcyI6WyJ0d2l0d
GVyIiwibWFucy1iZXN0LWZyaWVuZCJdLCJleHAiOjE0NzQyO
DA5NjMsImlhdCI6MTQ3NDI3OTE2MywianRpIjoiNjY4ODFiMD
Y4YjI0OWFkOSJ9.DTfSdMzIIsC0j8z3icRdYO1GaMGl6j1I_2DB
jiiHW9vmDz8OAw8Jh8DpO32fv0vICc0hb4F0QCD3KQnv8GV
M73kSYaOEUwlW0k1TaElxc43_Ocxm1F5IUNZvzlLJ_ksFXGD
L_cuadhVDaiqmhct098ocefuv08TdzRxqYoEqYNo
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD Nuevo Access Token
∙ header (JSON > Base64 URL Encoded)
∙ Describe como la firma (signature) del token puede ser
verificada
∙ payload (JSON > Base64 URL Encoded)
∙ Json map de información que desees incluir
∙ Campo estándar como el de Expiración
∙ signature (Binary > Base64 URL Encoded)
∙ La firma digital
∙ Hecha exclusivamente por el endpoint: /oauth2/token
∙ Si es RSA puede ser verificado por cualquier persona
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD ∙ { "alg": “RS256", "typ": “JWT" }
∙ {
"token-type": "access-token",
"username": "snoopy",
"animal": "beagle",
"iss": "https://demo.superbiz.com/oauth2/token",
"scopes": [
“twitter”, "mans-best-friend"
],
"exp": 1474280963,
"iat": 1474279163,
"jti": "66881b068b249ad9"
}
∙ DTfSdMzIIsC0j8z3icRdYO1GaMGl6j1I_2DBjiiHW9vmDz8OAw8Jh8DpO32fv0vI
Cc0hb4F0QCD3KQnv8GVM73kSYaOEUwlW0k1TaElxc43_Ocxm1F5IUNZvzlLJ
_ksFXGDL_cuadhVDaiqmhct098ocefuv08TdzRxqYoEqYNo
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
Ligero pero con alto impacto en
la arquitectura
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
¿Qué tenemos hasta el
momento?
(repaso)
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
(LDAP)
Data completa
del usuario desde
ldap
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
(LDAP)
Generación de
Access Token
(pointer)
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
(LDAP)
Ambos se
insertan en
BD
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
(LDAP)
Envío del Access Token (pointer)
hacia el cliente
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
Resultado final
cliente permanece
con el Pointer
Server almacena State
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
¿Qué podemos hacer ahora?
(hola JWT!)
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
(LDAP)
Data completa
del usuario desde
ldap
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
(LDAP)
La data se
representa
en JSON
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
(LDAP)
JSON es firmado
RSA-SHA 256
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
(LDAP)
Se inserta
solamente el
pointer en
DB
(para revocaciones)
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
(LDAP)
Envío del Access Token (estado)
hacia el cliente
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
Servidor almacena el
Puntero
Cliente permanece con el
Estado
Resultado obtenido
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
OAuth 2 - Password Grant
(LDAP)
(Repositorio
Token ID)
Verifica
Password
Genera
Token
Firmado
(Signed)
Post /oauth2/token
Host: api.superbliz.io
User-Agent: curl/7.43.0
Accept: */*
Content-Type: application/x-www-form-urlencoded
Content-Length: 54
grand_type=password&username=snoopy&password=woodstock
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
OAuth 2 - Password Grant
(LDAP)
Verifica
Password
(Repositorio
Token ID)
Genera
Token
Firmado
(Signed)
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
Mensaje OAuth 2.0 con JWT
POST /painter/color/palette HTTP/1.1
Host: api.superbiz.io
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbi10eXBlIjoiYWNjZXNzLXR
va2VuIiwidXNlcm5hbWUiOiJzbm9vcHkiLCJhbmltYWwiOiJiZWFnbGUiLCJpc3MiOiJodHRwczovL2RlbW8uc3VwZXJ
iaXouY29tL29hdXRoMi90b2tlbiIsInNjb3BlcyI6WyJ0d2l0dGVyIiwibWFucy1iZXN0LWZyaWVuZCJdLCJleHAiOjE0NzQ
y
ODA5NjMsImlhdCI6MTQ3NDI3OTE2MywianRpIjoiNjY4ODFiMDY4YjI0OWFkOSJ9.DTfSdMzIIsC0j8z3icRdYO1GaMGl
6j1I_2DBjiiHW9vmDz8OAw8Jh8DpO32fv0vICc0hb4F0QCD3KQnv8GVM73kSYaOEUwlW0k1TaElxc43_Ocxm1F5IUNZ
vzlLJ_ksFXGDL_cuadhVDaiqmhct098ocefuv08TdzRxqYoEqYNo
User-Agent: curl/7.43.0
Accept: */*
Content-Type: application/json
Content-Length: 46
{"color":{"b":0,"g":255,"r":0,"name":"green"}}
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD OAuth 2 + JWT
Tokens
enviados
3000 TPS
(HTTP+SSL)
0.55 TPS
(Verificaciones
refresh token)
OAuth
2
(LDAP)
4 saltos
12000 TPS
backend
3000 TPS
(verifica firma)
12000 TPS
(verifica firma)
Password enviados
(post oauth2/token …)
1000/daily
(HTTP+SSL)
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
“No!”
“Dame toda la
información del
salario de José.”
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
“Claro!”
“Dame toda la
información del
salario de José.”
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
OAuth 2 + JWT
Envío de
Tokens válidos
3000 TPS
(HTTP+SSL)
IP
whitelisting
0.55 TPS
(verifica refresh token)
Password enviados
1000/daily
(HTTP+SSL)
(LDAP)
4 saltos
12000 TPS
backend
9000 TPS
(verifica firma)
12000 TPS
(verifica firma)
Token inválidos
6000 TPS
(HTTP+SSL)
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
https://connect2id.com/products/nimbus-jose-jwt
Librería JWT
https://github.com/jwtk/jjwt
https://github.com/auth0/java-jwt
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
Eclipse MicroProfile
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
MicroProfile
∙ Comunidad Open-Source de la fundación Eclipse
∙ Enfocada en Microservicios bajo JavaEE
∙ Generadora de: Specificaciones, API y TCK.
∙ Implementado por diferentes entidades
http://microprofile.io/
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
MicroProfile JWT
MicroProfile 2.0
JAX-RS 2.1JSON-P 1.1CDI 2.0
Config 1.3
Fault
Tolerance
1.1
JWT
RBAC 1.1
Health
Check 1.0
Metrics 1.1
Open
Tracing 1.1
Open API
1.0
Rest Client
1.1
JSON-B 1.0
JWT
RBAC 1.1
https://microprofile.io/project/eclipse/microprofile-jwt-auth/
Standares de Seguridad
● OAuth 2.0
● OpenID Connect
● JSON Web Tokens
(JWT)
Tecnologías Java
● JAX-RS
● CDI
● JSON-P.
Demo
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
#RESTSecurity @otaviojava @tomitribe
ODCTour18LAD
Moviefun Diagrama de Despliegue
Gateway
Gracias

Stateless Microservice Security via JWT and MicroProfile - Mexico