5

I am currently working on migrating our users from an internal DB to an OIDC service (considering Cognito/Auth0/etc.), and I am trying to implement RBAC.

Our backend is basically a bunch of microservices, and I am trying to understand how we can manage the ACL of our service without having each service implement its own solution on the one hand, and having a central service that they will all have to call (single point of failure).

What we're imagining the solution to look like, is having a JWT Access Token that is signed and holds all the user permissions as its claims, but it seems like we are missing something since I cannot seem to find an implementation that does it.

I did see that I can add these claims to the ID Token, but as I understand it, the ID token should not be passed as an Acces Token. Am I missing something? how is it usually done in microservices environments?

Edit: Seems like Auth0 supports our use case and Cognito doesn't... That still leaves the question whether it's a good idea to implement it the way we're planning

Tomer Amir
  • 171
  • 7
  • 2
    Be mindful of 'token bloat' whereby a token contains too many claims / assertions. Generally, try to make the OAuth tokens only contain identity information (e.g. a user's role or department) but not their permissions. Use XACML or ALFA for fine-grained authorization API-side. – David Brossard Apr 02 '19 at 01:22
  • 1
    @DavidBrossard, It would be a bit strange to use an OAuth2 token for identification purposes, given that OAuth2 is a protocol for the delegation of authorization. – Jacco Jun 04 '19 at 13:32
  • Think Open ID Connect – David Brossard Jun 04 '19 at 13:33
  • OAuth 2.0 is indeed originally for authorization delegation but it's been abused for authentication – David Brossard Jun 04 '19 at 13:34
  • I you mean OpenID connect, it would be handy if you name it as such. And yes, OAuth2 is often times abused for authentication. This is exactly why we should be precise in our terminology, or risk becoming a source of incorrect security advice. – Jacco Jun 04 '19 at 13:37

2 Answers2

3

ID token and Access Token serve two different purposes in OIDC.

  • ID Token = For ascertaining Identity of the user. Who the user is? What is their email address?

  • Access Token = For ascertaining if the user is allowed to have access. If the Access Token signature is valid, then allow access. Typically contains the information needed to ascertain access (e.g. some identity info, roles, sometimes permissions, etc.)

For access related claims, you should only add them to the Access Token, unless those are "identity claims (e.g. address)"

As far as a separate authorization service is concerned, I think if your application does not deal with a high number of permissions and roles, then it is OK to simply add them as claims to the Access Token.

If there are very high number of roles and permissions, this will lead to token bloat (as mentioned in David's comment). In this case a separate authorization service makes sense. This authorization service should do the roles to permission mapping and provide an API to evaluate permissions. Keep the roles for the user in the Access Token. When a permission is evaluated, check the access token for the roles and determine the permission validity. Remember to pass around the access token when evaluating a permission. How common is this method? ONAP seems to use a similar approach.

bhorkarg
  • 432
  • 2
  • 12
0

I'm no expert -- but here goes.

The JWT access token is issued to a user post-authentication, meaning you've already validated the username/password of the user (and perhaps some 2FA pieces as well).

The secret-sauce of JWTs are that they are signed (either with symmetric or as asymmetric encryption). Which means that anyone can validate the JWT if they have the shared-private key or the public key (depending on which encryption type was used).

This removes the need for a single service to check the users session-ids or similar tokens, since the issuing of the JWT can be separated from the validation of the JWT.

In the case of asymetric encryption, all an API endpoint really needs is the public key, and some logic to determine if the scope of the token allows access to it. Which will handle both the authentication and authorization of the API.

But this has a downside, what happens if a JWT token gets lost -- how do you reset user sessions and force users to logon again?

To do this, we use the concept of an access token and a refresh token. An access token is what is provided on each API request, and usually has a lifespan of 15 minutes. This is handle by the issuing service setting an expiry on the token that is validated by each endpoint.

The refresh token is not meant to be passed around to API, but used only once when the access token has expired (or is nearly expiring). The refresh token is passed onto the authentication to obtain a new pair of both tokens.

This allows us to kill the refresh tokens on the issuing service and force all users to re-authenticate in case of an emergency -- of course the change doesn't happen immediately, but would take the lifespan of the token to come into effect. If you had a shared DB holding the session IDs, this would typically be immediate -- but that's the downside of not having a single point of failure.

I'm not sure where an ID Token comes in though -- but what I suspect is that it's something to do with OpenID and not necessarily JWT authentication. Hope that helps.

keithRozario
  • 3,571
  • 2
  • 12
  • 24