Monolith to Microservices – Securing w/OAuth, OpenID Connect, JWT

From IIW

Monolith to Microservices

Wednesday 2C Convener: Will Tran

Notes-taker(s): Will Tran

Tags for the session - technology discussed/ideas considered:

  1. OAuth2, #JWT, #Microservices

Discussion notes, key understandings, outstanding questions, observations, and, if appropriate to this discussion: action items, next steps:

Microservices:

What do they look like?

  • HTTP based (mostly)
  • Do one thing well
  • Bounded context
  • well defined APIs
  • independently deployable modules
  • Dimension of business capability

What do teams look like?

  • Pizza box sized teams
  • Agile methodology

What do you get?

  • Velocity
    • lower team communication overhead (smaller teams and well defined boundaries of responsibility)
    • enables continuous delivery
    • teams focused on a smaller domain can iterate faster

Note: I thought Alan was being sarcastic when he called out some of these things with “that’s not obvious” but my sarcasm meter may have been over sensitive so I tried to finish up this section as quickly as possible. Recommended reading if you need more details or convincing: http://pivotal.io/platform/migrating-to-cloud-native-application-architectures-ebook

How to get there:

Full Rewrite -> not very agile

Take a business capability that is ripe for evolution. Maybe a new capability, or an existing capability that you want add lots of features to. This becomes your first microservice.

What that looks like: Assumptions: AS, Client and Resources are all owned by the same entity, e.g. a mobile banking app. Trust cannot be assumed between the applications or teams that deliver them. All apps trust the AS however.

Step 0:

Mobile App (Client)

get a token (e.g. via authcode grant like https://developer.pingidentity.com/en/resources/napps-native-app-sso.html)

Should this be opaque or JWT? If the body is sensitive, make it opaque.

Authorization Server (AS/OP)

  • determines the token’s scopes

monolith (Resource)

  • verifies identity through /userinfo
  • verifies scope through token introspection

Step 1: Add Offers Resource (e.g. sign up for this credit card)

  • Should the Mobile app use the same token for both the monolith and Offers?
    • No. This would violate the principle of least privilege, as the monolith could reuse that token to access offers directly and vice versa.
  • Should the Mobile app get a token use the same token for both the monolith and Offers?
    • No. This would tightly couple the mobile app to implementation details.
  • Solution: Use an API gateway
    • API Gateway exchanges the opaque token for a JWT (e.g. ID Token with scopes) whose scope and audience is restricted to only the resource to be accessed.

Step 2: Add Analytics Resource (app -> GW -> Offers -> Analytics)

  • Does the GW get a token can can be used for Analytics?
    • No, that would violate principle of least privilege. Analytics should only be accessed by Offers
    • Offers exchanges the token it receives for a new one whose scopes and audience are restricted to only allow interaction with Analytics.

How to transform tokens?

Opaque <-> JWT at the gateway

  • JWE
  • Maintaining a mapping in the AS (e.g. persisting tokens, and using jti as the opaque value)
  • Could be cached by the GW until the JWT exp

How to exchange tokens?

JWT -> new JWT with different aud and scopes


Questions/Comments

C: JWT verification is hard / I don’t trust my dev’s to do it right. Let something external do it instead

A: It’s easy in Spring Security OAuth (and other libs). Microservices should be as self sufficient as possible. Also we’re assuming these services only trust the AS and don’t trust each other.

C: Or you could use self issued JWT instead of client ID/secret to authenticate clients

A: Yes.

Q: Why don’t you just use PKI?

A: (from audience) not very microservicey, things become tightly coupled and inflexible with PKI Rebuttal from asker: Well that depends…

C: (after the talk) You can use infrastructure e.g. network security groups to enforce trust domains instead

A: This could be enough for some. This is about empowering the application itself to make these decisions. Developers may not have the ability to manage infrastructure to that level. And if you want to move fast, best to reduce the dependencies on things you don’t control as much as possible.

Q: Any best practices on dealing with coarse grained vs fine grained authorization?

A: As an example, you can think of a coarse grained authorization saying “you have the ability to read 1 or more foo”, and fine grained as “you have the ability to read this/these particular foo” both could be expressed as scopes, but this could allow a token’s scope values to get out of hand. You could mitigate this on the token side by asking for the exact scopes you need when you request a token. On the AS, you’d need to supply it this knowledge of the foo you have access to somehow. If you can’t get the AS to deal with that, you could wrap that knowledge around a custom service exposed via some custom API, where the onus is on the resource server to check it; or incorporate another AS that can exchange a token from the first AS and use that knowledge of foos to generate a token containing the fine grained scopes.