QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
Stateless Microservice Security via JWT, TomEE and MicroProfile
Jean-Louis Monteiro Tomitribe
Stateless Microservice Security via QCON SP JWT, TomEE and - - PowerPoint PPT Presentation
Stateless Microservice Security via QCON SP JWT, TomEE and MicroProfile Jean-Louis Monteiro Tomitribe #RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe Why am I here today? QCON SP Microservices architecture case Security opEons OAuth2
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
Stateless Microservice Security via JWT, TomEE and MicroProfile
Jean-Louis Monteiro Tomitribe
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
Microservices architecture case Security opEons OAuth2 with JWT HTTP Signatures Demo with MP-JWT and TomEE
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
(SOA with a sexy name)
@dblevins @tomitribe
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
TradiEonal system
Component A Component B Component C Component D System
(Monolithic)
@dblevins @tomitribe
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
… with tradiEonal scalability
@dblevins @tomitribe
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
… with tradiEonal scalability
@dblevins @tomitribe
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
… with tradiEonal scalability
@dblevins @tomitribe
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
… with tradiEonal scalability
@dblevins @tomitribe
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
… and its tradiEonal security
@dblevins @tomitribe
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
What to expect from microservices?
@dblevins @tomitribe
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
Microservices - the technical perspecEve
@dblevins @tomitribe
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
The organizaEonal perspecEve
@dblevins @tomitribe
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
But there are new challenges
@dblevins @tomitribe
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
Baseline Architecture
1000 users x 3 TPS 4 hops 3000 TPS
frontend
12000 TPS
backend
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
@dblevins @tomitribe
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
OpEons
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
“The nice thing about standards is you have so many to choose from.”
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
(and its problems)
@dblevins @tomitribe
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
Basic Auth Message
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}}
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
Basic Auth
Password Sent
3000 TPS
(HTTP+SSL)
username+password Base64 (no auth)
3000 TPS
(LDAP)
12000 TPS
(HTTP)
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
Basic Auth
Password Sent
3000 TPS
(HTTP+SSL)
username+password Base64 username+password Base64
15000 TPS
(LDAP) Password Sent
12000 TPS
(HTTP)
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
Basic Auth - ATacks
Valid Password Sent
3000 TPS
(HTTP+SSL)
No auth
9000 TPS
(LDAP)
12000 TPS
(HTTP) Invalid Password Sent
6000 TPS
(HTTP+SSL)
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
(and its problems)
@dblevins @tomitribe
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
The theory behind it
@dblevins @tomitribe
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
Based on tokens
@dblevins @tomitribe
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
Based on tokens
@dblevins @tomitribe
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
Based on tokens
@dblevins @tomitribe
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
OAuth 2 - Password Grant
(LDAP) (Token Store)
POST /oauth2/token
Host: api.superbiz.io User-Agent: curl/7.43.0 Accept: */* Content-Type: application/x-www-form-urlencoded Content-Length: 54 grant_type=password&username=snoopy&password=woodstock
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8 Cache-Control: no-store Pragma: no-cache { "access_token":"2YotnFZFEjr1zCsicMWpAA", "expires_in":3600, "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA", }
Verify Password Generate Token
@dblevins @tomitribe
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
OAuth 2.0 Message
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"}}
@dblevins @tomitribe
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
OAuth 2.0 Message
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"}}
@dblevins @tomitribe
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
OAuth 2.0 Message
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"}}
@dblevins @tomitribe
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
OAuth 2.0 Message
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"}}
@dblevins @tomitribe
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
OAuth 2.0 Message
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"}}
@dblevins @tomitribe
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
@dblevins @tomitribe
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
OAuth 2 - Refresh Grant
(LDAP) (Token Store) Verify and Generate Token
POST /oauth2/token
Host: api.superbiz.io User-Agent: curl/7.43.0 Accept: */* Content-Type: application/x-www-form-urlencoded Content-Length: 54 grant_type=refresh_token&refresh_token=tGzv3JOkF0XG5Qx2TlKWIA
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8 Cache-Control: no-store Pragma: no-cache { "access_token":"6Fe4jd7TmdE5yW2q0y6W2w", "expires_in":3600, "refresh_token":"hyT5rw1QNh5Ttg2hdtR54e", }
@dblevins @tomitribe
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe Old pair
New pair
@dblevins @tomitribe
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
OAuth 2.0 Message
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"}}
@dblevins @tomitribe
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
OAuth 2.0 Message
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"}}
@dblevins @tomitribe
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
OAuth 2.0 Message
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"}}
@dblevins @tomitribe
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
What have we achieved?
side
@dblevins @tomitribe
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
New terms, really?
@dblevins @tomitribe
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
OAuth 2
Tokens Sent
3000 TPS
(HTTP+SSL)
No auth
3000 TPS
(token checks) Password Sent
1000/daily
(HTTP+SSL)
OAuth 2
(LDAP)
4 hops 12000 TPS
backend
@dblevins @tomitribe
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
OAuth 2
Tokens Sent
3000 TPS
(HTTP+SSL)
3000 TPS
(token checks) Password Sent
1000/daily
(HTTP+SSL)
OAuth 2
(LDAP)
12000 TPS
(token checks) backend
@dblevins @tomitribe
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
OAuth 2
Tokens Sent
3000 TPS
(HTTP+SSL)
3000 TPS
(token checks) Password Sent
1000/daily
(HTTP+SSL)
OAuth 2
(LDAP)
12000 TPS
(token checks) backend
@dblevins @tomitribe
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
OAuth 2
Tokens Sent
3000 TPS
(HTTP+SSL)
0 TPS
(token checks) Password Sent
1000/daily
(HTTP+SSL)
OAuth 2
(LDAP)
0 TPS
(token checks)
0 hops 0 TPS
backend
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
@dblevins @tomitribe
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
JSON Web Token
@dblevins @tomitribe
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
Access Token Previously
@dblevins @tomitribe
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
Access Token Now
10eXBlIjoiYWNjZXNzLXRva2VuIiwidXNlcm5hbWUiOiJzb m9vcHkiLCJhbmltYWwiOiJiZWFnbGUiLCJpc3MiOiJodHRw czovL2RlbW8uc3VwZXJiaXouY29tL29hdXRoMi90b2tlbiI sInNjb3BlcyI6WyJ0d2l0dGVyIiwibWFucy1iZXN0LWZyaW VuZCJdLCJleHAiOjE0NzQyODA5NjMsImlhdCI6MTQ3NDI3O TE2MywianRpIjoiNjY4ODFiMDY4YjI0OWFkOSJ9.DTfSdMz IIsC0j8z3icRdYO1GaMGl6j1I_2DBjiiHW9vmDz8OAw8Jh8 DpO32fv0vICc0hb4F0QCD3KQnv8GVM73kSYaOEUwlW0k1Ta Elxc43_Ocxm1F5IUNZvzlLJ_ksFXGDL_cuadhVDaiqmhct0 98ocefuv08TdzRxqYoEqYNo
@dblevins @tomitribe
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
Access Token Now
"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" }
KQnv8GVM73kSYaOEUwlW0k1TaElxc43_Ocxm1F5IUNZvzlLJ_ksFXGDL_cuadhVDaiqmhct098oc efuv08TdzRxqYoEqYNo
@dblevins @tomitribe
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
Access Token Now
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
(quick recap)
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
(LDAP) Pull User Info From IDP
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
(LDAP) Generate an Access Token (pointer)
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
(LDAP) Insert both into DB
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
(LDAP) Send Access Token (pointer) to client
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
Results
Client Holds Pointer Server Holds State
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
(Hello JWT!)
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
(LDAP) Pull User Info From IDP
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
(LDAP) Format the data as JSON
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
(LDAP) RSA-SHA 256 sign JSON
private
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
(LDAP) Insert only pointer into DB (for revoca9on)
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
(LDAP) Send Access Token (state) to client
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe Client Holds State Server Holds Pointer
Desired Results
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
OAuth 2 - Password Grant
(LDAP) (Token ID Store)
POST /oauth2/token
Host: api.superbiz.io User-Agent: curl/7.43.0 Accept: */* Content-Type: application/x-www-form-urlencoded Content-Length: 54 grant_type=password&username=snoopy&password=woodstock
Verify Password Generate Signed Token
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8 Cache-Control: no-store Pragma: no-cache { "access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9. eyJ0b2tlbi10eXBlIjoiYWNjZXNzLXRva2VuIiwidXNlcm5hb WUiOiJzbm9vcHkiLCJhbmltYWwiOiJiZWFnbGUiLCJpc3M iOiJodHRwczovL2RlbW8uc3VwZXJiaXouY29tL29hdXRoM i90b2tlbiIsInNjb3BlcyI6WyJ0d2l0dGVyIiwibWFucy1iZXN0 LWZyaWVuZCJdLCJleHAiOjE0NzQyODA5NjMsImlhdCI6M TQ3NDI3OTE2MywianRpIjoiNjY4ODFiMDY4YjI0OWFkOSJ 9.DTfSdMzIIsC0j8z3icRdYO1GaMGl6j1I_2DBjiiHW9vmDz8 OAw8Jh8DpO32fv0vICc0hb4F0QCD3KQnv8GVM73kSYaO EUwlW0k1TaElxc43_Ocxm1F5IUNZvzlLJ_ksFXGDL_cuadh VDaiqmhct098ocefuv08TdzRxqYoEqYNo", "expires_in":3600, "refresh_token":"eyJhbGctGzv3JOkF0XG5Qx2TlKWIAkF0X. eyJ0b2tlbi10eXBlIjoiYWNjZXNzLXRva2VuIiwidXNlcm5hb WUiOiJzbm9vcHkiLCJhbmltYWwiOiJiZWFnbGUiLCJpc3M iOiJodHRwczovL", }@dblevins @tomitribe
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
OAuth 2.0 Message with JWT
POST /painter/color/palene HTTP/1.1 Host: api.superbiz.io AuthorizaEon: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbi10eXBlIjoiYWNjZXNzLXR
va2VuIiwidXNlcm5hbWUiOiJzbm9vcHkiLCJhbmltYWwiOiJiZWFnbGUiLCJpc3MiOiJodHRwczovL2RlbW8uc3VwZXJ iaXouY29tL29hdXRoMi90b2tlbiIsInNjb3BlcyI6WyJ0d2l0dGVyIiwibWFucy1iZXN0LWZyaWVuZCJdLCJleHAiOjE0NzQy ODA5NjMsImlhdCI6MTQ3NDI3OTE2MywianRpIjoiNjY4ODFiMDY4YjI0OWFkOSJ9.DTfSdMzIIsC0j8z3icRdYO1GaMGl 6j1I_2DBjiiHW9vmDz8OAw8Jh8DpO32fv0vICc0hb4F0QCD3KQnv8GVM73kSYaOEUwlW0k1TaElxc43_Ocxm1F5IUNZ vzlLJ_ksFXGDL_cuadhVDaiqmhct098ocefuv08TdzRxqYoEqYNo
User-Agent: curl/7.43.0 Accept: */* Content-Type: applica/on/json Content-Length: 46 {"color":{"b":0,"g":255,"r":0,"name":"green"}}
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
OAuth 2 + JWT
Tokens Sent
3000 TPS
(HTTP+SSL)
0.27 TPS
(refresh token checks) Password Sent
1000/daily
(HTTP+SSL)
OAuth 2
(LDAP)
4 hops 12000 TPS
backend
3000 TPS
(signature verifica/on)
12000 TPS
(signature verifica/on)
(private key) (public key)QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
OAuth 2 + JWT
Valid Tokens Sent
3000 TPS
(HTTP+SSL)
0.27 TPS
(refresh token checks) Password Sent
1000/daily
(HTTP+SSL) (LDAP)
4 hops 12000 TPS
backend
9000 TPS
(signature verifica/on)
12000 TPS
(signature verifica/on) Invalid Tokens Sent
6000 TPS
(HTTP+SSL)
(private key) (public key)#RESTSecurity
@dblevins @tomitribe
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
@dblevins @tomitribe
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
What is it?
/microprofile.io/
@dblevins @tomitribe
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
Where are we at?
Open Tracing, Open API and REST Client
@dblevins @tomitribe
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
Who is involved?
@dblevins @tomitribe
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
Why?
@dblevins @tomitribe
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
What implementaEons?
@dblevins @tomitribe
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
Microprofile JWT
@dblevins @tomitribe
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
Goals
#RESTSecurity
@dblevins @tomitribe
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
QCON SP
#RESTSecurityWithMP-JWT @JLouisMonteiro @tomitribe
http://tribestream.io http://tomitribe.io http://microprofile.io