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.

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=true
GF_AUTH_JWT_JWK_SET_URL=https://<your-tenant>.twingate.com/api/v1/jwk/ec
GF_AUTH_JWT_HEADER_NAME=X-JWT-Assertion
GF_AUTH_JWT_USERNAME_ATTRIBUTE_PATH=user.username
GF_AUTH_JWT_EMAIL_ATTRIBUTE_PATH=user.email
GF_AUTH_JWT_AUTO_SIGN_UP=true
GF_AUTH_DISABLE_LOGIN_FORM=true

Or as the equivalent grafana.ini sections:

[auth.jwt]
enabled = true
jwk_set_url = https://<your-tenant>.twingate.com/api/v1/jwk/ec
header_name = X-JWT-Assertion
username_attribute_path = user.username
email_attribute_path = user.email
auto_sign_up = true
[auth]
disable_login_form = true

Each setting does the following:

SettingValuePurpose
enabledtrueTurns on JWT authentication.
jwk_set_urlhttps://<your-tenant>.twingate.com/api/v1/jwk/ecThe URL to fetch the JSON Web Key Set for validating JWTs.
header_nameX-JWT-AssertionThe header Grafana reads the user from.
username_attribute_pathuser.usernameThe JWT claim Grafana uses as the username.
email_attribute_pathuser.emailThe JWT claim Grafana uses as the email.
auto_sign_uptrueProvisions the user on their first request, so you don’t pre-create accounts.
disable_login_formtrueHides 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 KeyValue 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=true
GF_AUTH_PROXY_HEADER_NAME=X-WEBAUTH-USER
GF_AUTH_PROXY_HEADER_PROPERTY=username
GF_AUTH_PROXY_AUTO_SIGN_UP=true
GF_AUTH_DISABLE_LOGIN_FORM=true

Or as the equivalent grafana.ini sections:

[auth.proxy]
enabled = true
header_name = X-WEBAUTH-USER
header_property = username
auto_sign_up = true
whitelist = <gateway-ip>
[auth]
disable_login_form = true

Each setting does the following:

SettingValuePurpose
enabledtrueTurns on trusted-header authentication.
header_nameX-WEBAUTH-USERThe header Grafana reads the user from.
header_propertyusernameTreats the header value as the username.
auto_sign_uptrueProvisions 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_formtrueHides 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 KeyValue 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

Join us in the community subreddit to share your setup or ask questions.

Last updated 3 hours ago