Home > Software engineering >  Add additional inner user validation after successful OAuth2 Resource Server JWT check at Keycloak
Add additional inner user validation after successful OAuth2 Resource Server JWT check at Keycloak

Time:01-21

There is a Spring boot app with endpoints protected with JWT. Token validation is performed by Spring boot OAuth2 Resource Server that checks tokens at Keycloak Authorization Server. How can additional inner user validation be added to the app after it successfully passes authorization at Keycloak?

So I'd like to build some kind of a chain - if token passes validation at Auth Server then I check the username taken from JWT at local database.

CodePudding user response:

Checking access-token claims against local database for access-control on a resource-server is very inefficient: it is much better to have this DB access once when the token is created on authorization-server, rather than each time it is evaluated during resource-server authorization process (which happens for each request).

All the data required for access-control decisions should be included in the token already. If you need more than standard claims plus the default private claims for your authorization-server, then configure it to add the data you need about the user when issuing access-tokens. For Keycloak, this is done with so called "OIDC protocol mappers". Those can issue DB requests, web-service calls and about anything. I have a sample of a mapper adding a private claim with a value from a web-service call in this project.

Once all the data you need is in the token, you just use it as normal in Spring security expressions of your resource-server. Here is a working sample taken from my set of tutorials:

@PreAuthorize("is(#username) or isNice() or onBehalfOf(#username).can('greet')")

In this expression, it is checked that the user either:

  • is greeting himself (username @PathVariable is equal to preferred_username claim in access-token)
  • has one of "nice" roles
  • has permission to greet on behalf of user with preferred_username equal to username @PathVariable (the route is /greet/{username} and this permissions delegation is taken from a private claim added by a mapper like the one in the sample linked above)
  • Related