Grafana OAuth SSO Integration with KeyCloak
Single Sign-On integration is important. In my previous post, I demonstrated how to use Keycloak as the authentication layer in a FastAPI application. Now we will use Keycloak as identity provider for Grafana.
I'm going to run all those in my local env. So change the hostnames or FQDN for your domain.
Create KeyCloak Client
Properties of Keycloak client must be like following;
- Client Type: OpenID Connect
Client ID: grafana-oauth - Authentication: On
Authentication Flow: Standart Flow Enabled
Direct access grants Enabled - Root URL: Grafana's root url
Home URL: Grafana's root url
Valid Redirect URIs: Grafana's root url +/login/generic_oauth
Web Origins: Grafana's root url
After creating the client, go to client details page and click Credentials tab to obtain client secret.
Grafana Compose File and OAuth Configuration
What to replace the file in below;
- Your realm name and Client secret
- Your keycloak hostname. (There are two domains. Localhost is sent to browser. Host.docker.internal is for Grafana access to Keycloak.
version: '3.8'
services:
grafana:
image: docker.io/grafana/grafana-oss:12.0.2
container_name: grafana
restart: unless-stopped
environment:
- GF_SERVER_ROOT_URL=http://localhost:3000/
- GF_PLUGINS_PREINSTALL=grafana-clock-panel
- GF_SECURITY_ADMIN_USER=admin
- GF_SECURITY_ADMIN_PASSWORD=admin
- GF_AUTH_GENERIC_OAUTH_ENABLED=true
- GF_AUTH_GENERIC_OAUTH_NAME=Keycloak-OAuth
- GF_AUTH_GENERIC_OAUTH_ALLOW_SIGN_UP=true
- GF_AUTH_GENERIC_OAUTH_CLIENT_ID=grafana-oauth
- GF_AUTH_GENERIC_OAUTH_CLIENT_SECRET=[SECRET]
- GF_AUTH_GENERIC_OAUTH_SCOPES=openid email profile offline_access roles
- GF_AUTH_GENERIC_OAUTH_EMAIL_ATTRIBUTE_PATH=email
- GF_AUTH_GENERIC_OAUTH_LOGIN_ATTRIBUTE_PATH=username
- GF_AUTH_GENERIC_OAUTH_NAME_ATTRIBUTE_PATH=full_name
- GF_AUTH_GENERIC_OAUTH_AUTH_URL=http://localhost:8080/realms/local/protocol/openid-connect/auth
- GF_AUTH_GENERIC_OAUTH_TOKEN_URL=http://host.docker.internal:8080/realms/local/protocol/openid-connect/token
- GF_AUTH_GENERIC_OAUTH_API_URL=http://host.docker.internal:8080/realms/local/protocol/openid-connect/userinfo
- GF_AUTH_GENERIC_OAUTH_ROLE_ATTRIBUTE_PATH=contains(roles[*], 'admin') && 'Admin' || contains(roles[*], 'editor') && 'Editor' || 'Viewer'
ports:
- '3000:3000'
volumes:
- 'grafana_storage:/var/lib/grafana'
volumes:
grafana_storage:
You would see you can log in to Grafana via your Keycloak user. One important note here. In the localhost; you can't map Keycloak roles to Grafana users. OAUTH_ROLE_ATTRIBUTE_PATH
defines mapping. So normally you should assign that role to user. It's happening due to localhost and host.docker.internal domains' differences. The JWT token couldn't be verified by Grafana so it doesn't fetch it. But it works in production. And make sure, the path matches with the key in your JWT token. Adjust it by the token. Or modify client scope details in Keycloak.