Keycloak client credentials grant type with refresh token
Asked Answered
H

2

8

I have a client in keycloak (7.0.0) with given configuration - highlighted option "enables support for 'Client Credentials Grant'":

Keycloak client configuration

When I obtain a token for that client (POST /auth/realms/{my-realm}/protocol/openid-connect/token), I receive a following json response:

{
  "access_token": "xxx",
  "expires_in": 600,
  "refresh_expires_in": 1800,
  "refresh_token": "xxx",
  "token_type": "bearer",
  "not-before-policy": 1572415518,
  "session_state": "xxx",
  "scope": "xxx xxx"
}

I want to integrate it with OAuth2FeignRequestInterceptor, which by default ignores refresh token and creates a new session every access_token's expires_in seconds:

if (accessToken == null || accessToken.isExpired()) {
            try {
                // no refresh token usage here
                accessToken = acquireAccessToken();
            }
            ...
}

My questions are:

  1. Why do I receive a refresh token at all for client_credentials, which is a grant type for backend -> backend communication? The OAuth2 documentation link says explicitly that "A refresh token SHOULD NOT be included" for client_credentials grant type.
  2. Is it possible to configure keycloak that it won't send refresh tokens for clients with client_credentials grant type?
  3. If answer to 2. is 'NO' - do I have to implement my own feign request interceptor with refresh token support?
  4. If the client scope includes offline_access - the refresh_expires_in is 0 and, from what I understood, the refresh token is an offline token. Here is a link to keycloak mailing list where offline token usage is recommended by someone from keycloak's team - isn't it in conflict with OIDC specification for client_credentials grant type?
Hennahane answered 30/10, 2019 at 8:19 Comment(0)
D
6

My answer is maybe a bit too late, but Keycloak recently added support for disabling refresh tokens in the case of client_credentials grants. This was implemented in version 12.0.0, which was released in December 2020.

Here is the part of the documentation pointing to that: https://www.keycloak.org/docs/12.0/release_notes/#other-improvements

Before this version, it was not possible to disable refresh tokens, and so you would have indeed to write your own version of OAuth2FeignRequestInterceptor that would either ignore the refresh token (and try to obtain a new access token), or use the refresh token to obtain a renewed access token. I would choose the first solution, as it closer from the OAUTH2 spec.

Domella answered 12/1, 2021 at 13:3 Comment(0)
S
4

My questions are:

  1. Why do I receive a refresh token at all for client_credentials, which is a grant type for backend -> backend communication? The OAuth2 documentation link says explicitly that "A refresh token SHOULD NOT be included" for client_credentials grant type.

First, one needs to clarify the meaning of "SHOULD NOT" in that context. According to rfc2119:

  The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL
  NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED",  "MAY", and
  "OPTIONAL" in this document are to be interpreted as described in
  RFC 2119.

Note that the force of these words is modified by the requirement
level of the document in which they are used.

  1. MUST This word, or the terms "REQUIRED" or "SHALL", mean that the definition is an absolute requirement of the specification.

  2. MUST NOT This phrase, or the phrase "SHALL NOT", mean that the definition is an absolute prohibition of the specification.

  3. SHOULD This word, or the adjective "RECOMMENDED", mean that there may exist valid reasons in particular circumstances to ignore a particular item, but the full implications must be understood and carefully weighed before choosing a different course.

  4. SHOULD NOT This phrase, or the phrase "NOT RECOMMENDED" mean that there may exist valid reasons in particular circumstances when the particular behavior is acceptable or even useful, but the full implications should be understood and the case carefully weighed before implementing any behavior described with this label.

As you can read, "SHOULD NOT" does not mean that the specification prohibits it but rather that it does not recommend it.

  1. Is it possible to configure keycloak that it won't send refresh tokens for clients with client_credentials grant type?

As first mentioned in the answer provided by @Clement Petit; Keycloak v12 introduced:

Support for OAuth2 Client Credentials grant without refresh token and without user session.

That option can be found in each client configuration under the section "OpenID Connect Compatibility Modes" as shown below:

enter image description here

  1. If the client scope includes offline_access - the refresh_expires_in is 0 and, from what I understood, the refresh token is an offline token. Here is a link to keycloak mailing list where offline token usage is recommended by someone from keycloak's team - isn't it in conflict with OIDC specification for client_credentials grant type?

As you have seen, the specification does not explicitly prohibits it. Notwithstanding, conceptually, it does not make sense to have a refresh token when using the client credentials flow since the backend already has the client secret stored locally anyway, and can simply acquire a new access token without the hassle of either having to store user credentials or request the user to enter them again.

From the original poster from the thread of the keycloak mailing list that you have posted:

Hi,

Currently, every time a confidential client tries to get a new access token from the token endpoint a new session is created on the server. This can lead to multiple active sessions for a single client/service account when doing multiple requests to token endpoint.

To avoid that the client should store the access token/refresh token and use a refresh token when appropriate in case the access token has expired. That is fine.

one can infer that the reason why Keycloak had (at that time) the refresh token available for the client credential flows was to be used as a workaround to a technical issue with their client credential flow implementation (i.e., creating too many sessions).

Saltish answered 18/8, 2022 at 19:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.