Mais conteúdo relacionado Semelhante a 2017 Devoxx MA Deconstructing and Evolving REST Security (20) Mais de David Blevins (8) 2017 Devoxx MA Deconstructing and Evolving REST Security3. #RESTSecurity @dblevins @tomitribe
Focus Areas
• Beyond Basic Auth
• Theory of OAuth 2.0
• Introduc?on of JWT
• Google/Facebook style API security
• Stateless vs Stateful Architecture
• HTTP Signatures
• Amazon EC2 style API security
6. #RESTSecurity @dblevins @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}}
18. #RESTSecurity @dblevins @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
19. #RESTSecurity @dblevins @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"}}
20. #RESTSecurity @dblevins @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"}}
21. #RESTSecurity @dblevins @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"}}
22. #RESTSecurity @dblevins @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"}}
23. #RESTSecurity @dblevins @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"}}
25. #RESTSecurity @dblevins @tomitribe
OAuth 2 - Refresh Grant
(LDAP)
(Token Store)
Verify
Password
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",
}
26. #RESTSecurity @dblevins @tomitribe
Old pair
• Access Token 2YotnFZFEjr1zCsicMWpAA
• Refresh Token tGzv3JOkF0XG5Qx2TlKWIA
New pair
• Access Token 6Fe4jd7TmdE5yW2q0y6W2w
• Refresh Token hyT5rw1QNh5Ttg2hdtR54e
27. #RESTSecurity @dblevins @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"}}
28. #RESTSecurity @dblevins @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"}}
29. #RESTSecurity @dblevins @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"}}
36. #RESTSecurity @dblevins @tomitribe
OAuth 2
Tokens Sent
3000 TPS
(HTTP+SSL)
IP
whitelis?ng
3000 TPS
(token checks)
Password Sent
1000/daily
(HTTP+SSL)
OAuth 2
(LDAP)
12000 TPS
(token checks)
8 hops
24000 TPS
backend
37. #RESTSecurity @dblevins @tomitribe
OAuth 2
Tokens Sent
3000 TPS
(HTTP+SSL)
IP
whitelis?ng
3000 TPS
(token checks)
Password Sent
1000/daily
(HTTP+SSL)
OAuth 2
(LDAP)
12000 TPS
(token checks)
8 hops
24000 TPS
backend
55% of all traffic
38. #RESTSecurity @dblevins @tomitribe
OAuth 2
Tokens Sent
3000 TPS
(HTTP+SSL)
IP
whitelis?ng
0 TPS
(token checks)
Password Sent
1000/daily
(HTTP+SSL)
OAuth 2
(LDAP)
0 TPS
(token checks)
0 hops
0 TPS
backend
51. #RESTSecurity @dblevins @tomitribe
Encoding a Hash or Signature
Binary 0010100011010111110000011011000100101000110011100111010010001000
0100011011011010000000100011110100111111010100011000100011010001
1101101001010101111100010011111110100000001001100010000000010111
0000000000100101000010110011000100001001011011010111101111101101
Hex 8af5c1468a399708b12d205e7ec588c52dd547fe0232027400526846485bef5b
Base64 ivXBRoo5lwixLSBefsWIxS3VR_4CMgJ0AFJoRkhb71s
Base85 MY4eTME."/Yq7))I`7,^/_*Aj!sh!!)dK"86bOe~
55. #RESTSecurity @dblevins @tomitribe
Access Token Now
• eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlb
i10eXBlIjoiYWNjZXNzLXRva2VuIiwidXNlcm5hbWUiOiJ
zbm9vcHkiLCJhbmltYWwiOiJiZWFnbGUiLCJpc3MiOiJod
HRwczovL2RlbW8uc3VwZXJiaXouY29tL29hdXRoMi90b2t
lbiIsInNjb3BlcyI6WyJ0d2l0dGVyIiwibWFucy1iZXN0L
WZyaWVuZCJdLCJleHAiOjE0NzQyODA5NjMsImlhdCI6MTQ
3NDI3OTE2MywianRpIjoiNjY4ODFiMDY4YjI0OWFkOSJ9.
DTfSdMzIIsC0j8z3icRdYO1GaMGl6j1I_2DBjiiHW9vmDz
8OAw8Jh8DpO32fv0vICc0hb4F0QCD3KQnv8GVM73kSYaOE
UwlW0k1TaElxc43_Ocxm1F5IUNZvzlLJ_ksFXGDL_cuadh
VDaiqmhct098ocefuv08TdzRxqYoEqYNo
56. #RESTSecurity @dblevins @tomitribe
Access Token Now
• header (JSON > Base64 URL Encoded)
• describes how the token signature can be checked
• payload (JSON > Base64 URL Encoded)
• Basically a map of whatever you want to put in it
• Some standard entries such as expira?on
• signature (Binary > Base64 URL Encoded
• The actual digital signature
• made exclusively by the /oauth2/token endpoint
• If RSA, can be checked by anyone
57. #RESTSecurity @dblevins @tomitribe
• { "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_2DBjiiHW9vmDz8OAw8Jh8DpO32f
v0vICc0hb4F0QCD3KQnv8GVM73kSYaOEUwlW0k1TaElxc43_Ocxm1F5IUNZv
zlLJ_ksFXGDL_cuadhVDaiqmhct098ocefuv08TdzRxqYoEqYNo
73. #RESTSecurity @dblevins @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",
}
74. #RESTSecurity @dblevins @tomitribe
OAuth 2.0 Message with JWT
POST /painter/color/palele HTTP/1.1
Host: api.superbiz.io
Authorization: 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"}}
75. #RESTSecurity @dblevins @tomitribe
OAuth 2 + JWT
Tokens Sent
3000 TPS
(HTTP+SSL)
0.55 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)
79. #RESTSecurity @dblevins @tomitribe
OAuth 2 + JWT
Valid
Tokens Sent
3000 TPS
(HTTP+SSL)
0.55 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)
81. #RESTSecurity @dblevins @tomitribe
HTTP Signatures
• No “secret” ever hits the wire
• Signs the message itself
• Proves iden?ty
• Prevents message tampering
• Symmetric or Asymmetric signatures
• IETF Drat
• hlps://tools.ieu.org/html/drat-cavage-hlp-signatures
• Extremely simple
• Does NOT eliminate benefits of JWT
82. #RESTSecurity @dblevins @tomitribe
Signature Message
POST /painter/color/palele HTTP/1.1
Host: api.superbiz.io
Authoriza?on: Signature keyId=“my-key-name",
algorithm="hmac-sha256",
headers="content-length host date (request-target)”,
signature="j050ZC4iWDW40nVx2oVwBEymXzwvsgm+hKBkuw04b+w="
Date: Mon, 19 Sep 2016 16:51:35 PDT
Accept: */*
Content-Type: applica?on/json
Content-Length: 46
{"color":{"b":0,"g":255,"r":0,"name":"green"}}
83. #RESTSecurity @dblevins @tomitribe
Signature closeup
Signature
keyId=“my-key-name",
algorithm="hmac-sha256",
headers="content-length host date (request-target)”,
signature="j050ZC4iWDW40nVx2oVwBEymXzwvsgm+hKBkuw04b+w=
89. #RESTSecurity @dblevins @tomitribe
{ "alg": “RS256", "typ": “JWT" }
{ "token-type": "access-token",
"username": "snoopy",
"iss": "hlps://demo.superbiz.com/oauth2/token",
"scopes": ["twiler”, "mans-best-friend"],
"exp": 1474280963,
"iat": 1474279163,
"j?": "66881b068b249ad9"
}
DTfSdMzIIsC0j8z3icRdYO1GaMGl6j1I_2DBjiiHW9vmDz8OAw8Jh8DpO32fv0vICc
0hb4F0QCD3KQnv8GVM73kSYaOEUwlW0k1TaElxc43_Ocxm1F5IUNZvzlLJ_ksFX
GDL_cuadhVDaiqmhct098ocefuv08TdzRxqYoEqYNo
Access Token
90. #RESTSecurity @dblevins @tomitribe
{ "alg": “RS256", "typ": “JWT" }
{ "token-type": "pop",
"cnf":{ "kid": "green-1234" }
"username": "snoopy",
"iss": "hlps://demo.superbiz.com/oauth2/token",
"scopes": ["twiler”, "mans-best-friend"],
"exp": 1474280963,
"iat": 1474279163,
"j?": "66881b068b249ad9"
}
DTfSdMzIIsC0j8z3icRdYO1GaMGl6j1I_2DBjiiHW9vmDz8OAw8Jh8DpO32fv0vICc
0hb4F0QCD3KQnv8GVM73kSYaOEUwlW0k1TaElxc43_Ocxm1F5IUNZvzlLJ_ksFX
GDL_cuadhVDaiqmhct098ocefuv08TdzRxqYoEqYNo
Access Token
91. #RESTSecurity @dblevins @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":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc
3MiOiJodHRwczovL3NlcnZlci5leGFtcGxlLmNvbSIsImV4cCI6M
TMxMTI4MTk3MCwiaWF0IjoxMzExMjgwOTcwLCJjbmYiOnsia2",
"token_type":"pop",
"expires_in":3600,
"refresh_token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc
3MiOiJodHRwczovL2FzZGZhc2RzZGZzZXJ2ZXIuZXhhbXBsZS5
jb20iLCJleHAiOjEzMTEyODE5NzAsImlhdCI6MTMxMTI4MDk3M",
"key":"eyJrdHkiOiJvY3QiLCJ1c2UiOiJzaWciLCJraWQiOiJvcmFuZ
2UteXlqOUQwZWgiLCJrIjoiVlotMFFHTFoyUF9SUFVTVzEwQ0l1
MFdNeVhxLU5EMnBtRFl6QTBPVEtXVEhscDVpYWM1SzRWZWlS
ci1fQk9vWEo0WDJmU1R0NG5Id29fcXV0YTdqSkpLVDRQRVd5W
WFuQlNGc2kwRFc3b3dULUhFeEFHRHlKdEhVdE53NXhzczhOajZ
PeE5QdjZyUk9FLWtldmhMMndCOWNxZ2RJc2NidkRocmFzMzljd
2ZzIiwiYWxnIjoiSFMyNTYifQ"
}
Generate
HMAC
Key
(Key Store)
92. #RESTSecurity @dblevins @tomitribe
JSON Web Key (encoded)
eyJrdHkiOiJvY3QiLCJ1c2UiOiJzaWciLCJraWQiOiJvcmFuZ2Ute
XlqOUQwZWgiLCJrIjoiVlotMFFHTFoyUF9SUFVTVzEwQ0l1MF
dNeVhxLU5EMnBtRFl6QTBPVEtXVEhscDVpYWM1SzRWZWlS
ci1fQk9vWEo0WDJmU1R0NG5Id29fcXV0YTdqSkpLVDRQRVd
5WWFuQlNGc2kwRFc3b3dULUhFeEFHRHlKdEhVdE53NXhzc
zhOajZPeE5QdjZyUk9FLWtldmhMMndCOWNxZ2RJc2NidkRo
cmFzMzljd2ZzIiwiYWxnIjoiSFMyNTYifQ
93. #RESTSecurity @dblevins @tomitribe
JSON Web Key (decoded)
{ "kty": "oct",
"use": "sig",
"kid": "orange-1234",
"k": "VZ-0QGLZ2P_RPUSW10CIu0WMyXq-ND2pmDYzA0OTKW
THlp5iac5K4VeiRr-_BOoXJ4X2fSTt4nHwo_quta7j
JJKT4PEWyYanBSFsi0DW7owT-HExAGDyJtHUtNw5xs
s8Nj6OxNPv6rROE-kevhL2wB9cqgdIscbvDhras39c
wfs",
"alg": "HS256"
}
94. #RESTSecurity @dblevins @tomitribe
Signed OAuth 2.0 Message
POST /painter/color/palele HTTP/1.1
Host: api.superbiz.io
Authoriza?on: Signature keyId=“orange-1234", algorithm="hmac-sha256",
headers="content-length host date (request-target)”,
signature="j050ZC4iWDW40nVx2oVwBEymXzwvsgm+hKBkuw04b+w="
Bearer: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbi10eXBlIjoiYWNjZXNzLXRva2VuIiwidXNlcm5h
bWUiOiJzbm9vcHkiLCJhbmltYWwiOiJiZWFnbGUiLCJpc3MiOiJodHRwczovL2RlbW8uc3VwZXJiaXouY29tL2
9hdXRoMi90b2tlbiIsInNjb3BlcyI6WyJ0d2l0dGVyIiwibWFucy1iZXN0LWZyaWVuZCJdLCJleHAiOjE0NzQyO
DA5NjMsImlhdCI6MTQ3NDI3OTE2MywianRpIjoiNjY4ODFiMDY4YjI0OWFkOSJ9.DTfSdMzIIsC0j8z3icRdY
O1GMGl6j1I_2DBjiiHW9vmDz8OAw8Jh8DpO32fv0vICc0hb4F0QCD3KQnv8GVM73kSYaOEUwlW0k1TaE
lxc43_Ocxm1F5IUNZvzlLJ_ksFXGDL_cuadhVDaiqmhct098ocefuv08TdzRxqYoEqYNo
Date: Mon, 19 Sep 2016 16:51:35 PDT
Accept: */*
Content-Type: applica?on/json
Content-Length: 46
{"color":{"b":0,"g":255,"r":0,"name":"green"}}
95. #RESTSecurity @dblevins @tomitribe
OAuth 2 + JWT + Signatures
Tokens Sent
3000 TPS
(HTTP+SSL)
0.55 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)
97. #RESTSecurity @dblevins @tomitribe
Observations
• HTTP Signatures the only HTTP friendly approach
• Signatures does not solve the “Iden?ty Load” problem
• OAuth 2 with JWT significantly improves IDP load
• Plain OAuth 2
• HTTP Session-like implica?ons
• OAuth 2 with JWT
• Signed cookie
• Signing key to the future