Grafana Integration
Add Twingate user identity to Grafana with its built-in JWT or trusted-header authentication.
Grafana ships with the ability to validate JWTs via the auth.jwt configuration. Grafana receives and validates the JWT via a configurable header and JWKS endpoint. This option is only available if outbound connections are allowed as Grafana will need to access the Twingate JWKS endpoint for its token validation process.
If your Grafana instance has network restrictions, you can use the trusted-header integration. Only choose this option if your network infrastructure does not allow Grafana to reach the Twingate JWKs endpoint. The trusted-header integration is less secure than JWT validation, but it still allows you to authenticate users and provision accounts without code changes.
For the architecture and the full list of headers the Gateway can inject, see the Identity Firewall for Web Apps overview.
Prerequisites
- A Grafana instance you administer (this guide was verified against Grafana 11.4).
- Administrator access to Grafana’s configuration, whether through environment variables or
grafana.ini. - A Twingate Web App Resource for Grafana, network-isolated so the Gateway is the only path to it.
JWT Auth Based Integration (Recommended)
Enable auth.jwt and tell Grafana which header carries the signed-in user JWT. You can set these as GF_* environment variables:
GF_AUTH_JWT_ENABLED=trueGF_AUTH_JWT_JWK_SET_URL=https://<your-tenant>.twingate.com/api/v1/jwk/ecGF_AUTH_JWT_HEADER_NAME=X-JWT-AssertionGF_AUTH_JWT_USERNAME_ATTRIBUTE_PATH=user.usernameGF_AUTH_JWT_EMAIL_ATTRIBUTE_PATH=user.emailGF_AUTH_JWT_AUTO_SIGN_UP=trueGF_AUTH_DISABLE_LOGIN_FORM=trueOr as the equivalent grafana.ini sections:
[auth.jwt]enabled = truejwk_set_url = https://<your-tenant>.twingate.com/api/v1/jwk/echeader_name = X-JWT-Assertionusername_attribute_path = user.usernameemail_attribute_path = user.emailauto_sign_up = true
[auth]disable_login_form = trueEach setting does the following:
| Setting | Value | Purpose |
|---|---|---|
enabled | true | Turns on JWT authentication. |
jwk_set_url | https://<your-tenant>.twingate.com/api/v1/jwk/ec | The URL to fetch the JSON Web Key Set for validating JWTs. |
header_name | X-JWT-Assertion | The header Grafana reads the user from. |
username_attribute_path | user.username | The JWT claim Grafana uses as the username. |
email_attribute_path | user.email | The JWT claim Grafana uses as the email. |
auto_sign_up | true | Provisions the user on their first request, so you don’t pre-create accounts. |
disable_login_form | true | Hides Grafana’s local login form, since authentication now comes from Twingate. |
Configure the Twingate Gateway
On the Grafana Web App Resource, add a request header so the Gateway injects the identity on every request:
| Header Key | Value Template |
|---|---|
X-JWT-Assertion | {{jwt}} |
{{jwt}} resolves to the signed-in user’s Twingate JWT.
How It Works
On each request, the Gateway injects the X-JWT-Assertion header with the user’s JWT, then forwards to Grafana. Grafana’s auth.jwt handler reads the username from the JWT’s user.username claim and email from the user.email claim. If no matching account exists, auto_sign_up creates one. There’s no separate user administration step in Grafana. Accounts are provisioned straight from the JWT.
Trusted Header Integration (Fallback)
This section uses Grafana’s auth.proxy configuration, which reads the signed-in user from a header. If your Grafana instance can reach the Twingate JWKs endpoint, use the JWT integration instead. It validates the JWT cryptographically, which is more secure than trusting a header. If you follow this guide, make sure that the only traffic that is allowed to send headers to Grafana is coming from the Twingate Gateway.
Enable auth.proxy and tell Grafana which header carries the signed-in user. You can set these as GF_* environment variables:
GF_AUTH_PROXY_ENABLED=trueGF_AUTH_PROXY_HEADER_NAME=X-WEBAUTH-USERGF_AUTH_PROXY_HEADER_PROPERTY=usernameGF_AUTH_PROXY_AUTO_SIGN_UP=trueGF_AUTH_DISABLE_LOGIN_FORM=trueOr as the equivalent grafana.ini sections:
[auth.proxy]enabled = trueheader_name = X-WEBAUTH-USERheader_property = usernameauto_sign_up = truewhitelist = <gateway-ip>
[auth]disable_login_form = trueEach setting does the following:
| Setting | Value | Purpose |
|---|---|---|
enabled | true | Turns on trusted-header authentication. |
header_name | X-WEBAUTH-USER | The header Grafana reads the user from. |
header_property | username | Treats the header value as the username. |
auto_sign_up | true | Provisions the user on their first request, so you don’t pre-create accounts. |
whitelist | <gateway-ip> | Restricts trusted-header authentication to requests coming from the Gateway. |
disable_login_form | true | Hides Grafana’s local login form, since authentication now comes from Twingate. |
On the Twingate path, the Gateway overwrites any client-supplied X-WEBAUTH-USER, so a forged header can’t reach Grafana through Twingate. That only covers requests coming through the Gateway, though. Other internal services or endpoints that can reach Grafana directly over the network could still forge the header. Pinning auth.proxy.whitelist to the Gateway IP ensures Grafana trusts the header only when it comes from the Gateway. See Web App Integrations for the full model.
Configure the Twingate Gateway
On the Grafana Web App Resource, add a request header so the Gateway injects the identity on every request:
| Header Key | Value Template |
|---|---|
X-WEBAUTH-USER | {{username}} |
{{username}} resolves to the signed-in user’s Twingate username.
How It Works
On each request, the Gateway injects X-WEBAUTH-USER, then forwards to Grafana. Grafana’s auth.proxy handler reads the username from X-WEBAUTH-USER. If no matching account exists, auto_sign_up creates one. There’s no separate user administration step in Grafana; accounts are provisioned straight from the header.
Next Steps
- Jenkins integration guide for another trusted-header web app integration
- Web App Integrations for the shared trusted-header pattern
- Identity Firewall for Web Apps overview for all available header template variables
Join us in the community subreddit to share your setup or ask questions.
Last updated 3 hours ago