7

Context: We are using Keycloak to secure our APIs by usually passing tokens through Authorization Headers. However, these APIs also allow users to download files (for instance: https://api.service.io/users.xlsx).

To use these "download endpoints", our web client applications pass users' token via query strings. (e.g. https://api.service.io/users.xlsx?accessToken=${bearerToken})).

Problem: Passing tokens via query string has several security flaws (browser history, ...). Therefore we would like to pass a very short-lived token (e.g. lifespan of 15sec) instead of the normal one (lifespan of 300sec by default).

Question: How could we request a different token from Keycloak API (for instance, /realms/#{realm_id}/protocol/openid-connect/token) by:

  • providing the normal access token (not credentials);
  • and specifying a different lifespan ?
  • Did you even go through documentation ? http://www.keycloak.org/docs/latest/server_admin/index.html#_timeouts – Kavindu Dodanduwa Jan 18 '18 at 05:58
  • Sending access in query string is bad. Why not use a header. When you get SSL, you get encrpyion. Access logs won't reveal them too – Kavindu Dodanduwa Jan 18 '18 at 06:03
  • 1
    I've read the documentation, indeed. I can change the **default** lifespan using the Admin API, but that's not the point. I want to keep this default lifespan for most tokens. However, I want the capability to specify a different lifespan when requesting specific tokens. About your second comment, you can't always use Headers. For example, when you redirect browsers to a download link, you can't. – Lorent Lempereur Jan 18 '18 at 09:20
  • okay, now only I understood your requirement. And for the second point, you might use a form submission on page load (but will depend on exact scenario). For the original question, can't you specificy scope value in auth req and restrict access tokens access level ? – Kavindu Dodanduwa Jan 18 '18 at 13:39

2 Answers2

5

After reading Keycloak's source code, it appears this is not possible (version 3.4.2.Final) to ask for a specific lifespan at runtime.

However, I developed a Keycloak Custom REST endpoint to do that. https://github.com/looorent/keycloak-configurable-token-api

When this JAR file is deployed in Keycloak, you can ask for a given lifespan at runtime. For example: $ curl -X POST -d '{ "tokenLifespanInSeconds": 20}' -H "Content-Type: application/json" -H "Authorization: Bearer <user-access-token>" http://auth.service.io/auth/realms/a-realm/configurable-token

0

For someone looking for a way to get a permanent token for internal usage (or any usage), without using any external jar, there is a workaround.

  1. Create a client and enable client-credentials for that client: Enable client-authentication and client-authorization.

  2. For that client, remember the client-id and client-secret, then send the following request to keycloak:

    curl --location 'https://my.keycloak.url/realms/realm-name/protocol/openid-connect/token' \
    --header 'Content-Type: application/x-www-form-urlencoded' \
    --data-urlencode 'client_id=my-client-id' \
    --data-urlencode 'client_secret=my-client-secret' \
    --data-urlencode 'grant_type=client_credentials'
    

    This will return you a json with access_token.

  3. Use this access token.

  4. In case you wish to have a set of roles assigned to this token, just go to your client and click on the Service account roles tab. Here you can add one or more roles to this client. Any further token request will provide you with a token with the assigned roles.


Note that although this access token is time limited and will expire soon, you can always get a new token directly via the API call mentioned in step 2. So no human intervention involved.