OIDC: Role not applied

Hi there,
i have connected Grafana to Keycloak and can successfully login with that. However, the user role is not applied.

This is how my userinfo token from keycloak looks like:

{
  "sub": "f21646e8-ae12-4cca-b55a-22c30219989e",
  "resource_access": {
    "nextcloud.simonszu.de": {
      "roles": [
        "admin"
      ]
    },
    "grafana.simonszu.de": {
      "roles": [
        "grafanaadmin"
      ]
    },
    "Kimai": {
      "roles": [
        "kimai_admin"
      ]
    },
    "master-realm": {
      "roles": [
        "view-realm",
        "view-identity-providers",
        "manage-identity-providers",
        "impersonation",
        "create-client",
        "manage-users",
        "query-realms",
        "view-authorization",
        "query-clients",
        "query-users",
        "manage-events",
        "manage-realm",
        "view-events",
        "view-users",
        "view-clients",
        "manage-authorization",
        "manage-clients",
        "query-groups"
      ]
    },
    "account": {
      "roles": [
        "manage-account",
        "manage-account-links",
        "view-profile"
      ]
    }
  },
  "email_verified": true,
  "name": "Simon Szustkowski",
  "preferred_username": "simonszu",
  "given_name": "Simon",
  "family_name": "Szustkowski",
  "email": "mail@simonszu.de"
}

I have checked with https://jmespath.org/ the correct selection string for the role attribution path and when i use

contains(resource_access."grafana.simonszu.de".roles[*], `grafanaadmin`) && `GrafanaAdmin`

the online debugger properly returns “GrafanaAdmin” with the userInfo JSON provided above.

However, Grafana is not granting me the superadmin role. Of course, the GF_AUTH_GENERIC_OAUTH_ALLOW_ASSIGN_GRAFANA_ADMIN is set.

What am i missing?

Do you have Grafana version, which support it? (Check Grafana doc, release notes, … to find which version has that)

Sure, it is grafana v11.0.0-162332. When i login as admin directly (not via OIDC) it says that the OIDC user permissions are synced via generic OAuth which point to this documentation: Configure authentication | Grafana documentation which also say that role mapping is supported.

I have enabled GF_LOG_LEVEL:debug in the docker container env list. It is a bit helpful.

logger=oauth.generic_oauth t=2024-02-22T15:06:28.361303221Z level=debug msg="Getting user info"
logger=oauth.generic_oauth t=2024-02-22T15:06:28.36135616Z level=debug msg="Extracting user info from OAuth token"
logger=oauth.generic_oauth t=2024-02-22T15:06:28.361855692Z level=debug msg="Received id_token" raw_json="{\"exp\":1708614448,\"iat\":1708614388,\"auth_time\":1708614388,\"jti\":\"1f46b790-6216-465f-a716-1fa56a4b5ad3\",\"iss\":\"https://keycloak.simonszu.de/real
ms/master\",\"aud\":\"grafana.simonszu.de\",\"sub\":\"f21646e8-ae12-4cca-b55a-22c30219989e\",\"typ\":\"ID\",\"azp\":\"grafana.simonszu.de\",\"session_state\":\"78e5c3b1-eecb-4df1-b230-a2da96612e52\",\"at_hash\":\"QMqLXzmyQq8HY6hyrI8iUg\",\"acr\":\"1\",\"sid\":\"
78e5c3b1-eecb-4df1-b230-a2da96612e52\",\"email_verified\":true,\"name\":\"Simon Szustkowski\",\"preferred_username\":\"simonszu\",\"given_name\":\"Simon\",\"family_name\":\"Szustkowski\",\"email\":\"mail@simonszu.de\"}" data="Name: Simon Szustkowski, Displayname
: , Login: , Username: , Email: mail@simonszu.de, Upn: , Attributes: map[]"
logger=oauth.generic_oauth t=2024-02-22T15:06:28.361883243Z level=debug msg="Getting user info from API"
logger=oauth.generic_oauth t=2024-02-22T15:06:28.370767294Z level=debug msg="HTTP GET" url=https://keycloak.simonszu.de/realms/master/protocol/openid-connect/userinfo status="200 OK" response_body="{\"sub\":\"f21646e8-ae12-4cca-b55a-22c30219989e\",\"resource_acc
ess\":{\"nextcloud.simonszu.de\":{\"roles\":[\"admin\"]},\"grafana.simonszu.de\":{\"roles\":[\"grafanaadmin\"]},\"Kimai\":{\"roles\":[\"kimai_admin\"]},\"master-realm\":{\"roles\":[\"view-realm\",\"view-identity-providers\",\"manage-identity-providers\",\"impers
onation\",\"create-client\",\"manage-users\",\"query-realms\",\"view-authorization\",\"query-clients\",\"query-users\",\"manage-events\",\"manage-realm\",\"view-events\",\"view-users\",\"view-clients\",\"manage-authorization\",\"manage-clients\",\"query-groups\"
]},\"account\":{\"roles\":[\"manage-account\",\"manage-account-links\",\"view-profile\"]}},\"email_verified\":true,\"name\":\"Simon Szustkowski\",\"preferred_username\":\"simonszu\",\"given_name\":\"Simon\",\"family_name\":\"Szustkowski\",\"email\":\"mail@simons
zu.de\"}"
logger=oauth.generic_oauth t=2024-02-22T15:06:28.370859897Z level=debug msg="Received user info response from API" raw_json="{\"sub\":\"f21646e8-ae12-4cca-b55a-22c30219989e\",\"resource_access\":{\"nextcloud.simonszu.de\":{\"roles\":[\"admin\"]},\"grafana.simons
zu.de\":{\"roles\":[\"grafanaadmin\"]},\"Kimai\":{\"roles\":[\"kimai_admin\"]},\"master-realm\":{\"roles\":[\"view-realm\",\"view-identity-providers\",\"manage-identity-providers\",\"impersonation\",\"create-client\",\"manage-users\",\"query-realms\",\"view-auth
orization\",\"query-clients\",\"query-users\",\"manage-events\",\"manage-realm\",\"view-events\",\"view-users\",\"view-clients\",\"manage-authorization\",\"manage-clients\",\"query-groups\"]},\"account\":{\"roles\":[\"manage-account\",\"manage-account-links\",\"
view-profile\"]}},\"email_verified\":true,\"name\":\"Simon Szustkowski\",\"preferred_username\":\"simonszu\",\"given_name\":\"Simon\",\"family_name\":\"Szustkowski\",\"email\":\"mail@simonszu.de\"}" data="Name: Simon Szustkowski, Displayname: , Login: , Username
: , Email: mail@simonszu.de, Upn: , Attributes: map[]"
logger=oauth.generic_oauth t=2024-02-22T15:06:28.370869685Z level=debug msg="Processing external user info" source=token data="Name: Simon Szustkowski, Displayname: , Login: , Username: , Email: mail@simonszu.de, Upn: , Attributes: map[]"
logger=oauth.generic_oauth t=2024-02-22T15:06:28.372206379Z level=debug msg="Setting user info name from name field"
logger=oauth.generic_oauth t=2024-02-22T15:06:28.372234711Z level=debug msg="Searching for login among JSON" loginAttributePath=username
logger=oauth.generic_oauth t=2024-02-22T15:06:28.372284504Z level=debug msg="Set user info email from extracted email" email=mail@simonszu.de
logger=oauth.generic_oauth t=2024-02-22T15:06:28.372441467Z level=debug msg="Processing external user info" source=API data="Name: Simon Szustkowski, Displayname: , Login: , Username: , Email: mail@simonszu.de, Upn: , Attributes: map[]"
logger=oauth.generic_oauth t=2024-02-22T15:06:28.372452347Z level=debug msg="Searching for login among JSON" loginAttributePath=username
logger=oauth.generic_oauth t=2024-02-22T15:06:28.372554538Z level=debug msg="No role found, returning default."
logger=oauth.generic_oauth t=2024-02-22T15:06:28.372559166Z level=debug msg="Defaulting to using email for user info login" email=mail@simonszu.de

As you can see, it is displaying in the keycloak response that it gets the JSON which i pasted pretty-formatted in my opening post, but it somehow fails to parse the roles list from the userinfo endpoint response, although this should be valid JMESpath according to the JMESpath website.

Since i have no idea how the logs should look like when Grafana is able to correctly parse the userinfo endpoint, i am unsure how to proceed here.

OK, i have made some progress. At first: The role mapper in keycloak has to be applied to the id_token, i found some other hints that it has to be applied to the userinfo_token, which does not work.
And apparently this is also not working when the grafana roles are set up as client roles, maybe because i got confused with all the escaping, since my client names contains dots, because they are the FQDN of the client.
This is somehow okay for me, since the grafanaadmin role is realm-wide unique due to its name. At least it’s working now when i set up everything as realm role and expose it in the id_token, but i am wondering if this would be possible as client roles as well.