Gab
Gab

Reputation: 8323

Keycloak - OpenId Connect Access types

I'd like to authenticate a legacy java (6) application against a node-js one currently secured using keycloak OIDC bearer only (both apps belonging to same realm).

I've been told to use keycloak-authz-client library resolving a keycloak OIDC JSON as below { "realm": "xxx", "realm-public-key": "fnzejhbfbhafbazhfzafazbfgeuizrgyez...", "bearer-only": true, "auth-server-url": "http://xxx:80/auth", "ssl-required": "external", "resource": "resourceName" }

However, the keycloak java client required java 8 and my current runtime is a jre6. Recompiling the lib including transitive dependencies does not looks like a good idea and I end up so using keycloak oauth2 REST endpoint.

As far as I know oauth2 I would go with a client_credentials flows exchanging a client secret against an access_token once at application initialization and refreshing / renewing when expired.

Coming to keycloak documentation :

Access Type

This defines the type of the OIDC client.

confidential

Confidential access type is for server-side clients that need to perform a browser login and require a client secret when they turn an access code into an access token, (see Access Token Request in the OAuth 2.0 spec for more details). This type should be used for server-side applications. public

Public access type is for client-side clients that need to perform a browser login. With a client-side application there is no way to keep a secret safe. Instead it is very important to restrict access by configuring correct redirect URIs for the client. bearer-only

Bearer-only access type means that the application only allows bearer token requests. If this is turned on, this application cannot participate in browser logins.

It seems that confidential access type is the one suitable for my needs (should be used for server-side applications) however I don't get how it is related to browser login (which is my mind is related to authenticating using third parties identity providers as facebook and co).

The confidential client settings also require a valid redirect uri the browser will redirect to after successful login or lagout. As the client I want to authenticate is an application I don't see the point.

Generally speaking I don't get the whole access type things. Is it related only to the client or to the resource owner also (Is my node.js application stuck to bearer-only as existing clients use this access type ? will it accept the bearer authentication using the access_token obtained with client_credentials flow ? I suppose it will).

Can someone clarify keycloak OIDC access type and where I went wrong if I did ?

What is the proper way to delegate access for my legacy application to some resources (not limited to a specific user ones) of another application using keycloak ?

Upvotes: 12

Views: 16183

Answers (1)

dreamcrash
dreamcrash

Reputation: 51393

You are mixing up the OAuth 2.0 concepts of Client Types and Grants. Those are different, albeit interconnected, concepts. The former refers to the application architecture, whereas the latter to the appropriate grant to handle a particular Authorization/Authentication use-case.

One chooses and combines those options; first one choses the client type (e.g., public, confidential), and then the grant (e.g., Authorization code flow). Both client types share some of the same grants, with the caveat that the confidential client will require also a client secret to be provided during the execution of the Authentication/Authorization grant.

From the Oauth 2.0 specification:

   OAuth defines two client types, based on their ability to
   authenticate securely with the authorization server (i.e., ability to
   maintain the confidentiality of their client credentials):

   confidential
      Clients capable of maintaining the confidentiality of their
      credentials (e.g., client implemented on a secure server with
      restricted access to the client credentials), or capable of secure
      client authentication using other means.

   public
      Clients incapable of maintaining the confidentiality of their
      credentials (e.g., clients executing on the device used by the
      resource owner, such as an installed native application or a web
      browser-based application), and incapable of secure client
      authentication via any other means.

As one can read the client type refers to the type of the application architecture. Why do you need those types? The answer is to add an extra layer of security.

Let us look at the example of the Authorization Code Grant. Typically the flow is as follows:

  • The user goes to an application;
  • The user gets redirect to the Keycloak login page;
  • The user authenticates itself;
  • Keycloak check the username and password, and if correct, sends back to the application an authorization code;
  • The application receives that code and calls Keycloak in order to exchange the code for tokens.

One of the "security issue" with that flow is that the exchange of code for token happens on the frontend channel which due to the nature of browsers it is susceptible to a hacker intercepting that code and exchange it for the tokens before the real application does it. There are ways of mitigating this but it is out of the scope of this question.

Now, If your application is a single-page application, then it cannot safely store a secret, therefore we have to use a public client type. However, if the application has a backend where the client secret can be safely stored, then we could use a confidential client.

So for the same flow (i.e., Authorization Code Grant), one can make it more secure by using a confidential client. This is because the application will now have to send to Keycloak a client secret as well, and this happens on the backend channel, which it is more secure than the frontend channel.

What is the proper way to delegate access for my legacy application to some resources (not limited to a specific user ones) of another application using keycloak ?

The proper grant is to use the so called Client Credential Grant:

4.4. Client Credentials Grant

The client can request an access token using only its client
credentials (or other supported means of authentication) when the
client is requesting access to the protected resources under its
control, or those of another resource owner that have been previously arranged with the authorization server (the method of which is beyond the scope of this specification).

Since this grant uses the client credentials (e.g., client secret) you can only use it if you have selected confidential as the client type.

Upvotes: 3

Related Questions