Keycloak OAuth2 authentication allows users to log in to Grafana using their Keycloak credentials. This guide explains how to set up Keycloak as an authentication provider in Grafana.
As an example, `<PROVIDER_DOMAIN>` can be `keycloak-demo.grafana.org`
and `<REALM_NAME>` can be `grafana`.
> **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.
## Keycloak configuration
1. Create a client in Keycloak with the following settings:
- Client ID: `grafana-oauth`
- Enabled: `ON`
- Client Protocol: `openid-connect`
- Access Type: `confidential`
- Standard Flow Enabled: `ON`
- Implicit Flow Enabled: `OFF`
- Direct Access Grants Enabled: `ON`
- Root URL: `<grafana_root_url>`
- Valid Redirect URIs: `<grafana_root_url>/*`
- Web Origins: `<grafana_root_url>`
- Admin URL: `<grafana_root_url>`
- Base URL: `<grafana_root_url>`
As an example, `<grafana_root_url>` can be `https://play.grafana.org`.
Non-listed configuration options can be left at their default values.
2. In the client scopes configuration, _Assigned Default Client Scopes_ should match:
```
email
offline_access
profile
roles
```
> **Warning**: these scopes do not add group claims to the id_token. Without group claims, teamsync will not work. Teamsync is covered further down in this document.
3. For role mapping to work with the example configuration above,
you need to create the following roles and assign them to users:
> **Note:** Available in [Grafana Enterprise]({{< relref "../../../../introduction/grafana-enterprise" >}}) and [Grafana Cloud Advanced](/docs/grafana-cloud/).
[Teamsync]({{< relref "../../configure-team-sync" >}}) is a feature that allows you to map groups from your identity provider to Grafana teams. This is useful if you want to give your users access to specific dashboards or folders based on their group membership.
If you use nested groups containing special characters such as quotes or colons, the JMESPath parser can perform a harmless reverse function so Grafana can properly evaluate nested groups. The following example shows a parent group named `Global` with nested group `department` that contains a list of groups:
> **Note:** This feature is behind the `accessTokenExpirationCheck` feature toggle.
When a user logs in using an OAuth provider, Grafana verifies that the access token has not expired. When an access token expires, Grafana uses the provided refresh token (if any exists) to obtain a new access token.
Grafana uses a refresh token to obtain a new access token without requiring the user to log in again. If a refresh token doesn't exist, Grafana logs the user out of the system after the access token has expired.
To enable a refresh token for Keycloak, extend the `scopes` in `[auth.generic_oauth]` with `offline_access`.