0

I started playing with Keycloak, but I have a question. While reading articles, I always found examples where a client (let's say Angular) is logging in on Keycloak, it gets a bearer and then it send the bearer to the SpringBoot application. The backend, so, validates that the bearer is valid and, if so, it allows you accessing the desired endpoint.

But it's not enough in my opinion. I don't need just to login, I would need the entire functionality - let's say I have a backend application and I need a user. I could have a basic todo-application, how do I know for which backend user I am actually accesing an endpoint?

Straight question: how can I bind my own backend user (stored in the DB from backend) to the one from Keycloak?

What is the best way to do it? The only thing that I found online and into the Keycloack documenation is that I could move the logic of logging in from client (Angular) to backend (SpringBoot). Is this the way to go?

Imagine like I'm creating my manual /login endpoint on backend on which I would then call the Keycloak server (Keycloak REST client?) and I would pass myself (as a backend) the bearer to the client.

Please help me with an explanation if I'm right or wrong, what's the best practice, maybe help me with an online example, because I just found out the too easy ones.

Flatron
  • 3
  • 1

3 Answers3

0

The simplest way to do it is to consider that the job of storing users will be delegated to your Keycloak server. But you can implement some roles and checks manually with in-memory or any database of your preference too.

I invite you to follow some documentation about OAuth 2 and Keycloak, to make requests to get a valid token for a time period and to make others request inside that time period to get datas. You can use CURL to make requests or web/software tools like Postman.

Be careful, a lot of Keycloak Adapters are deprecated ones since some months.

BendaThierry.com
  • 2,080
  • 1
  • 15
  • 17
  • 1
    Thanks for your message, appreciate it. I played already a bit with Keycloak, managed to get a token. But still I'm not sure if I was clear enough. I know that the job of storing users and roles is delegated to the Keycloak server. However, if I am user X, what is the best way to tell my backend server that I really am user X? I would like to have a simple endpoint like: /backend/api/todos/{userId}. How can I map my own backend userId (or call it however you want, of course) to the keycloak user? This is what for me it's not clear what's the best practice. – Flatron Feb 04 '23 at 08:28
  • When your application is using these kind of software to delegate stuff, the best practice is to delegate all the user management layer to them. So you get a user repository which can be shared across many web and software applications inside your enterprise. As @ch4mp has said, you should not mobilize a data query on each request only for that. To get your user id, look at the decrypted JWT token which is containing your user information to map roles and privileges. – BendaThierry.com Feb 14 '23 at 09:59
  • Thank you for the answer. I played in the meanwhile with Keycloack and I managed to retrieve the data that I need from the JWT, indeed. I didn't go any further yet, but my plan is to map an email address (from the JWT) to an entity (let's call it user) and play with the backend user id both in frontend and backend. Of course NOT for validating tokens and user management itself, that's the Keycloak part. But I need an entity to identify the real-life-client in my backend application, I don't see how Keycloack would help me without me having my own identifier. Please correct me if I'm wrong. – Flatron Feb 15 '23 at 17:02
0

I would echo BendaThierry's comments. Look into OAuth2 and Keycloak. The Bearer token you receive from Keycloak will have user information in it (typically in the Claims). This way you can have user preferences or features in your backend without needing to manage the authorization and authentication that Keycloak does.

There are lots of great resource include Spring's website tutorials (like https://spring.io/guides/tutorials/spring-boot-oauth2/) and Baeldung (https://www.baeldung.com/).

cneller
  • 1,542
  • 1
  • 15
  • 24
  • Thank you for the answer. I played in the meanwhile with Keycloack and I managed to retrieve the data that I need from the JWT, indeed. I didn't go any further yet, but my plan is to map an email address (from the JWT) to an entity (let's call it user) and play with the backend user id both in frontend and backend. Of course NOT for validating tokens and user management itself, that's the Keycloak part. But I need an entity to identify the real-life-client in my backend application, I don't see how Keycloack would help me without me having my own identifier. Please correct me if I'm wrong. – Flatron Feb 15 '23 at 17:02
  • Yes, I think that's reasonable. You can use the token data and map that to, say, preferences for your back-end application based on email or username or whatever is appropriate for your app. – cneller Feb 22 '23 at 21:17
0

OpenID tokens are rich

Keycloak is an OpenID provider and emits JWTs. You already have the standard OpenID info about user identity in the token (matching requested scopes), plus some Keycloak specific stuff like roles plus whatever you add with "mappers".

All the data required for User Authentication (identity) and Authorization (access-control) should be embedded in access-tokens.

How to bind user data between Keycloak and your backend

In my opinion, the best option is to leave user management to Keycloak (do not duplicate what is already provided by Keycloak). An exception is if you already have a large user database, then you should read the doc or blog posts to bind Keycloak to this DB instead of using its own.

Spring clients and resource-servers configuration

I have detailed that for Spring Boot 3 in this other answer: Use Keycloak Spring Adapter with Spring Boot 3

In addition to explaining configuration with Spring Boot client and resource-server starters, it links to alternate Spring Boot starters which are probably easier to use and more portable (while building on top of spring-boot-starter-oauth2-resource-server).

I Also have a set of tutorials from most basic RBAC to advanced access-control involving the accessed resource itself as well as standard and private OpenID claims from the token (user details) there.

Tokens private claims

For performance reason, it is a waste to query a DB (or call a web-service) when evaluating access-control rules after decoding a JWT: this happens for each request.

It is much more efficient to put this data in the tokens as private claims: this happens only once for each access-token issuance.

Keycloak provides with quite a few "mappers" you can configure to enrich tokens and also allows you to write your own. Sample project with a custom Keycloak mapper here. This is a multi-module maven project composed of:

  • a custom "mapper" responsible for adding a private claim to the tokens
  • a web-service which exposes the data used to set the value of this claim
  • a resource-server reading this private claim to take access-control decisions
ch4mp
  • 6,622
  • 6
  • 29
  • 49
  • Thank you for the answer. I played in the meanwhile with Keycloack and I managed to retrieve the data that I need from the JWT, indeed. I didn't go any further yet, but my plan is to map an email address (from the JWT) to an entity (let's call it user) and play with the backend user id both in frontend and backend. Of course NOT for validating tokens and user management itself, that's the Keycloak part. But I need an entity to identify the real-life-client in my backend application, I don't see how Keycloack would help me without me having my own identifier. Please correct me if I'm wrong. – Flatron Feb 15 '23 at 17:02
  • You mentioned: "it is a waste to query a DB when evaluating access-control rules after decoding a JWT:" --> no, my plan is not to do that at each request, of course. I just want to know this user-id (from my db) into the frontend. I will retrieve it only once, after the login (login being managed by Keycloak, of course). – Flatron Feb 15 '23 at 17:06
  • The OpenID client should have access to the ID token, and as so to the user `subject` as well as potential surrogate keys (`email`, `preferred_username`,...). If the OpenID client is not the UI application consuming the API (case of apps rendered in the browser with BFF pattern), you can have a look at the BFF tutorial linked in my answer. It contains a sample endpoint to reflect user OpenID claims contained in the access token. – ch4mp Feb 15 '23 at 17:17
  • Thanks a lot! I will mark your answer as accepted. – Flatron Feb 15 '23 at 17:41
  • Thks. I edited my answer to enrich it and add external links. I recommand you take time to follow those links... – ch4mp Feb 15 '23 at 18:52