3

I am new to Keycloak and I am looking to integrate it into a system consisting of a frontend (written in Vue.js) and a RESTful Backend service (written in Node.js).

The frontend application communicates with the backend to serve requests. At the moment the application is secured by JWT Tokens and there is no separate identity manager. On first look Keycloak seems a reliable identity and access management system and I am looking to adopt it.

What I am looking for is a solution to provide authentication and authorization using Keycloak. I have read the Keycloak docs and some other answers here on StackOverflow, however I still have a few questions which are not completely clear to me.

  1. Firstly, most of the answers online suggest creating 2 separate clients, one for the frontend (with public access) and one for the backend (confidential client), but it doesn't seem to fit well because Clients are applications and services that can request authentication of a user, but the backend client isn't going to authenticate the user. Only the frontend public client will do that and issue tokens. So is it a good and recommended solution to do it like this?

  2. Secondly, what is the need for 2 clients if the backend service can verify authenticity of tokens via the token introspection API endpoint?

  3. There is the the need for authorization. Permissions can only be defined on confidential clients so you can't really do that in public clients. Preferably resource permissions should be included in the access token, but again you can't do that with a public client. If there is a way to get permissions via Keycloak API, again it wouldn't be the best solution because it would mean hitting the Keycloak API on every request. Sure you can apply caching mechanisms, but it would just add extra unnecessary overhead.

So regarding all these questions, what are the practices to adopt Keycloak in a situation like this.

dreamcrash
  • 47,137
  • 25
  • 94
  • 117
David Prifti
  • 621
  • 2
  • 8
  • 17
  • Can you give me a example of the first claim 1) most of the answers online suggest creating 2 separate clients, one for the frontend (with public access) and one for the backend (confidential client) please, this is very context dependent – dreamcrash Jan 08 '23 at 08:58
  • @dreamcrash Sure. I mostly relied on blog posts and StackOverflow answers. To mention a few: https://medium.com/devops-dudes/secure-front-end-react-js-and-back-end-node-js-express-rest-api-with-keycloak-daf159f0a94e (Medium blog post) https://stackoverflow.com/questions/65009654/how-to-protect-frontend-and-rest-api-with-keycloak https://stackoverflow.com/questions/72147402/oauth-2-0-flow-using-keycloak-with-a-back-end-and-front-end – David Prifti Jan 08 '23 at 09:16

2 Answers2

2

Firstly, most of the answers online suggest creating 2 separate clients, one for the frontend (with public access) and one for the backend (confidential client), but it doesn't seem to fit well because Clients are applications and services that can request authentication of a user, but the backend client isn't going to authenticate the user. Only the frontend public client will do that and issue tokens. So is it a good and recommended solution to do it like this?

As with most cases the answer is it depends. But let us break your statement bit by bit:

Firstly, most of the answers online suggest creating 2 separate clients, one for the frontend (with public access) and one for the backend (confidential client)

I can only speculate here, however, based on the links that you have provided in the comment section:

@dreamcrash Sure. I mostly relied on blog posts and StackOverflow answers. To mention a few: medium.com/devops-dudes/… (Medium blog post) stackoverflow.com/questions/65009654/… stackoverflow.com/questions/72147402/…

If you read carefully the blog and the SO answers on those threads (first and second) they refer to the use of two clients, but those clients are public and bearer-only (not confidential).

(...) but it doesn't seem to fit well because Clients are applications and services that can request authentication of a user,

Not necessary; clients can also so be used solely for the purposes of authorization.

, but the backend client isn't going to authenticate the user.

Maybe not in your case, but a backend client can also be used for user authentication, depending on the use-case in question.

So is it a good and recommended solution to do it like this?

Depends

Typically, such tutorials (e.g., the blog that you referenced) are created to showcase the authentication and authorization capabilities of Keycloak.

The authentication part is showcased by the user authenticating via the browser (using the frontend client), whereas the authorization part is showcased by the application sending an access token to the Keycloak server where the claims on the access token (e.g., roles) can then be used to infer if the user has the permissions to perform the desire action (i.e., authorization).

Technically, even in those use-cases you are not force to use two clients. Alternatively to the approach that I have previously mentioned, one could have had a single client (i.e, the frontend client), and after the user has successfully authenticated, the application would pass the access token to the backend. The backend could then perform the authorization by directly checking, for instance, the roles in the access token, instead of relying on the Keycloak server to do so. There are pros and cons to both approaches.

A typical example where one could have two clients, a public and a confidential one, would be if the backend would be a separated micro-service that triggers some maintenance task for example. Assuming that task is not related at all to the user authentication process, it would make more sense to then have a separate client (in this case a confidential one) that would rely on the client credentials flow which is typically used for machine-to-machine use-cases.

As I have mentioned there are cases that you:

  • only need a public client
  • might need both public and a confidential client
  • you just need a confidential client

For the last case, you can think about a server-side web application, in this case you can use either a public or a confidential client. Since, it is a server-side application (i.e., it can securely store a secret) then one should use a confidential client because (compared with the public client) it adds an extra layer of security (i.e., you also need to provide the client secret) to the authentication process.

Secondly, what is the need for 2 clients if the backend service can verify authenticity of tokens via the token introspection API endpoint?

I feel that this one was also answered. You do not really need to have two clients for this.

There is the the need for authorization. Permissions can only be defined on confidential clients so you can't really do that in public clients. Preferably resource permissions should be included in the access token, but again you can't do that with a public client. If there is a way to get permissions via Keycloak API, again it wouldn't be the best solution because it would mean hitting the Keycloak API on every request. Sure you can apply caching mechanisms, but it would just add extra unnecessary overhead.

I feel that you might be mixing up concepts, namely public and confidential clients vs. frontend and backend. As I have mentioned, you can use public clients on the backend as well, albeit is sub-optimal. Regarding the permissions part, this again depends on the approach that you want to use to handle the authorization concerns, namely handling the authorization on the 1) Keycloak server or 2) in your backend. Have a look a this SO answer to better understand the trade-offs of one approach over the other.

dreamcrash
  • 47,137
  • 25
  • 94
  • 117
1

OIDC and OAuth 2.0 can be used with Keycloak for authentication and authorization respectively.

  1. OIDC (build on top of OAuth 2.0) is recommended for user authentication (SSO) on a frontend where the id token can be exchanged on the backend side for your internal user session. (JWT as a session for users is not the best solution - problem with session renewal, invalidation, storing securely JWT on the frontend, etc.)

For backend services, you should use OAuth 2.0 and i.e. client credentials grant type, where access token can be obtained and then used to communicate between services.

  1. You should not use OAuth 2.0 JWT tokens directly in the frontend application. It was possible with implicit grant type, but was deprecated due to security risks: https://oauth.net/2/grant-types/implicit/ and replaced with authorization code grant used in OIDC.

That's why you need two clients, one public (for the frontend app that is not able to store credentials securely) and one confidential client for backend communication where you can store credentials securely for some services. (Actually, on Keycloak you can have one client with different grant types support i.e. OIDC and client credentials) Moreover, token introspection is just an extension for OAuth 2.0 and is not implemented i.e. by Azure so base token verification can be performed using signature and token claims without additional request to the authorization server.

  1. User permissions to backend services should be defined based on Keycloak roles. With this information, the backend service knows the context and permissions for a particular user so you can restrict or allow access to resources. Permissions on the Keycloak side can be also assigned to scopes and in this scenario, we have two different scopes, OIDC and OAuth 2.0.

To make a final decision I suggest reading about:

  1. JWT pros and cons
  2. JWT vs session-based authentication
  3. OAuth 2.0 and OIDC

Here you can find useful links to RFCs: https://oauth.net/specs/ OAuth 2.0 was not well defined at the beginning so you can find some wrong examples, those RFCs describe problems with the initial OAuth 2.0 framework, new extensions, and correct usage scenarios.

MSZMC
  • 97
  • 1
  • 8
  • Thank you for your answer. You mentioned that authorisation is achieved with Keycloak roles. However the backend service allows or denies access to users based on fine grained permissions, not only roles. How would that fit in? Do you issue access tokens from the backend client different from those issued from the public frontend client? – David Prifti Jan 08 '23 at 09:46
  • It is hard to talk about details without understanding concept of OAuth 2.0 and OIDC. In Oauth access is delegated to application on behalf of user - it is not authentication in user context https://www.scottbrady91.com/oauth/oauth-is-not-authentication. OIDC returns also access tokens that should be stored only by backend services and used when needed, but in general for services and for user authentication different approach should be used. Please check best practices for OAuth 2.0 for frontend browser based apps: https://www.ietf.org/archive/id/draft-ietf-oauth-browser-based-apps-10.html – MSZMC Jan 08 '23 at 11:04