Setting Up SSO with Zitadel for Grafana

My multi-iteration experience of setting up SSO for my Grafana in homelab

Recently, I decided to enhance the security and user experience of my Grafana instance by implementing Single Sign-On (SSO) with Zitadel as the identity provider. I have written an article a year ago for something similar with Zitadel and Tailscale. In this blog post, I’ll share my experience following the process outlined in this helpful article, along with some additional insights and tips I discovered along the way.

What is Zitadel? (to those wonder)

Zitadel is an open-source identity management platform that provides authentication, authorization, and user management functionality. It supports various authentication protocols including OAuth 2.0 and OpenID Connect (OIDC), making it an excellent choice for implementing SSO across multiple applications.

Why implement SSO for Grafana?

Before diving into the technical details, here’s why I decided to implement SSO:

  1. Centralized User Management: Managing users in a single location rather than maintaining separate credentials for Grafana
  2. Enhanced Security: Reducing password fatigue and enabling stronger authentication mechanisms
  3. Improved User Experience: Allowing users to access Grafana without having to remember another set of credentials
  4. Standardization: Aligning with modern authentication best practices

Prerequisites

Before starting, I made sure I had:

  • A running Grafana instance (I am using version 11.x hosted in my Docker)
  • Access to Zitadel (I use the cloud version, but you can also self-host)
  • Administrative privileges on both platforms
  • Basic understanding of OIDC concepts
Step 1: Creating a project in Zitadel

I started by logging into my Zitadel instance and got to my Grafana project, (in your case it may be creating a new project):

  1. Navigated to the “Projects” section and click “Create New Project”. Since I’ve my Grafana project already, I opened it directly.
  2. In your case, name the project “Grafana” or something meaningful for you and click Continue. It will create the new project straight away.
Step 2: Creating an OIDC application

Once project was created, I needed to configure an OIDC application:

  1. Inside the project, I selected “New” under the Applications section
  2. Click “I’m Pro. Skip this wizard”, It’ll save your time.
  3. I named the application “Grafana_SSO”, you name something meaningful for you.
  4. I chose Application Type as Web, the moment you change this, other features will pop-up or revealed.
  5. In Grant Type, choose “Authorization Code” and “Refresh Token”. In Response Type, choose “Code”.
  6. In Authentication Method, choose “None”. (“Basic” will work too)
  7. For the redirect URIs, I added https://[my-grafana-domain]/login/generic_oauth add, whatever in your case by replacing the exact Grafana URL path, sometimes it will be https://grafana-ip:3000/login/generic_oauth
  8. In the Token Settings, Set “Auth Token Type” to “JWT” and check all the three options underneath “Auth Token Type”
Step 3: Configuring Grafana

The next step was to update my Grafana configuration to use Zitadel as an OIDC provider. I edited Grafana GUI directly. You can edit grafana.ini file (or environment variables if using Docker):

[auth.generic_oauth]
enabled = true
name = Zitadel
allow_sign_up = true
client_id = [my-client-id-from-zitadel]
client_secret = [my-client-secret-from-zitadel]
scopes = openid email profile
auth_url = https://[my-zitadel-domain]/oauth/v2/authorize
token_url = https://[my-zitadel-domain]/oauth/v2/token
api_url = https://[my-zitadel-domain]/oidc/v1/userinfo
role_attribute_path = contains(roles[*], 'Grafana Admin') && 'Admin' || contains(roles[*], 'Grafana Editor') && 'Editor' || 'Viewer'
Step 4: Configuring User Roles in Zitadel

To manage user permissions effectively, I created roles in Zitadel:

  1. In my Zitadel project, I went to the “Roles” section and created three roles:
    • “Grafana Admin”
    • “Grafana Editor”
    • “Grafana Viewer”
  2. I then assigned these roles to appropriate users

The role_attribute_path in my Grafana configuration maps these Zitadel roles to the corresponding Grafana roles.

Step 5: Testing the Integration

After restarting Grafana (in my case, I do not need to restart because I added them in Grafana GUI settings) to apply the configuration changes, I tested the integration:

  1. Navigated to my Grafana login page
  2. Clicked on the “Sign in with Zitadel” button
  3. Was redirected to the Zitadel login page
  4. After authentication, I was successfully redirected back to Grafana with appropriate permissions

Troubleshooting

During the implementation, I encountered a few issues:

Issue 1: Scopes can be set to openid, email and profile only

Initially, I have openid email profile offline_access roles, but it can be avoided by choosing the Auth Token Type JWT and three options beneath it.

Issue 2: Role Mapping

My initial role mapping wasn’t working correctly. I had to adjust the role_attribute_path to properly parse the roles coming from Zitadel.

Additional Tips

Here are some additional insights I gained during this process:

  1. Log Inspection: Grafana’s logs provided valuable information when troubleshooting authentication issues
  2. Test Users: Creating test users with different roles helped verify that permissions were working correctly
  3. JWK Configuration: For enhanced security, consider configuring the JWK endpoint in Grafana
  4. MFA: Consider enabling Multi-Factor Authentication in Zitadel for additional security

Conclusion

Implementing SSO between Zitadel and Grafana has significantly improved both security and user experience for my monitoring setup. The process was relatively straightforward, thanks to good documentation from both platforms.

The ability to centrally manage user access and leverage modern authentication protocols has been valuable, and I’m looking forward to extending this SSO setup to other applications in my infrastructure.

Have you implemented SSO for your monitoring tools? I’d love to hear about your experiences!

Resources


See also