-
What Grafana version and what operating system are you using?
Grafana v11.4.0 (b58701869e)
onRocky 8.10
-
What are you trying to achieve?
We want to switch the auth from ldap to generic sso (keycloak). We’re using organisations to let people manage their own org alert/dashboard/datasource. Permission roles are pretty simple. Team A should be admin of Org A , all can be viewer , and infra team has additional permission on all org. So no rbac needed or whatsoever. And based on the doc I should be able to achieve that wileorg_mapping
androle
-
How are you trying to achieve it?
I’m adding a new attribute in keycloakorgUnits
with the org matching org in grafana and add it to userinfo
[auth.generic_oauth]
enabled = true
name = SSO
allow_sign_up = true
client_id = grafana
client_secret = <MYSECRET>
scopes = openid email profile offline_access roles groups
auth_url = https://sso-stage.mydomain.com/realms/staging/protocol/openid-connect/auth
token_url = https://sso-stage.mydomain.com/realms/staging/protocol/openid-connect/token
api_url = https://sso-stage.mydomain.com/realms/staging/protocol/openid-connect/userinfo
email_attribute_path = email
login_attribute_path = username
name_attribute_path = full_name
role_attribute_path = contains(groups[*], 'grafana_team-admin') && 'GrafanaAdmin' || contains(groups[*], 'grafana_team-editor') && 'Editor' || 'Viewer'
org_attribute_path = organizationalUnits
org_mapping = *:*:Viewer ORGA:ORGA:Admin ORGB:ORGB:Admin ORGA:*:Editor
role_attribute_strict = false
allow_assign_grafana_admin = true
skip_org_role_sync = false
use_refresh_token = true
allowed_domains = <EMAILDOMAIN>
oauth_allow_insecure_email_lookup = true
- What happened?
Nothing. We tried dozens of configurations. The only workings are:- using default value like
username
(visible in both tokens AND userinfo calls) - using an array but it has to be in /tokens call
- using default value like
This one does not work
#single string not matter is in /token or /userinfo
org_attribute_path = organizationalUnits
org_mapping = *:*:Viewer ORGA:ORGA:Admin ORGB:ORGB:Admin ORGA:*:Editor
I belong to ORGA and should be Admin for ORGA and editor for all other orgs; When I connect I’m only viewer
Debug log output:
logger=oauth.generic_oauth t=2025-01-21T14:36:28.999764255Z level=debug msg="Extracting user info from OAuth token"
logger=oauth.generic_oauth t=2025-01-21T14:36:28.999989732Z level=debug msg="Received id_token" raw_json="{\"exp\":1737470488,\"iat\":1737470188,\"auth_time\":1737465155,\"jti\":\"cb786f76-3b3f-4e84-bf11-742d0259ff86\",\"iss\":\"https://sso-stage.mydomain.com/realms/staging\",\"aud\":\"grafana\",\"sub\":\"7ff01089-ca69-480b-b349-08761b6d8e31\",\"typ\":\"ID\",\"azp\":\"grafana\",\"session_state\":\"a61884f3-224e-43e3-bb19-415fc8e31076\",\"at_hash\":\"29yEhre9hiXLd1RuXKiKLQ\",\"acr\":\"0\",\"sid\":\"a61884f3-224e-43e3-bb19-415fc8e31076\",\"email_verified\":true,\"orgUnit\":[\"ORGA\"],\"name\":\"myusername myname\",\"groups\":[\"sso_employee\",\"grafana_team-admin\",\"grafana_team-editor\"],\"organizationalUnits\":\"ORGA\",\"preferred_username\":\"vmyname\",\"given_name\":\"myusername\",\"family_name\":\"myname\",\"email\":\"myusername.myname@mydomain.com\"}" data="Name: myusername myname, Displayname: , Login: , Username: , Email: myusername.myname@mydomain.com, Upn: , Attributes: map[]"
logger=oauth.generic_oauth t=2025-01-21T14:36:29.000015862Z level=debug msg="Getting user info from API"
logger=oauth.generic_oauth t=2025-01-21T14:36:29.046707837Z level=debug msg="HTTP GET" url=https://sso-stage.mydomain.com/realms/staging/protocol/openid-connect/userinfo status="200 OK" response_body="{\"sub\":\"7ff01089-ca69-480b-b349-08761b6d8e31\",\"email_verified\":true,\"orgattrs\":{\"departmentid\":\"id_infra\",\"teamid\":\"id_infra_253944651_253839237\",\"team\":\"Infrastructure - grafana\",\"department\":\"Infrastructure\"},\"orgUnit\":[\"ORGA\"],\"name\":\"myusername myname\",\"groups\":[\"ORGA\"],\"organizationalUnits\":\"ORGA\",\"preferred_username\":\"vmyname\",\"given_name\":\"myusername\",\"family_name\":\"myname\",\"email\":\"myusername.myname@mydomain.com\"}"
logger=oauth.generic_oauth t=2025-01-21T14:36:29.046806196Z level=debug msg="Received user info response from API" raw_json="{\"sub\":\"7ff01089-ca69-480b-b349-08761b6d8e31\",\"email_verified\":true,\"orgattrs\":{\"departmentid\":\"id_infra\",\"teamid\":\"id_infra_253944651_253839237\",\"team\":\"Infrastructure - grafana\",\"department\":\"Infrastructure\"},\"orgUnit\":[\"ORGA\"],\"name\":\"myusername myname\",\"groups\":[\"ORGA\"],\"organizationalUnits\":\"ORGA\",\"preferred_username\":\"vmyname\",\"given_name\":\"myusername\",\"family_name\":\"myname\",\"email\":\"myusername.myname@mydomain.com\"}" data="Name: myusername myname, Displayname: , Login: , Username: , Email: myusername.myname@mydomain.com, Upn: , Attributes: map[]"
logger=oauth.generic_oauth t=2025-01-21T14:36:29.046818216Z level=debug msg="Processing external user info" source=token data="Name: myusername myname, Displayname: , Login: , Username: , Email: myusername.myname@mydomain.com, Upn: , Attributes: map[]"
logger=oauth.generic_oauth t=2025-01-21T14:36:29.046934114Z level=debug msg="Setting user info name from name field"
logger=oauth.generic_oauth t=2025-01-21T14:36:29.046973334Z level=debug msg="Searching for login among JSON" loginAttributePath=username
logger=oauth.generic_oauth t=2025-01-21T14:36:29.047031383Z level=debug msg="Set user info email from extracted email" email=myusername.myname@mydomain.com
logger=oauth.generic_oauth t=2025-01-21T14:36:29.047189081Z level=debug msg="Processing external user info" source=API data="Name: myusername myname, Displayname: , Login: , Username: , Email: myusername.myname@mydomain.com, Upn: , Attributes: map[]"
logger=oauth.generic_oauth t=2025-01-21T14:36:29.047220021Z level=debug msg="Searching for login among JSON" loginAttributePath=username
logger=orgrole.mapper t=2025-01-21T14:36:29.047908953Z level=debug msg="No direct role mapping found"
logger=oauth.generic_oauth t=2025-01-21T14:36:29.047924483Z level=debug msg="Defaulting to using email for user info login" email=myusername.myname@mydomain.com
logger=oauth.generic_oauth t=2025-01-21T14:36:29.047930463Z level=debug msg="User info result" result="Id: 7ff01089-ca69-480b-b349-08761b6d8e31, Name: myusername myname, Email: myusername.myname@mydomain.com, Login: myusername.myname@mydomain.com, Role: , Groups: [], OrgRoles: map[1:Viewer 2:Viewer 3:Viewer 10:Viewer 11:Viewer 12:Viewer 13:Viewer 14:Viewer 15:Viewer 16:Viewer 17:Viewer 18:Viewer 19:Viewer 20:Viewer 21:Viewer 22:Viewer 23:Viewer 24:Viewer 25:Viewer 26:Viewer 27:Viewer 28:Viewer 29:Viewer 30:Viewer 31:Viewer 32:Viewer 33:Viewer 34:Viewer 35:Viewer]"
For instance this does work (because an array AND in the token call)
# array string and only work if we add it to /token
org_attribute_path = orgUnit
org_mapping = *:*:Viewer ORGA:ORGA:Admin ORGB:ORGB:Admin ORGA:*:Editor
When I connect via SSO I’m correctly Editor of all org and admin of ORGA
Debug log output:
logger=oauth.generic_oauth t=2025-01-21T13:54:47.595358429Z level=debug msg="Extracting user info from OAuth token"
logger=oauth.generic_oauth t=2025-01-21T13:54:47.595569636Z level=debug msg="Received id_token" raw_json="{\"exp\":1737467987,\"iat\":1737467687,\"auth_time\":1737465155,\"jti\":\"4f245de2-d4c7-4d7a-8e23-6788f319e05c\",\"iss\":\"https://sso-stage.mydomain.com/realms/staging\",\"aud\":\"grafana\",\"sub\":\"7ff01089-ca69-480b-b349-08761b6d8e31\",\"typ\":\"ID\",\"azp\":\"grafana\",\"session_state\":\"a61884f3-224e-43e3-bb19-415fc8e31076\",\"at_hash\":\"6IhNQRRq_FUDNTM4gay4kA\",\"acr\":\"0\",\"sid\":\"a61884f3-224e-43e3-bb19-415fc8e31076\",\"email_verified\":true,\"orgUnit\":[\"ORGA\"],\"name\":\"myusername myname\",\"groups\":[\"sso_employee\",\"grafana_team-admin\",\"grafana_team-editor\"],\"organizationalUnits\":\"ORGA\",\"preferred_username\":\"mmyname\",\"given_name\":\"myusername\",\"family_name\":\"myname\",\"email\":\"myusername.myname@mydomain.com\"}" data="Name: myusername myname, Displayname: , Login: , Username: , Email: myusername.myname@mydomain.com, Upn: , Attributes: map[]"
logger=oauth.generic_oauth t=2025-01-21T13:54:47.595608926Z level=debug msg="Getting user info from API"
logger=oauth.generic_oauth t=2025-01-21T13:54:47.635746904Z level=debug msg="HTTP GET" url=https://sso-stage.mydomain.com/realms/staging/protocol/openid-connect/userinfo status="200 OK" response_body="{\"sub\":\"7ff01089-ca69-480b-b349-08761b6d8e31\",\"email_verified\":true,\"orgattrs\":{\"departmentid\":\"id_infra\",\"teamid\":\"id_infra_253944651_253839237\",\"team\":\"Infrastructure - grafana\",\"department\":\"Infrastructure\"},\"orgUnit\":[\"ORGA\"],\"name\":\"myusername myname\",\"groups\":[\"ORGA\"],\"organizationalUnits\":\"ORGA\",\"preferred_username\":\"mmyname\",\"given_name\":\"myusername\",\"family_name\":\"myname\",\"email\":\"myusername.myname@mydomain.com\"}"
logger=oauth.generic_oauth t=2025-01-21T13:54:47.635816783Z level=debug msg="Received user info response from API" raw_json="{\"sub\":\"7ff01089-ca69-480b-b349-08761b6d8e31\",\"email_verified\":true,\"orgattrs\":{\"departmentid\":\"id_infra\",\"teamid\":\"id_infra_253944651_253839237\",\"team\":\"Infrastructure - grafana\",\"department\":\"Infrastructure\"},\"orgUnit\":[\"ORGA\"],\"name\":\"myusername myname\",\"groups\":[\"ORGA\"],\"organizationalUnits\":\"ORGA\",\"preferred_username\":\"mmyname\",\"given_name\":\"myusername\",\"family_name\":\"myname\",\"email\":\"myusername.myname@mydomain.com\"}" data="Name: myusername myname, Displayname: , Login: , Username: , Email: myusername.myname@mydomain.com, Upn: , Attributes: map[]"
logger=oauth.generic_oauth t=2025-01-21T13:54:47.635833103Z level=debug msg="Processing external user info" source=token data="Name: myusername myname, Displayname: , Login: , Username: , Email: myusername.myname@mydomain.com, Upn: , Attributes: map[]"
logger=oauth.generic_oauth t=2025-01-21T13:54:47.635919192Z level=debug msg="Setting user info name from name field"
logger=oauth.generic_oauth t=2025-01-21T13:54:47.635928862Z level=debug msg="Searching for login among JSON" loginAttributePath=username
logger=oauth.generic_oauth t=2025-01-21T13:54:47.635966661Z level=debug msg="Set user info email from extracted email" email=myusername.myname@mydomain.com
logger=oauth.generic_oauth t=2025-01-21T13:54:47.63607296Z level=debug msg="Processing external user info" source=API data="Name: myusername myname, Displayname: , Login: , Username: , Email: myusername.myname@mydomain.com, Upn: , Attributes: map[]"
logger=oauth.generic_oauth t=2025-01-21T13:54:47.63608207Z level=debug msg="Searching for login among JSON" loginAttributePath=username
logger=orgrole.mapper t=2025-01-21T13:54:47.636541055Z level=debug msg="No direct role mapping found"
logger=oauth.generic_oauth t=2025-01-21T13:54:47.636554484Z level=debug msg="Defaulting to using email for user info login" email=myusername.myname@mydomain.com
logger=oauth.generic_oauth t=2025-01-21T13:54:47.636559714Z level=debug msg="User info result" result="Id: 7ff01089-ca69-480b-b349-08761b6d8e31, Name: myusername myname, Email: myusername.myname@mydomain.com, Login: myusername.myname@mydomain.com, Role: , Groups: [], OrgRoles: map[1:Editor 2:Editor 3:Editor 10:Editor 11:Editor 12:Editor 13:Editor 14:Editor 15:Editor 16:Editor 17:Editor 18:Editor 19:Editor 20:Editor 21:Editor 22:Editor 23:Editor 24:Editor 25:Editor 26:Editor 27:Admin 28:Editor 29:Editor 30:Editor 31:Editor 32:Editor 33:Editor 34:Editor 35:Editor]"
logger=login.authinfo t=2025-01-21T13:54:47.651328257Z level=debug msg="auth info set in cache" cacheKey=authinfo-0-oauth_generic_oauth-7ff01089-ca69-480b-b349-08761b6d8e31
logger=user.sync t=2025-01-21T13:54:47.651763551Z level=debug msg="Updating auth connection for user" id=
logger=login.authinfo.store t=2025-01-21T13:54:47.660497136Z level=debug msg="Updated user_auth" user_id=62 auth_id=7ff01089-ca69-480b-b349-08761b6d8e31 auth_module=oauth_generic_oauth rows=1
logger=org.sync id=62 login=myusername.myname@mydomain.com t=2025-01-21T13:54:47.663376732Z level=debug msg="Syncing organization roles" extOrgRoles="map[1:Editor 2:Editor 3:Editor 10:Editor 11:Editor 12:Editor 13:Editor 14:Editor 15:Editor 16:Editor 17:Editor 18:Editor 19:Editor 20:Editor 21:Editor 22:Editor 23:Editor 24:Editor 25:Editor 26:Editor 27:Admin 28:Editor 29:Editor 30:Editor 31:Editor 32:Editor 33:Editor 34:Editor 35:Editor]"
Nothing in /userinfo
as specific attributes is read (and this is for sure I tried dozens of combinaison over 3 days
-
What did you expect to happen?
I would expect theorg_attribute_path
should retrieve value from/userinfo
calls or even from/token
call but as a string
Nothing in the doc mentions it’s impossible in the opensource version -
Can you copy/paste the configuration(s) that you are having problems with?
See above -
Did you receive any errors in the Grafana UI or in related logs? If so, please tell us exactly what they were.
I didn’t receive any Error , even in debugging mode I can see the/userinfo
having the values and grafana not being able to retrieve them ; see all logs above -
Did you follow any online instructions? If so, what is the URL?
Configure generic OAuth2 authentication | Grafana documentation