Skip to main content

Grafana

This guide explains how to configure single sign-on (SSO) between VaultysHub and Grafana using OpenID Connect. Grafana offers excellent native support for OAuth2/OpenID Connect.

Prerequisites​

  • Grafana version 7.0 or higher
  • Administrator access to Grafana
  • Application configured in VaultysHub with OpenID Connect
  • HTTPS configured on Grafana (recommended)

Configuration in VaultysHub​

1. Create the application​

  1. Log in to VaultysHub as an administrator
  2. Go to Applications → Add
  3. Create a new application:
    • Name: Grafana
    • URL: https://grafana.example.com
    • Description: Monitoring and observability platform
    • Icon: Choose the Grafana icon

2. Configure OpenID Connect​

  1. In the Authentication tab
  2. Select OpenID Connect
  3. Note the information:
    • Client ID: grafana-xxxxxx
    • Client Secret: secret-xxxxxx
    • Issuer URL: https://your-vaultyshub.link.vaultys.org/api/oidc/[appid]
    • App ID: [appid] (unique identifier of the application in VaultysHub)

3. Redirect URLs​

Add to Allowed redirect URLs:

https://grafana.example.com/login/generic_oauth

4. Scopes and claims​

Required scopes:

  • openid
  • profile
  • email

Configuration in Grafana​

1. Configuration via INI file​

Edit /etc/grafana/grafana.ini or /conf/grafana.ini:

#################################### Auth ####################################
[auth]
# Disable account creation via the interface
disable_login_form = false
disable_signout_menu = false
# OAuth auto login
oauth_auto_login = true
# Automatic team synchronization
oauth_allow_insecure_email_lookup = false

#################################### Generic OAuth ##########################
[auth.generic_oauth]
enabled = true
name = VaultysHub SSO
allow_sign_up = true
auto_login = false
client_id = grafana-xxxxxx
client_secret = secret-xxxxxx
scopes = openid profile email
email_attribute_name = email
email_attribute_path = email
login_attribute_path = email
name_attribute_path = name
role_attribute_strict = false
allow_assign_grafana_admin = true
auth_url = https://your-vaultyshub.link.vaultys.org/api/oidc/[appid]/auth
token_url = https://your-vaultyshub.link.vaultys.org/api/oidc/[appid]/token
api_url = https://your-vaultyshub.link.vaultys.org/api/oidc/[appid]/userinfo
signout_redirect_url = https://your-vaultyshub.link.vaultys.org/api/oidc/[appid]/logout
use_pkce = true
use_refresh_token = true

2. Configuration via environment variables​

For Docker or Kubernetes:

version: '3.8'
services:
grafana:
image: grafana/grafana:latest
environment:
# OAuth Configuration
- GF_AUTH_GENERIC_OAUTH_ENABLED=true
- GF_AUTH_GENERIC_OAUTH_NAME=VaultysHub SSO
- GF_AUTH_GENERIC_OAUTH_ALLOW_SIGN_UP=true
- GF_AUTH_GENERIC_OAUTH_CLIENT_ID=grafana-xxxxxx
- GF_AUTH_GENERIC_OAUTH_CLIENT_SECRET=secret-xxxxxx
- GF_AUTH_GENERIC_OAUTH_SCOPES=openid profile email
- GF_AUTH_GENERIC_OAUTH_EMAIL_ATTRIBUTE_NAME=email
- GF_AUTH_GENERIC_OAUTH_EMAIL_ATTRIBUTE_PATH=email
- GF_AUTH_GENERIC_OAUTH_LOGIN_ATTRIBUTE_PATH=email
- GF_AUTH_GENERIC_OAUTH_NAME_ATTRIBUTE_PATH=name
- GF_AUTH_GENERIC_OAUTH_AUTH_URL=https://your-vaultyshub.link.vaultys.org/api/oidc/[appid]/auth
- GF_AUTH_GENERIC_OAUTH_TOKEN_URL=https://your-vaultyshub.link.vaultys.org/api/oidc/[appid]/token
- GF_AUTH_GENERIC_OAUTH_API_URL=https://your-vaultyshub.link.vaultys.org/api/oidc/[appid]/userinfo
- GF_AUTH_GENERIC_OAUTH_USE_PKCE=true
# Auto login
- GF_AUTH_OAUTH_AUTO_LOGIN=true
# Disable anonymous authentication
- GF_AUTH_ANONYMOUS_ENABLED=false
ports:
- "3000:3000"
volumes:
- grafana-data:/var/lib/grafana

volumes:
grafana-data:

3. Helm Configuration (Kubernetes)​

# values.yaml for the Grafana chart
grafana:
grafana.ini:
auth:
oauth_auto_login: true
auth.generic_oauth:
enabled: true
name: VaultysHub SSO
allow_sign_up: true
client_id: grafana-xxxxxx
client_secret: secret-xxxxxx
scopes: openid profile email
auth_url: https://your-vaultyshub.link.vaultys.org/api/oidc/[appid]/auth
token_url: https://your-vaultyshub.link.vaultys.org/api/oidc/[appid]/token
api_url: https://your-vaultyshub.link.vaultys.org/api/oidc/[appid]/userinfo

Role and Permission Management​

Automatic Role Mapping​

Grafana supports three main roles: Admin, Editor, and Viewer.

VaultysHub can pass the user's groups to Grafana, derived from the folders they belong to. Grafana uses this to automatically assign the role:

  1. In VaultysHub, open the Grafana application, Groups section: check Send groups and associate your folders with group names, for example, the Ops folder to grafana-admins and the Development folder to grafana-editors (see Send groups).
  2. In Grafana, add the scope groups and the role rule:
[auth.generic_oauth]
scopes = openid email profile groups
groups_attribute_path = groups
role_attribute_path = contains(groups[*], 'grafana-admins') && 'Admin' || contains(groups[*], 'grafana-editors') && 'Editor' || 'Viewer'

The list of groups is sent at each login, even empty: a user removed from a folder loses the corresponding role at their next login.

Without this configuration, new users receive the default role of Grafana (auto_assign_org_role, Viewer by default), and roles are managed directly in Grafana.

Automatic Provisioning​

Dashboards and datasources​

Create /etc/grafana/provisioning/datasources/smartlink.yaml:

apiVersion: 1

datasources:
- name: Prometheus
type: prometheus
access: proxy
url: http://prometheus:9090
isDefault: true
editable: false

- name: Loki
type: loki
access: proxy
url: http://loki:3100
editable: false

Team Folder Configuration​

# /etc/grafana/provisioning/dashboards/teams.yaml
apiVersion: 1

providers:
- name: 'team-dashboards'
orgId: 1
folder: ''
type: file
disableDeletion: false
updateIntervalSeconds: 10
allowUiUpdates: true
options:
path: /var/lib/grafana/dashboards
foldersFromFilesStructure: true

Configuration Testing​

1. Connection Test​

  1. Restart Grafana:

    systemctl restart grafana-server
    # or
    docker-compose restart grafana
  2. Access https://grafana.example.com

  3. Click on Sign in with VaultysHub SSO

  4. Authenticate on VaultysHub

  5. You should be logged into Grafana

2. Permission Verification​

# Via the Grafana API
curl -H "Authorization: Bearer YOUR_TOKEN" \
https://grafana.example.com/api/user

# Expected response
{
"id": 1,
"email": "[email protected]",
"name": "John Doe",
"login": "johndoe",
"role": "Admin",
"isGrafanaAdmin": false
}

3. Role Testing​

  1. Log in with different users
  2. Check the permissions:
    • Admin: Can create/edit dashboards and datasources
    • Editor: Can create/edit dashboards
    • Viewer: Read-only

Troubleshooting​

Error "login.OAuthLogin(missing saved state)"​

Problem: Session/cookies issue

Solution:

  1. Check cookie configuration:
    [security]
    cookie_secure = true
    cookie_samesite = lax
  2. Ensure you are using HTTPS
  3. Verify that the domains match

Error "User not a member of one of the required organizations"​

Problem: The user does not have the correct permissions

Solution:

  1. Check the user's organization and role in Grafana
  2. Verify allow_sign_up = true

Groups are not mapped correctly​

Problem: Roles are not assigned correctly

Solution:

  1. Ensure Send groups is checked in the Groups section of the application, and that the user's folder is associated with a group name
  2. Verify that groups is included in the scopes of Grafana
  3. Ensure that the names used in role_attribute_path exactly match the group names configured in VaultysHub

Error "Failed to get user info"​

Problem: Grafana cannot retrieve user information

Solution:

  1. Test the UserInfo endpoint:
    curl -H "Authorization: Bearer TOKEN" \
    https://your-vaultyshub.link.vaultys.org/api/oidc/[appid]/userinfo
  2. Check api_url in the configuration
  3. Verify the requested scopes

Security​

Recommendations​

  1. HTTPS required: Always use HTTPS
  2. PKCE enabled: use_pkce = true
  3. Secure cookies:
    [security]
    cookie_secure = true
    cookie_httponly = true
  4. Limit anonymous viewers:
    [auth.anonymous]
    enabled = false
  5. Audit logs:
    [log]
    mode = file
    level = info
    [log.file]
    log_rotate = true
    max_lines = 1000000
    max_size_shift = 28
    daily_rotate = true
    max_days = 7

Protection against brute force​

[security]
# Enable brute force protection
disable_brute_force_login_protection = false
# Secret to sign cookies
secret_key = YOUR_SECRET_KEY

Advanced Configuration​

Multi-tenancy with organizations​

[auth.generic_oauth]
# Automatically create the organization if it does not exist
auto_assign_org = true
auto_assign_org_id = 1
# Allow organization switching
allow_org_switch = true

Integration with Terraform​

resource "grafana_folder" "team_folders" {
for_each = var.teams
title = each.value.name
}

resource "grafana_team" "teams" {
for_each = var.teams
name = each.value.name
members = each.value.members
}

resource "grafana_dashboard_permission" "team_permissions" {
for_each = var.teams
dashboard_id = grafana_folder.team_folders[each.key].id
permissions {
team_id = grafana_team.teams[each.key].id
permission = "Edit"
}
}

Authentication Monitoring​

# Prometheus metrics for authentication
[metrics]
enabled = true
interval_seconds = 10

[metrics.graphite]
address = localhost:2003
prefix = prod.grafana.%(instance_name)s.

Resources​