Due to an unplanned update of my Grafana Docker image I ended up with a new version of Grafana which seems to have somehow broken my Oauth connection to Keycloak.
I accidentally have been using grafana/grafana as image, so I don’t know what my previous version was, but I am now on v2.9.3
Steps to reproduce:
Select "Login with Keycloak on Grafana login page
Authenticate in Keycloak
Redirect leads to error message below
Below is the error I get in the grafana logs:
logger=oauth.generic_oauth t=2022-11-09T07:53:48.825034947Z level=error msg="Error getting email address" url=https://iam.myDomain.com/realms/myDomain/protocol/openid-connect/userinfo/emails error="{\"error\":\"RESTEASY003210: Could not find resource for full path: https://iam.myDomain.com/realms/myDomain/protocol/openid-connect/userinfo/emails\"}"
All users have got proper email addresses in Keycloak.
Were there any recent changes in the OAuth section of Grafana which may have led to a change in behaviour?
I realise that the Grafana update may be a false flag, and whatever the issue is, was simply exposed by restarting the server, but right now it’s the only change to Grafana and Keycloak I can think of.
Some more detail in case it’s relevant:
docker-compose.yml section:
Oh I know, have been bitten by this with other containers. Somehow this one survived unnoticed
Thanks for the link, I’ll work through it and will report back. The puzzling piece is that my setup has been working flawless for a few months and only broke after this update. Well, we’ll see…
I made a little bit of progress, if I understand things right, the link you pointed me to basically says the email address needs to be provided in the OAuth token.
So I went ahead and deciphered what Keycloak is returing via calling it directly from the cli:
Followed by sticking the token into this service JSON Web Tokens - jwt.io
At first there was indeed no email, nowhere. I therefore updated the client mapper in Keycloak, adding the email address.
Following that I can see that the email is now part of the payload:
to my docker-compose.yml to match the new “email” field in the screenshot higher up.
Unfortunately no difference.
There’s also GF_AUTH_GENERIC_OAUTH_EMAIL_ATTRIBUTE_PATH which may play a role here, but I am not sure if I need it and what it should look like.
Not sure if this means that a value named “type” is wrong, or if one of the many “value-types” is off. If it’s the later I guess I need to somehow find out which value-type is causing the issue. But definitely a start.
grafana | logger=oauth.generic_oauth t=2022-11-10T14:52:15.789642588Z level=debug msg="Getting user info"
grafana | logger=oauth.generic_oauth t=2022-11-10T14:52:15.789652226Z level=debug msg="Extracting user info from OAuth token"
grafana | logger=oauth.generic_oauth t=2022-11-10T14:52:15.789659908Z level=debug msg="No id_token found" token="unsupported value type"
grafana | logger=oauth.generic_oauth t=2022-11-10T14:52:15.789670245Z level=debug msg="Getting user info from API"
grafana | logger=oauth.generic_oauth t=2022-11-10T14:52:15.793005501Z level=debug msg="Error getting user info from API" url=https://iam.mydomain.com/realms/myRealm/protocol/openid-connect/userinfo error=…
I searched through the token clear text and decoded, but there is no “type” anywhere. Only “typ”: “Bearer” in the decoded payload would come closest. A typo? Most likely not…
My knowledge in this area is pretty shallow so I am trying to make sense of this all.
The beginning of the payload is:
I bet you don’t have id token, because you didn’t use openid scope, so you have pure OAuth (and not OpenID Connect). Configure GF_AUTH_GENERIC_OAUTH_SCOPES properly.
I am afraid, I don’ know what a proper configuration of the scopes would look like.
Before things stopped working I had just “profile” as scope in Grafana.
GF_AUTH_GENERIC_OAUTH_SCOPES: “profile”
I meanwhile changed the email scope in Keycloak from optional to default, which makes the email address show up in the token payload.
I tried adding “email” explicitly to the scope, with and without “profile”, but no success.
GF_AUTH_GENERIC_OAUTH_SCOPES: “profile, email”
Other than that, the client is set up as OpenID connect (#1)
grafana:
persistence:
enabled: true
storageClassName: "rook-ceph-block"
grafana.ini:
server:
domain: grafana.xxx.com
root_url: https://grafana.xxx.com
log:
filters: "oauth.generic_oauth:debug"
auth.generic_oauth:
enabled: true
name: Keycloak
client_id: grafana
client_secret: gLfARsNXIIxb0eK5Xj9nnb8G6UKIITt1
scopes: ["openid", "profile", "email", "offline_access", "roles"]
role_attribute_path: "contains(roles[*], 'grafana_admin') && 'Admin' || contains(roles[*], 'grafana_editor') && 'Editor' || 'Viewer'"
email_attribute_path: "email"
login_attribute_path: "username"
name_attribute_path: "full_name"
auth_url: "https://keycloak.xxx.com/realms/itps/protocol/openid-connect/auth"
token_url: "http://keycloak.security.svc.cluster.local/realms/itps/protocol/openid-connect/token"
# Note: api_url is not required if the id_token contains all the necessary user information and can add latency to the login process.
# It is useful as a fallback or if the user has more than 150 group memberships
api_url: "http://keycloak.security.svc.cluster.local/realms/itps/protocol/openid-connect/userinfo"
allow_sign_up: true
panels:
disable_sanitize_html: true
logs:
logger=context userId=0 orgId=0 uname= t=2023-08-08T03:45:17.44805103Z level=info msg="Request Completed" method=GET path=/login/generic_oauth status=302 remote_addr=172.16.89.0 time_ms=1 duration=1.071894ms size=267 referer=https://grafana.bgzchina.com/login handler=/login/:name
logger=oauth t=2023-08-08T03:45:27.417034569Z level=info msg="state check" queryState=922a0fe801fb1ed0fb8937d9cf3f9a0c86c87cc8ed137cf0f1809b443675a499 cookieState=922a0fe801fb1ed0fb8937d9cf3f9a0c86c87cc8ed137cf0f1809b443675a499
logger=oauth.generic_oauth t=2023-08-08T03:45:27.428978661Z level=debug msg="Getting user info"
logger=oauth.generic_oauth t=2023-08-08T03:45:27.429050436Z level=debug msg="Extracting user info from OAuth token"
logger=oauth.generic_oauth t=2023-08-08T03:45:27.429060039Z level=debug msg="No id_token found" token="unsupported value type"
logger=oauth.generic_oauth t=2023-08-08T03:45:27.429081616Z level=debug msg="Getting user info from API"
logger=oauth.generic_oauth t=2023-08-08T03:45:27.431844892Z level=debug msg="Error getting user info from API" url=http://keycloak.security.svc.cluster.local/realms/itps/protocol/openid-connect/userinfo error=
logger=oauth.generic_oauth t=2023-08-08T03:45:27.432880616Z level=error msg="Error getting email address" url=http://keycloak.security.svc.cluster.local/realms/itps/protocol/openid-connect/userinfo/emails error="{\"error\":\"RESTEASY003210: Could not find resource for full path: http://keycloak.security.svc.cluster.local/realms/itps/protocol/openid-connect/userinfo/emails\"}"
logger=context userId=0 orgId=0 uname= t=2023-08-08T03:45:27.432956841Z level=error msg="login.OAuthLogin(get info from generic_oauth)" error="Error getting email address: {\"error\":\"RESTEASY003210: Could not find resource for full path: http://keycloak.security.svc.cluster.local/realms/itps/protocol/openid-connect/userinfo/emails\"}"