Skip to content

feat: add browser-based SSO authentication#646

Open
solganik wants to merge 7 commits intografana:mainfrom
solganik:feature/browser-auth
Open

feat: add browser-based SSO authentication#646
solganik wants to merge 7 commits intografana:mainfrom
solganik:feature/browser-auth

Conversation

@solganik
Copy link
Copy Markdown

@solganik solganik commented Mar 11, 2026

Add chromedp-based browser login flow that opens a real browser window for SSO authentication, captures the grafana_session cookie, and persists it to disk. Includes automatic re-authentication on 401 responses via a custom http.RoundTripper middleware.

New files:

  • auth/browser.go: chromedp browser login with persistent Chrome profile
  • auth/session_store.go: cookie persistence to ~/.config/mcp-grafana/
  • auth/transport.go: SessionAuthTransport with auto 401 re-login

Modified:

  • cmd/mcp-grafana/main.go: --browser-auth CLI flag
  • mcpgrafana.go: wire browser auth transport into Grafana client

Note

High Risk
Introduces cookie-based authentication with automated browser login and persistence, and injects it into all Grafana HTTP traffic; mistakes here could leak sessions or break auth across requests. Also adds chromedp-based local rendering and expands query/deeplink generation logic, increasing dependency and behavioral surface area.

Overview
Adds browser-based SSO authentication as an alternative to API tokens: a new auth package drives a chromedp login flow, captures the grafana_session cookie, persists it to ~/.config/mcp-grafana/sessions.json, and injects/refreshes it via a SessionAuthTransport that auto re-logins on 401 (enabled via --browser-auth or GRAFANA_AUTH_BROWSER).

Expands tooling around dashboards and navigation: get_dashboard_panel_queries now supports panelId filtering, row-nested panels, multi-datasource query extraction, and optional template variable substitution with processedQuery/requiredVariables; generate_deeplink now builds full Explore left state (including queries and embedded time range) and can auto-resolve dashboard datasource template variables from a provided datasourceUid.

Adds render_panel_image_local, a new headless-Chrome screenshot renderer that uses the stored SSO session (no Grafana Image Renderer plugin), and wires it into rendering tools. Updates transports to ensure OrgID is consistently applied and adds/updates unit/integration tests, plus new chromedp dependencies and changelog entry for 0.11.3.

Written by Cursor Bugbot for commit 0db86dc. This will update automatically on new commits. Configure here.

@solganik solganik requested a review from a team as a code owner March 11, 2026 19:45
@cla-assistant
Copy link
Copy Markdown

cla-assistant bot commented Mar 11, 2026

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
1 out of 3 committers have signed the CLA.

✅ sd2k
❌ ataran-dev
❌ solganik
You have signed the CLA already but the status is still pending? Let us recheck it.

@solganik solganik force-pushed the feature/browser-auth branch 3 times, most recently from e47d093 to aa4832b Compare March 12, 2026 06:04
Add chromedp-based browser login flow that opens a real browser window
for SSO authentication, captures the grafana_session cookie, and
persists it to disk. Includes automatic re-authentication on 401
responses via a custom http.RoundTripper middleware.

New files:
- auth/browser.go: chromedp browser login with persistent Chrome profile
- auth/session_store.go: cookie persistence to ~/.config/mcp-grafana/
- auth/transport.go: SessionAuthTransport with auto 401 re-login

Modified:
- cmd/mcp-grafana/main.go: --browser-auth CLI flag
- mcpgrafana.go: wire browser auth transport into Grafana client
@solganik solganik force-pushed the feature/browser-auth branch from aa4832b to 5983064 Compare March 12, 2026 06:06
solganik and others added 6 commits March 17, 2026 10:52
…oard/panel deeplinks

When generating dashboard or panel deeplinks, callers previously had to
know the exact internal value for var-datasource, which differs from both
the datasource display name and UID. Now, passing datasourceUid for
dashboard/panel types auto-fetches the dashboard JSON, finds the
datasource-type template variable, looks up the datasource by UID, and
injects the correct var-<name>=<value> into the URL.

Also documents that TimeRange must use relative or epoch ms format (not
ISO timestamps, which Grafana silently ignores).
…riable substitution (grafana#539)

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…#649)

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
New tool `render_panel_image_local` renders Grafana dashboard panels
as PNG screenshots using local headless Chromium (chromedp). Does not
require the Grafana Image Renderer plugin to be installed server-side.

Uses browser SSO session cookie for authentication, monitors network
activity via CDP to detect panel readiness (waits for all HTTP requests
to complete + quiet period), and disables auto-refresh to prevent
infinite network activity during rendering.

Supports datasourceUid for auto-resolving the datasource template
variable, matching the generate_deeplink improvement.
…ore deeplinks

Add extraJSON field to ExploreQuery that allows passing arbitrary
datasource-specific properties (query, metrics, bucketAggs, timeField)
directly into the query object. This enables generating working Explore
deeplinks for Elasticsearch-based datasources like Coralogix, which use
a different query structure than PromQL/LogQL datasources.
Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix is ON, but it could not run because the branch was deleted or merged before autofix could start.

})

return result
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicate variable substitution logic across two functions

Low Severity

The new substituteVariables in dashboard_helpers.go and the existing substituteTemplateVariables in run_panel_query.go both replace the same three Grafana template variable patterns (${varname}, $varname, [[varname]]) with different implementations. The new version additionally handles ${varname:option} but otherwise serves the same purpose. This duplication increases maintenance burden and risks inconsistent behavior.

Additional Locations (1)
Fix in Cursor Fix in Web

@sd2k sd2k added the cla: no Contributor License Agreement is not signed label Mar 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cla: no Contributor License Agreement is not signed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants