How to integrate keycloak with grafana backend API in version 11.5

Hello Grafana Community,

I have integrated Keycloak with Grafana, and I am able to login in grafana using keycloak flow from browser. But when I used the Basic auth to fetch/create the service account it failed as instead of Basic auth I need to use the Bearer Token to authenticate/Authorize the user.

While doing the same using the access_token from keycloak as a Bearer Token in grafana, I’m facing an issue with authorization.

Here’s what I’ve done so far:

  1. Successfully fetched an access_token from Keycloak using below curl command:

curl -X POST “https://<keycloak_url>/auth/realms/<my_realm>/protocol/openid-connect/token”
-H “Content-Type: application/x-www-form-urlencoded”
-d “grant_type=password”
-d “client_id= <client_name>”
-d “client_secret= <client_secret>”
-d “username=<user_name>”
-d “password=<valid_password>”
-d “scope=openid” -k

  1. Used the obtained access_token from above step as a Bearer token in the API call to Grafana’s /api/serviceaccounts endpoint. Below is the curl command for the same:

curl -X GET “http://<grafana_ip>:<grafana_port>/api/serviceaccounts”
-H “Content-Type: application/json”
-H “Authorization: Bearer $token”
-k

Unfortunately, the request fails with a 401 Unauthorized error. Below is the response of above command:

{
“extra”: null,
“message”: “Invalid API key”,
“messageId”: “api-key.invalid”,
“statusCode”: 401,
“traceID”: “”
}

Here is the grafana.ini entry:

[auth.generic_oauth]
name = keycloak
enabled = true
allow_sign_up = true
auto_login = false
use_pkce = true
use_refresh_token = true
tls_skip_verify_insecure = true
client_id = <Client_id>
client_secret =
auth_url = https://<keycloak_url>/auth/realms/<my_realm>/protocol/openid-connect/auth
token_url = https://<keycloak_url>/auth/realms/<my_realm>/protocol/openid-connect/token
api_url = https://<keycloak_url>/auth/realms/<my_realm>/protocol/openid-connect/userinfo
redirect_uri = http://<grafana_url>:<grafana_port>/login/generic_oauth
role_attribute_path = contains(realm_access.roles[], ‘EM_admin’) && ‘GrafanaAdmin’ || contains(realm_access.roles[], ‘Admin’) && ‘Admin’ || ‘Viewer’
auto_assign_org_role = false
skip_org_role_sync = false
allow_assign_grafana_admin = true
email_attribute_path = email
login_attribute_path = username
name_attribute_path = name
role_attribute_strict = false
org_attribute_path = “Admin”
role_mapping = {“Admin”: “Admin”, “Editor”: “Editor”, “default”: “Editor”}
scopes = openid email profile roles
signout_redirect_url = https://<keycloak_url>/auth/realms//protocol/openid-connect/logout?post_logout_redirect_uri=http://<grafana_url>:<grafana_port>/login

Below the Keycloak configurations:

I suspect I might be missing some configuration or steps to properly set up authentication between Keycloak and Grafana. Could anyone provide guidance on:

  1. Correctly configuring Grafana to recognize Keycloak tokens.
  2. Ensuring that the token is valid for accessing Grafana’s API endpoints.
  3. Any specific Grafana settings or Keycloak configurations needed for service account access.

Any help or documentation references would be greatly appreciated!

Thank you in advance for your assistance.

Best regards,
Vikram Goel

That bearer token must be Service account token, not OAuth access token. See doc:

Thanks for the quick reply!!

I had already tried this. I am able to successfully fetch alerts using a manually created service token via a curl command or Postman.

However, my requirement is to automate the creation of the service account and service token within my code, eliminating the need for manual creation.

Is there a way to automatically generate service account/token using the keycloak authentication?

Best Regards,
Vikram Goel

Doc mentions:

a session cookie (acquired via regular login or OAuth).

1 Like

Thanks @Jangaraj, for pointing out the session cookies flow - this is something we missed, as there isn’t much documentation or examples available for this process.

After getting the access_token from keycloak, I passed it as a bearer token in /login/generic_oauth curl command. Below is the same command:

curl -v -X GET -c cookies.txt
-H “Authorization: Bearer $token”
“http://<grafana_url>:<grafana_port>/login/generic_oauth”
-H “Content-Type: application/json”
-k -L

But the grafana_session cookie is not being set from the response. Below is the cookies.txt file.

#HttpOnly_seliicbl00118-vip2.ete.ka.sw.ericsson.se FALSE /auth/realms/emrealm/ FALSE 0 KC_RESTART <cookie_value>
#HttpOnly_seliicbl00118-vip2.ete.ka.sw.ericsson.se FALSE /auth/realms/emrealm/ FALSE 0 AUTH_SESSION_ID_LEGACY 89ca4e48-168f-4e3e-a760-53a66b16987b.eric-sec-access-mgmxx-xx33
#HttpOnly_seliicbl00118-vip2.ete.ka.sw.ericsson.se FALSE /auth/realms/emrealm/ TRUE 0 AUTH_SESSION_ID 89ca4e48-168f-4e3e-a760-53a66xxxxxx.eric-sec-access-mgmt-0-10333
#HttpOnly_10.61.245.91 FALSE / FALSE 1743145917 oauth_code_verifier gXdHzvNRyVwGcXbpRRLn8B1vVK2SFoLeTGQzZbfoDPN_3hC0UczZcor
#HttpOnly_10.61.245.91 FALSE / FALSE 1743145917 redirectTo
#HttpOnly_10.61.245.91 FALSE / FALSE 1743145917 oauth_state a23034d3d7bf585d69b61e3e43b72155499c76cbcb4bxxxxxx10c43ab7c59

Could you please share any example or a detailed guide or any pointer. It would be great help. Thanks!

Best Regards,
Vikram Goel

That doesn’t work like: I use the simplest client credentials flow to get access token, which I exchange for a session cookie. Please be familiar with the Authorization Code Flow or Authorization Code Flow with Proof Key for Code Exchange (PKCE). You will need a browser, or at least you must be able to emulate that and then execute the right flow to get the session. That’s not code/api friendly, so you must understand what/why you are doing. There are no real examples for this because this is not a standard approach. So sorry, I wouldn’t spend 2-3 hours to develop an example just for you. I gave you only ideas, not copy&paste examples.

Explore other options - tips for reading: Grafana Cloud, auth proxy, …

I am aware with Authorization Code Flow and Authorization Code Flow with Proof Key for Code Exchange (PKCE). These are used for services where browser based authentication is possible. And we have followed Authorization Code Flow only to integrate Grafana with keycloak and that is working fine I am able to login in Grafana with keycloak users, from browser, when generic oauth is enabled.

Now for other use case where my Application is interacting with Grafana for fetching Alerts. My java application is able to fetch alerts from Grafana (when generic oauth is disabled and with HTTP API exposed by Grafana) using basic auth flow (with Grafana’s local users/passwords). I first create a service account then generate a Service Account token and then using that token i fetches Alerts. All that works fine.

But for use case where I am facing problem is - When Generic OAuth is enabled in Grafana and basic authentication is disabled. My Java based application is facing problem to fetch Alerts. As this is backend communication I can not used Authorization Code Flow and Authorization Code Flow with Proof Key for Code Exchange (PKCE).
What I beleive that for backend communication I would have to use ROPC or Client Credentials Flow to first fetch Token from Keycloak which I am able to get (to simulate this I am getting token from curl). But after getting token how to use keycloak provided token I am not able to understand. Neither there is any documentation which can help me on this. I tried getting Service Account token using Keycloak token also I tried login/generic_oauth to generate session cookies directly using keycloak client credentials and ropc token but evertime I am getting Unauthorized error.

Hope I am able to communicate problem I am facing.

OK, please provide any Grafana documentation, which proves this believe.

That’s what I am also saying, I didn’t find any documentation regarding this. Upon referring chat gpt it suggested to use ROPC/Client credentials flow to get token.

Pleas let us know if you are aware of any solution for our case.

Best Regards,
Vikram Goel

Do you trust ChatGPT or documentation?

I have written this content, to make Grafana champion aware of our use case and get the solution for it as I didn’t find any documentation regarding this.

If you know any solution for my use case of if you have any documentation please share.

Best Regards,
Vikram Goel

I believe you didn’t read my recommendations: