Beyond OAuth2: End to End Microservice Security
William Tran, Principal Software Engineer, Pivotal
Twitter: @fivetenwill
github.com/william-tran/microxchg2017
About Me
The What and Why of Microservices
What do microservices look like?
What do microservice organizations look like?
Why microservices? Speed to production.
The Challenges of Securing Microservices
Mo' Processes, Mo' Problems.
OAuth2 to the rescue?
App
Auth Server
Resource
Browser makes a request to the App
/
OAuth2 to the rescue?
App redirects to Auth Server. User authenticates.
/authorize
App
Auth Server
Resource
OAuth2 to the rescue?
Auth Server redirects back to App with an Authorization Code.
/callback?code=xyz
App
Auth Server
Resource
OAuth2 to the rescue?
App gives Authorization Code to Auth Server
/oauth/token?code=
App
Auth Server
Resource
OAuth2 to the rescue?
Auth Server responds with JWT representing the user. App validates JWT.
App stores JWT in session. Browser's session is now authenticated.
JWT
App
Auth Server
Resource
OAuth2 to the rescue?
App uses JWT to request the Resource on behalf of User.
Resource validates JWT.
/api (JWT in header)
App
Auth Server
Resource
OAuth2 to the rescue?
data
homepage
Resource responds with data, and App renders page.
App
Auth Server
Resource
The limits of OAuth2
/feature2
Browser makes another request for some feature.
App
Auth Server
Resource
The limits of OAuth2
/api/2 (JWT in header)
App uses JWT stored in session to make another request to Resource.
App
Auth Server
Resource
The limits of OAuth2
A
... (same JWT in headers)
Resource validates JWT.
Resource reuses JWT for downstream requests.
B
App
Auth Server
Resource
The limits of OAuth2
App
Auth Server
Resource
A
... (same JWT in headers)
And the same JWT continues to be propagated and reused.
B
C
D
One token to rule them all!
Token Propagation
New Tokens via Client Credentials Grant
App
Auth Server
Resource
/api/2 (JWT in header)
App uses JWT stored in session to make another request to Resource.
New Tokens via Client Credentials Grant
App
Auth Server
Resource
/oauth/token
Resource requests a new token to use downstream via Client Credentials grant type.
New Tokens via Client Credentials Grant
App
Auth Server
Resource
JWT for Resource
Resource receives a JWT representing itself.
New Tokens via Client Credentials Grant
App
Auth Server
Resource
Resource uses its JWT for downstream requests.
A and B can authenticate the request as coming from Resource.
Resource says it's acting on behalf of the User.
A
... (Resource JWT in headers)
B
Confused deputy attack
Total (and misplaced) trust in the real world
60%
Of all attackers are "insiders"
Don't let one bad apple spoil the whole bunch.
Confused deputy mitigations
New Tokens via Token Exchange
New Tokens via Token Exchange
App
Auth Server
Resource
/api/2 (JWT in header)
App uses JWT stored in session to make another request to Resource.
New Tokens via Token Exchange
App
Auth Server
Resource
/oauth/token
Resource requests a new token to use downstream via Token Exchange grant type.
Resource provides its own client credentials, the user's JWT it received, and the Service(s) it wants to hit.
New Tokens via Client Credentials Grant
App
Auth Server
Resource
JWT for User + Resource meant for (A,B)
Resource receives a JWT representing both itself and the User, which can be used for A and B
New Tokens via Client Credentials Grant
App
Auth Server
Resource
Resource uses the JWT in requests to A and B
A and B can authenticate the request as coming from Resource, acting on behalf of the User, and meant for those services.
A
... (Resource + User JWT in headers)
B
New Tokens via Token Exchange
More trust boundaries,
different problems.
New Tokens via Token Exchange
Pros:
Cons:
More processes,
more than just auth problems.
Message Security
HTTPS Everywhere
Shop
Cart
Payments
Shop provides UI and API facade to Cart.
User enters credit card info and hits the confirm payment button.
HTTPS provides confidentiality and integrity between browser and Shop.
/checkout/confirm
8152 4444 1234 5678
HTTPS Everywhere
Shop
Cart
Payments
Cart provides checkout functionality.
Shop passes the CC info to Cart.
HTTPS provides confidentiality and integrity between Shop and Cart.
/cart/confirm
8152 4444 1234 5678
HTTPS Everywhere
Shop
Cart
Payments
Cart calls Payments to settle the order, providing the CC info.
HTTPS provides confidentiality and integrity between Cart and Payments.
/pay-for-order/12345
8152 4444 1234 5678
HTTPS everywhere doesn't solve everything
End-to-End Message Security
Solution Goals
A Possible Solution
Disclaimer
JOSE:
JOSE to the rescue
JOSE for Message Security
Keypairs from where?
Service Discovery
Service Registry
Service Registry and Trust
Trusted Service Registries and Service Identity
Service Discovery = Identity + Location.
It must be trustworthy.
Sign All Of The Things
Verify All Of The Things
Encrypt Some Of The Things
Message Security: that was easy
Are we there yet?
Decentralize & Embed
All Of The Things
Self Issued JWT
Single Use JWT
Nested, Self Issued JWT
Chain Truncation
Cart JWT
Shop JWT
Shop
Cart
Payments
User JWT
Shop JWT
User JWT
1
2
Shop JWT
User JWT
3
Preventing Chain Truncation With JWS Envelope
Payments Envelope
Cart Envelope
Shop Envelope
Cart JWT
Shop JWT
Shop
Cart
Payments
User JWT
Shop JWT
User JWT
1
2
Shop JWT
User JWT
3
Example Nested JWT + Service Registry
{
"alg": "RS256",
"typ": "JWT"
}
{� "jti" : "ddd",� "sub" : "2938409238502935",� "scope" : [ "openid", "shop.customer" ],� "cid" : "shop",� "grant_type" : "authorization_code",� "user_name" : "marissa",� "iat" : 1477523159,� "exp" : 1477566359,� "iss" : "https://uaa.shop.com/oauth/token",� "aud" : [ "openid", "shop" ]�}
[signature of JWT]
Token received by Shop from AS
{
"alg": "RS256",
"typ": "JWT"
}
{
"ini": "eyJhbGciOi...",
"jti": "eee",
"iss": "123",
"aud": "CART",
"op": "POST /cart/confirm",
"iat": 1477523259,
"exp": 1477523264,
"bdy": true
}
[signature of JWT]
Token received by Cart
{
"alg": "RS256",
"typ": "JWT"
}
{
"jwt": "eyJhbGciOi...",
"jti": "fff",
"iss": "456",
"aud": "PAYMENTS",
"op": "POST /pay-for-order/12345",
"iat": 1477523260,
"exp": 1477523274,
"bdy": true
}
[signature of JWT]
Token received by Payments
Instance ID | App Name | Location | Metadata |
123 | SHOP | 10.0.0.4:12380 | public_key: … |
456 | CART | 10.0.0.5:45034 | public_key: ... |
789 | PAYMENTS | 10.0.0.6:25303 | public_key: … |
Externalized Policy, Embedded Decisionmaking
Example Policy (for Payments)
security:
policy:
for-each-of-the-following:
- enforce-the-first-matching-rule:
- tokens-that:
have-operation:
matching: "POST /pay-for-order/.*"
must:
have-initial-token:
where-scope-contains:
value: shop.customer
come-from:
- app-name: CART
- app-name: SHOP
via-operation:
equal-to: POST /cart/confirm
Example Nested JWT + Service Registry
{
"alg": "RS256",
"typ": "JWT"
}
{� "jti" : "ddd",� "sub" : "2938409238502935",� "scope" : [ "openid", "shop.customer" ],� "cid" : "shop",� "grant_type" : "authorization_code",� "user_name" : "marissa",� "iat" : 1477523159,� "exp" : 1477566359,� "iss" : "https://uaa.shop.com/oauth/token",� "aud" : [ "openid", "shop" ]�}
[signature of JWT]
Token received by Shop from AS
{
"alg": "RS256",
"typ": "JWT"
}
{
"ini": "eyJhbGciOi...",
"jti": "eee",
"iss": "123",
"aud": "CART",
"op": "POST /cart/confirm",
"iat": 1477523259,
"exp": 1477523264,
"bdy": true
}
[signature of JWT]
Token received by Cart
{
"alg": "RS256",
"typ": "JWT"
}
{
"jwt": "eyJhbGciOi...",
"jti": "fff",
"iss": "456",
"aud": "PAYMENTS",
"op": "POST /pay-for-order/12345",
"iat": 1477523260,
"exp": 1477523274,
"bdy": true
}
[signature of JWT]
Token received by Payments
Instance ID | App Name | Location | Metadata |
123 | SHOP | 10.0.0.4:12380 | public_key: … |
456 | CART | 10.0.0.5:45034 | public_key: ... |
789 | PAYMENTS | 10.0.0.6:25303 | public_key: … |
Advances use cases
Demo Time!
Demo goals
Coming Soon...
Coming Maybe...
Watch this space:
github.com
/pivotal-cf-experimental
/spring-cloud-services-security
Stay In Touch
William Tran
Principal Software Engineer
Pivotal
github.com/william-tran
linkedin.com/in/fivetenwill
@fivetenwill
wtran@pivotal.io
The Gory Details
Risks
The Authorization Server
A new token for every request
Preventing reuse and replay with jti and exp
Guaranteed non replay
Limit the token's power
Link the Token to the JWS Body
Custom Claims
Example Nested JWT
{
"alg": "RS256",
"typ": "JWT"
}
{
"ini": "eyJhbGciOi...",
"jti": "0120124b-5f4c-4791-99c4-28bc062eb9ef",
"iss": "6366d4ae-7f65-4b73-83f5-8ec0c84e8200",
"aud": "FUNDS-TRANSFER",
"req": "POST /api/funds-transfer",
"iat": 1477523159,
"exp": 1477523164,
"bdy": true,
"ip": "123.123.123.123"
}
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJqd3QiOiJleUpoYkdjaU9pLi4uIiwianRpIjoiYWVkOTZkODYtODU2MC00MmRmLTg4NjAtNzNkMzE4ZWNhOWIwIiwiaXNzIjoiOTc0MWRmMWItYTY1Mi00ZTY2LTg0MzEtMDAyNGZkYzFlNDkyIiwiYXVkIjoiRlVORFMtVFJBTlNGRVIiLCJyZXEiOiJHRVQgL2FwaS9hY2NvdW50cz90eXBlPXRyYWRpbmciLCJpYXQiOjE0Nzc1MjMxNTksImV4cCI6MTQ3NzU2NjM1OSwiaXAiOiIxMjMuMzIxLjEyMy4zMjEifQ.0AwnQzABbqQM2qpawQW9fwL3fzTk1ZfHHSHRMeuY1ogx-ic-2_HpU5PqGDTo-jq9q1Ep7C6FZQ4McS7_zr5RGt2YP2P5qc43yD3HM4WQrZ88Ilv-e-ZQzXCSBSzINIXp1JUl6TNQBneMIF5O_BxMLQK-IuqblL2dA_Q9jznr9YxS8qrQ74kCJPlldxjXD-TZEDCuc22hlOgAkJGlAPt7XchGqo4w1D3IiANFxIOVOj3y3kpyds-G8m_yZMIdC6Aqov7FCf4HWXitIZqOdHaJA8R1fnoC54LtO3bOcvwp6Tt-bo1PxjBwkjd9hE1ea5QQ9_hy-PGzSuA1H3sFt06OCQ
Example Corresponding JWS Body
{
"alg": "RS256",
"typ": "JOSE",
"jti": "0120124b-5f4c-4791-99c4-28bc062eb9ef",
"cty": "application/json"
}
{
"account_from": "123",
"account_to": "456",
"amount": "1000"
}
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpPU0UiLCJqdGkiOiI1NjJmNmE3Yi02MmI1LTQwYjAtOTQ3Yi02M2MxOTk1NzdkNjYiLCJjdHkiOiJhcHBsaWNhdGlvbi9qc29uIn0.eyJhY2NvdW50X2Zyb20iOiIxMjMiLCJhY2NvdW50X3RvIjoiNDU2IiwiYW1vdW50IjoiMTAwMCJ9.S1tZw-yGSXRP9zH72RKZ7Vsdl71sGHspWqquxjKbrqp-s7zx2BcjCbvuxKITpvMabB_xQ5EeMrgpKgn4b8YLahQpTshw_m9xxoCVUmo4IMQObUVGBXQuBxQPwDiYl-13CuNgeCpIEm7xCJNEorVhZhmV5FYuS-Qe3SONSgy0SwQLZDta0PAtC2vsaIezUiciErgAmRFa9wjOKS0IGqSeWueuGoBbGx8KoWMio-kacqnTV9b_ROT7tAtMdc8rNRfCAdn72QDtE18nWE7cSDQxu3BKpj8Vod1De1I3N0adJ_7UW5s_KEppDm2y2MelCo0sy2IFYl7MCuB8XDgW4I0_PQ
Fire Away
Repeat
Token Size
Token Size