Embedding Grafana dashboards in other applications: when teams need it
Embedding means displaying Grafana panels or dashboards inside another application, such as a product, customer portal or internal tool, so that people see operational charts without opening Grafana itself. On a self-hosted instance, the embedded frame is served by your Grafana server, so the work is less about rendering and more about deciding who is allowed to see the chart and how their identity reaches Grafana. A product or portal team usually arrives here because its own users need uptime, usage or capacity views that should not require a Grafana login.
There are three main routes. The first is an iframe with allow_embedding enabled, which lets a page on another origin load a Grafana dashboard, typically for users who already have a Grafana account or a trusted session. The second is JWT authentication, where a reverse proxy in front of Grafana validates the caller and injects a signed token, so the viewer never signs in to Grafana directly. The third is an externally shared dashboard, which serves a dashboard to people with no account at all. Each route suits a different viewer: employees, authenticated customers, or anonymous readers. Choosing the wrong one either exposes data or forces users through a login they do not need.
Before choosing, ask who the viewer is, which data sources the panels query, and whether those queries are safe to expose to that audience. Confirm with your Grafana edition and hosting model that the setting you need is available, since the JWT route depends on settings that are not offered on every platform. Also confirm how your identity provider and proxy will issue and expire tokens, because Grafana's current JWT support does not include refresh tokens. Settle these questions first, as they determine the build, the security review and the operating model that follow.
Which embedding route fits which viewer
Three routes put Grafana panels in front of other people: an iframe that relies on JWT authentication, an externally shared dashboard, and a URL login. Each serves a different viewer and carries a different constraint, so the choice starts with who will look at the panel and whether they hold a Grafana account.
Iframe with JWT authentication
This route suits signed-in users of your own application who should see live panels without a second login. A reverse proxy in front of Grafana injects a JWT header, and allow_embedding must be enabled so the browser accepts the frame. The main constraint is that this setting is not available in Grafana Cloud, so a Cloud deployment cannot use this route. Check that your Grafana instance and proxy are in the same trust boundary as your application, and confirm who can reach the embedding page.
Externally shared dashboards
This route suits people outside your identity system who need a read-only view of one dashboard, such as a partner or an auditor. Viewers do not need a Grafana account. The trade-off is that the shared view is a separate exposure surface, so you should review which data sources and features work in that mode before you share anything. Confirm that the shared content contains no sensitive labels or annotations.
URL login with a token parameter
This route passes a JWT in the auth_token query parameter when url_login is enabled. It is the quickest way to open a Grafana view from another page, but it is the weakest option. The docs warn that tokens can appear in logs and that a captured token enables session hijacking when TLS is absent. Treat it as a restricted pattern, keep TLS enforced end to end, and check proxy and access logs before enabling it.
Token lifetime and renewal
Grafana does not currently support refresh tokens for JWT authentication. Your application must issue a new JWT when a session expires, and the embedded panel will stop loading until it does. Plan token lifetimes with your identity team, decide where renewal happens, and test what users see when a token lapses in the middle of a session.
Deployment type and edition
Your Grafana deployment type decides which routes are open to you. Self-hosted open-source instances can enable allow_embedding and JWT settings, while Grafana Cloud cannot use the iframe route. Confirm the deployment model before you design the user flow, and ask your vendor or the Grafana docs to confirm current behavior for your version.
How a reverse proxy injects JWT for iframe embedding
The host application never handles Grafana credentials. When a user opens a page that contains a Grafana iframe, the browser requests the dashboard URL through your reverse proxy. The proxy authenticates the user against your existing session or identity provider, then adds a signed JWT to the request in a header that Grafana is configured to read. Grafana validates the signature against the key you configured, maps the claims to a user and role, and renders the dashboard inside the frame. The proxy is therefore the trust boundary: if it forwards requests without checking the user first, anyone who can reach the Grafana URL can be signed in under whatever identity the proxy supplies.
Two settings must be enabled on the Grafana side. JWT authentication has to be turned on in the [auth.jwt] section, with the header name, key or JWKS source, expected claims and username or email claim set to match what your proxy sends. Embedding also requires allow_embedding set to true in the [security] section, because Grafana sends headers that block framing by default. Confirm both against the Grafana JWT authentication documentation, and note that allow_embedding is not available in Grafana Cloud, so this pattern applies only to self-hosted instances.
Grafana does not currently support refresh tokens for JWT authentication. The session lifetime is therefore set by the token your proxy issues, not by Grafana. Decide before build how long a user stays signed in inside the embedded view, how the proxy re-issues a token when it expires, and what happens to an open dashboard when the token lapses. Keep token lifetimes short, make the proxy reissue tokens from the host session, and test expiry in a browser that has the host page open for longer than the token lifetime. Each renewal path should be verified in a staging environment that mirrors your production proxy configuration.
Configuration options and when each fits
This table compares four ways to show Grafana panels in another application: iframe embedding, JWT injected by a reverse proxy, externally shared dashboards and URL login. Read each row for the use case, the main risk and what to confirm before you choose it. The main takeaway is that the URL login option carries the most token exposure and should be checked against your logging and TLS setup first.
| Option | Use case | Main risk | What to confirm |
|---|---|---|---|
| allow_embedding in an iframe | Showing a Grafana panel or dashboard inside a portal page that the user already reaches through a supported login | Clickjacking or framing by untrusted sites if the embedding setting is enabled more broadly than needed | Which origins frame the dashboard, and whether your portal enforces its own session before the frame loads |
| JWT with reverse proxy header injection | Embedding for signed-in users where a proxy adds a trusted JWT header so users need no separate Grafana login | A misconfigured proxy that lets clients set or forward the header, granting access as another user | Who signs the JWT, how the proxy strips inbound headers, and how roles map from token claims |
| allow_embedding with JWT (self-hosted only) | Iframe embedding that depends on JWT authentication through the proxy | Not available in Grafana Cloud, so cloud-hosted plans cannot use this path | Whether you run self-hosted Grafana, since this setting is not offered in Grafana Cloud |
| Externally shared dashboards | Giving people with no Grafana account read access to a single dashboard | Data exposure through the shared dashboard's queries, annotations and data sources | Which data sources and features work when shared, and whether annotations contain sensitive detail |
| url_login with auth_token query parameter | Passing a JWT in the URL so a link opens Grafana without a separate login step | Tokens written to access logs and browser history, and session hijacking when TLS is absent | Whether url_login is enabled, that all traffic uses TLS, and that proxy and web server logs redact query strings |
| Refresh tokens for JWT sessions | Keeping long embedded sessions alive without a new login | Not supported for JWT authentication, so sessions end when the token expires | How your portal reissues tokens and how users recover after expiry |
Why URL login with a JWT in the query string is risky
When url_login is enabled, Grafana accepts a JWT in the auth_token query parameter, so the token travels inside the URL itself. The Grafana JWT authentication docs warn that this can expose tokens in logs and enable session hijacking when TLS is not in use. Anything that records request URLs, including web server access logs, reverse proxy logs, load balancer logs, browser history and referrer headers passed to third-party assets, can end up holding a credential that grants a valid Grafana session until the token expires.
Because Grafana does not currently support refresh tokens for JWT authentication, the token your embedding application issues is the only session credential the viewer has. If it leaks through a URL, you cannot revoke it on the Grafana side without also changing the signing key or the token lifetime, so the exposure window is set when you issue the token. Confirm the expiry you configure on the application side and keep it short enough that a leaked token has limited value.
The safer pattern is to keep url_login disabled and let your reverse proxy inject the JWT into the request header that Grafana reads, so the token never appears in a URL. Serve every embedded page and the Grafana origin over TLS, and review proxy and application logs to confirm no query string carries auth_token. Ask your team to test this with a browser developer tools network trace before go-live, since it is the fastest way to confirm no token leaves in a URL.
Setting up JWT-based iframe embedding
This sequence takes a self-hosted Grafana instance from a plain login to dashboard panels that render inside another application for users who are already signed in to that application. Each step ends with a check so the team knows the layer below works before adding the next one.
Confirm a self-hosted edition and scope the host
Confirm in writing that the instance is self-hosted open-source or Enterprise Grafana, not Grafana Cloud, because the allow_embedding setting is not available in Grafana Cloud. Record the exact host domain of the parent application and the Grafana domain that will serve the iframe, since every later setting depends on those two names. Done when the team can show the Grafana version, the edition and both domains in a short written design note that the security owner has approved.
Configure JWT authentication and the expected claims
In the Grafana authentication settings, enable the JWT provider and set the header name the reverse proxy will populate, along with the claim that carries the login, the email and the role mapping. Agree the claim names with the team that issues the application session, and decide which signing key or key set Grafana will use to verify signatures. Check: a token signed with the test key and carrying the agreed claims logs a test user into Grafana, while a token with a wrong signature or a missing claim is rejected.
Enable allow_embedding for the Grafana server
Set allow_embedding to true in the server section of the Grafana configuration and restart the service so the change takes effect. Because this setting allows the page to be framed, limit who can reach the instance and do not enable it on a server that is exposed without the proxy in front. Check: loading a test page that contains an iframe pointing at a Grafana dashboard renders the panel for an authenticated session, with no browser framing error in the console.
Inject the JWT header in the reverse proxy
Configure the reverse proxy so it only adds the JWT header to requests from sessions that the parent application has already authenticated. The proxy should drop any client-supplied value for that header, sign or pass through the token the parent issues, and avoid forwarding the token in a URL. Check: a request with no application session receives no dashboard, and a request with a valid session reaches Grafana with the header set, which the team confirms in the proxy and Grafana logs.
Set cookie and framing policy for the host domain
Set session cookies to secure and SameSite values that still allow the embedded request to work from the parent domain, and restrict the frame-ancestors directive in the Content Security Policy to the parent application's domain only. Follow the Grafana security hardening guidance for these settings and review them with the security owner. Check: the browser shows the panel when the parent page is loaded, and a test page on any other domain is blocked from framing Grafana.
Confirm URL login and refresh behavior are off
Leave url_login disabled so the JWT is never accepted in the auth_token query parameter, which the Grafana docs warn can expose tokens in logs and enable session hijacking without TLS. Note that Grafana does not currently support refresh tokens for JWT authentication, so the parent application must reissue tokens when they expire. Check: a request that puts a JWT in the query string is rejected, and the team has written down how the parent application handles token expiry.
Test with two users and a revoked session
Sign in as two users with different Grafana roles and confirm each sees only the dashboards their role allows inside the parent application. Then end one user's session in the parent application and reload the page, confirming the embedded panel no longer renders. Check: both users see the expected content, and the revoked session returns no dashboard data, with the results recorded in the test log before the integration is released.
Security controls for embedded dashboards
Embedding places Grafana sessions inside other people's pages, so these controls decide who can frame panels, what the browser sends and where credentials can leak. Grafana's security hardening guide and JWT documentation supply most of the settings. Work through them with your portal team before the first embedded panel goes live.
Enforce TLS on every hop
Embedded panels add more network paths between the browser, your portal and Grafana, and each one can carry a session or token. Use TLS between the browser, the reverse proxy and Grafana, and make the proxy refuse plain HTTP for embedded paths. The JWT documentation warns that a token passed in a URL can enable session hijacking without TLS, so every hop must be encrypted before any token is issued. Confirm which certificate authority your portal trusts and test the embedded load from a clean browser profile.
Secure and SameSite cookies
The hardening guide recommends secure and SameSite cookies for Grafana sessions. The Secure attribute keeps the session cookie off plain HTTP connections, and the SameSite attribute controls whether the browser sends the cookie on requests that start from another site, such as your portal framing Grafana. A stricter SameSite value can stop the frame from receiving the session. Test sign-in and panel loads in each browser your users run after changing these values.
Content Security Policy for framing
The hardening guide recommends a Content Security Policy, a response header that tells the browser which sources a page may load scripts, styles, frames and connections from. For embedding, the policy is where you limit which portal origins may frame Grafana and block everything else. Start with a report-only policy on a staging instance, collect violations from the embedded pages, then enforce the policy. Ask your Grafana team which plugin assets and external data source URLs the policy must allow.
Limit origins that may embed
Framing is controlled by the allow_embedding setting, so enabling it is a deliberate decision that affects the whole instance. Pair it with the framing rules in your Content Security Policy so that only your portal domains can display panels. Confirm in the Grafana configuration reference whether the setting limits origins in your version, and test an embed from an origin that is not on your list. Record the allowed origins in the same change record as the proxy configuration.
Keep tokens out of URLs and logs
With url_login enabled, Grafana accepts a JWT in the auth_token query parameter. The JWT documentation warns that this can expose tokens in logs and enable session hijacking without TLS. Keep url_login disabled and have the reverse proxy inject the JWT header instead. Confirm that proxy and Grafana access logs do not record query strings for embedded requests. Grafana does not currently support refresh tokens for JWT authentication, so agree token lifetimes with your identity team before rollout.
Hide version and protect metrics
The hardening guide recommends hiding the Grafana version from unauthenticated users and requiring authentication for the metrics endpoint. Embedded pages and proxy paths can be reached by people who never sign in to Grafana, so an exposed version string or open metrics path tells them about your stack. Check which paths your proxy forwards without authentication, and confirm that your monitoring scrapers present credentials after the change.
Questions teams ask before embedding Grafana
Can our own team embed Grafana dashboards in our application without a partner?
Yes, if you have people who can run a Grafana server, operate a reverse proxy and manage your identity provider. The core steps are enabling allow_embedding, configuring JWT authentication, and having the proxy inject the token that Grafana trusts. Teams without experience in JWT signing, proxy header handling and session behavior usually take longer and make more mistakes in the authentication path, which is the part that carries the most risk. A partner can run that work as a fixed-scope engagement with written deliverables, while your team keeps ownership of the result.
What drives the cost and effort of embedding Grafana in an application?
The cost depends mostly on how many distinct integration points exist and how many of them already work. The main drivers are the number of host applications that need panels, whether your identity provider already issues tokens that can be mapped to Grafana roles, how many dashboards and data sources are involved, and how much testing the authentication path needs. Costs are one-time for design, build and verification, and recurring for upgrades and proxy or identity changes. Ask any quote to separate these items and to state which Grafana version and deployment model it assumes.
What do we need from the host application and identity teams?
Embedding touches three teams, so the work moves faster when each has a named owner before the build starts:
- Host application team: confirms which pages embed panels, the dashboard and panel IDs, and how user sessions are created in the application.
- Identity owners: confirm which claims identify each user, which groups map to Grafana roles, and how token signing keys are stored and rotated.
- Platform or infrastructure team: owns the Grafana server, the reverse proxy, TLS certificates and the database that backs Grafana.
Ask each owner to sign off on the claim mapping and the proxy configuration, because changes made later in one team usually break the others.
How long does setup depend on the proxy and identity work?
Most of the schedule depends on the identity and proxy work rather than on Grafana itself. Enabling embedding and pointing a test page at a dashboard is quick, but the time that matters is spent agreeing on claims, roles, token lifetimes and how the proxy handles sessions that expire while a user is still viewing a page. Grafana does not currently support refresh tokens for JWT authentication, so the design has to decide how a long-lived embedded view gets a fresh token. Ask any proposal to name the identity provider, the proxy and the number of host applications, and to show how those inputs change the schedule.
Is it safe to pass a JWT in the URL for embedded dashboards?
It is not a safe default. When url_login is enabled, Grafana accepts a JWT in the auth_token query parameter. The Grafana documentation warns that this can expose tokens in logs and enable session hijacking if TLS is not in use. Keep url_login disabled unless you have a specific requirement, and have the reverse proxy inject the token as a header instead. Confirm with your security team how proxy and load balancer logs record query strings before you test any URL-based approach. The Grafana JWT authentication documentation describes both options.
Does embedding work on Grafana Cloud?
Not with the same setup. The Grafana JWT documentation states that allow_embedding is not available in Grafana Cloud, and the embedding pattern described here depends on a reverse proxy in front of a self-hosted Grafana server. If you are comparing options, the Grafana pricing page lists a free tier, a Pro tier with a 19 US dollar monthly platform fee plus usage, and an Enterprise tier with a minimum commitment of 25,000 US dollars per year. Those figures are a comparison point only, and you should confirm current terms with Grafana Labs before deciding.
When does an outside partner help with embedded Grafana?
A partner is useful when the authentication design needs to be right the first time and your team has not built it before. Typical reasons include multiple host applications with different session models, a need to separate viewer and editor access inside embedded views, or security reviews that require documented evidence of the token path. DeployOpen plans, implements, hardens and documents self-hosted Grafana inside your own infrastructure, and most engagements are fixed-scope with deliverables agreed in writing before work starts. A quote follows from that written scope.
What should we verify before going live with embedded dashboards?
Test the token path end to end, not only the happy path. Verify that a user without access cannot view a panel through a direct link, that expired sessions are rejected, and that tokens do not appear in proxy, application or Grafana logs. Check that allow_embedding is set only on the instance that needs it, that cookies and TLS settings match your security baseline, and that upgrades keep the embedding configuration intact. Record the results so your security and compliance reviewers can see what was tested and when.
How DeployOpen scopes and delivers embedded Grafana
DeployOpen plans, builds and hands over embedded Grafana panels inside infrastructure you control, starting with a written scope that settles how users sign in, which dashboards appear and where tokens travel. Each engagement is fixed-scope, so the boundaries are agreed before any proxy or Grafana configuration changes.
How we scope
- The written scope names which dashboards and panels appear in each host application and which user groups see them.
- We confirm your Grafana edition and hosting, since allow_embedding and JWT settings are not available in Grafana Cloud.
- The scope records the reverse proxy, identity source and token lifetime you require, with refresh token handling stated as a limit.
How we build
- We configure JWT authentication behind your reverse proxy so the proxy injects the header and Grafana trusts only that path.
- We enable allow_embedding only on the hosts you approve and set cookie and framing rules to match your portal domains.
- We test that URL login with the auth_token parameter stays disabled, and that tokens never appear in access logs or browser history.
How we hand over
- You receive the proxy and Grafana configuration files, with the JWT claims, signing keys and trusted origins documented.
- Provisioned dashboards and folder permissions are described so that changes made in the host application do not alter Grafana data.
- A runbook covers token expiry, key rotation, proxy log review and the steps to disable embedding for a single host.
How we support
- Ongoing support, upgrades and continuous testing are available as a retainer, covering Grafana releases that change embedding behavior.
- We re-test the embedding path after each proxy, identity or Grafana upgrade before the change reaches production.
- Security testing of the host application and its token handling can be scoped separately from the Grafana engagement.

