webauth

package
v0.11.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 12, 2026 License: MIT Imports: 10 Imported by: 0

Documentation

Overview

Package webauth holds the browser sign-in capture core shared by openobserve-cli and the o3 desktop app: cookie shaping, the login-success heuristic, the injected capture script, and the policy deciding when a captured state counts as a completed login.

It is pure and dependency-light — it imports only the standard library and pkg/auth — so both a CLI driving a browser over the DevTools Protocol and a desktop app driving a native WebView can share it. Transport-specific code lives with its client (see pkg/webauth/cdp for the CLI's).

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AssembleSession

func AssembleSession(cookies []Cookie, host, authorization, email string) pkgauth.Session

AssembleSession builds the storable/replayable session from captured cookies. Only cookies scoped to host are kept; the Cookie header is serialized stably, and the soonest cookie expiry (if any) drives the connection UI. Authorization and email ride along as the header fallback and display metadata.

func EarliestExpiry

func EarliestExpiry(cs []Cookie) time.Time

EarliestExpiry returns the soonest non-zero expiry among cookies (drives the "expires in N days" UI). Zero when every cookie is a session cookie.

func HostMatches

func HostMatches(cookieDomain, host string) bool

HostMatches reports whether a cookie's Domain applies to host. An empty domain is a host-only cookie and matches (the caller already scoped it). A leading dot is ignored; host equal to, or a subdomain of, the domain matches.

func LoginSucceeded

func LoginSucceeded(currentURL, host string, cookies []Cookie) bool

LoginSucceeded is the capture heuristic, kept pure so it can be unit-tested in isolation. Login is considered complete when either:

  • a known post-login OpenObserve auth cookie for the host is present, or
  • the WebView has navigated off the login page AND at least one host cookie exists (OpenObserve lands on /web/ or /web/logs after login).

func ProbeJS

func ProbeJS(deliver, host string) string

ProbeJS returns the capture script injected into the sign-in page. The script calls the global function named deliver with an object carrying an {authorization} or {email} key as it observes them.

host scopes the script to the OpenObserve instance. This is a security boundary, not a nicety: the injection mechanisms both callers use (the CDP Page.addScriptToEvaluateOnNewDocument, and o3's WKUserScript) evaluate the script in EVERY document, including a full-page or iframed identity provider on a completely different origin. An IdP that sends its own Authorization header over XHR or fetch would otherwise have that header captured, written to the user's keychain, and replayed on every request to the OpenObserve instance — a third party's bearer token handed to a different server. So the script does nothing at all unless location.hostname is host, or a subdomain of it (the same relation HostMatches applies to cookie domains). Any port in host is stripped first, since location.hostname carries none. An empty host disables capture entirely rather than capturing everywhere.

It hooks BOTH window.fetch and XMLHttpRequest.prototype.setRequestHeader. Both are required: OpenObserve's web app issues its API requests through axios, which uses XHR, so a fetch-only hook captures nothing on a real instance and leaves only the short-lived session cookie. The Authorization header the SPA sends is the durable credential — typically Basic base64(email:token) — and it outlives the session cookie, so it is the more valuable of the two captures.

The script is defensive to the point of paranoia — every step is wrapped in try/catch and the original function is always called — because it runs inside a page we do not control and must never break the user's ability to log in.

func Replayable

func Replayable(s pkgauth.Session) bool

Replayable reports whether a captured state carries anything o3 could replay, and so is worth handing to the verifier.

Cookies are the usual authenticator, but they are NOT universal: an instance using native (email + password) login authenticates its own SPA with an Authorization header the browser builds locally and sets no cookies at all. Gating capture on cookies alone therefore never verified such a login — the window stayed open on the instance's home page after the user had signed in.

func SerializeCookies

func SerializeCookies(cs []Cookie) string

SerializeCookies renders cookies into a Cookie header value ("k1=v1; k2=v2"), sorted by name (then value) for a stable, testable result.

Types

type Cookie struct {
	Name     string
	Value    string
	Domain   string
	Path     string
	Expires  time.Time // zero for session cookies
	Secure   bool
	HTTPOnly bool
}

Cookie is a single captured cookie, mirroring the fields the native WKHTTPCookieStore hands back.

func FilterForHost

func FilterForHost(cs []Cookie, host string) []Cookie

FilterForHost keeps only cookies whose domain applies to host.

type Driver

type Driver interface {
	Capture(loginURL, host string, verify VerifyFunc) (pkgauth.Session, error)
}

Driver opens a browser at loginURL and captures the session established there. host scopes which cookies are kept. Implementations block until login is verified, the user gives up, or a timeout elapses.

Two implementations exist: pkg/webauth/cdp drives a Chromium-family browser over the DevTools Protocol (used by the CLI, and by o3 off macOS), and o3's own darwin shell drives a native WKWebView.

type Tracker

type Tracker struct {
	// contains filtered or unexported fields
}

Tracker decides when an observed browser state counts as a completed login. It is shared by every transport so the CLI and o3 cannot drift on the question of when sign-in has actually finished.

The policy, in order:

  • Assemble the observed state into a session and drop it unless something is replayable. An instance using native login sets no cookies at all, so "has cookies" is not the test — "has cookies OR an Authorization header" is.
  • An authenticated API probe is the SOLE success signal. A benign cookie set on the login page, or an in-progress redirect to an external identity provider, must never be mistaken for a completed login, and only a real authenticated request can tell the difference.
  • Verify each distinct state at most once. Without this a static page is re-probed on every tick, sending an authenticated request per second.

A nil verifier disables the probe and falls back to the pure cookie/URL heuristic in LoginSucceeded. That path exists for unit tests and for any caller with no API client to hand; production callers always pass a verifier.

func NewTracker

func NewTracker(host string, verify VerifyFunc) *Tracker

NewTracker returns a Tracker scoping cookies to host and confirming captures with verify. A nil verify selects the heuristic fallback.

func (*Tracker) Observe

func (t *Tracker) Observe(cookies []Cookie, currentURL, authz, email string) (pkgauth.Session, bool)

Observe feeds one sampled browser state to the policy. It returns the captured session and true exactly when sign-in is complete.

Observe blocks for the duration of the verification request, so callers should not hold a UI lock across it.

type VerifyFunc

type VerifyFunc func(pkgauth.Session) bool

VerifyFunc confirms that a captured session actually authenticates against the instance's API. When a verifier is supplied, Capture reports success only once it returns true, so a login that merely set a benign preference/language cookie — or an in-progress SSO redirect that briefly leaves the login path — is never mistaken for a completed sign-in. A nil verifier disables the probe and falls back to the pure cookie/URL heuristic (used off-darwin and in unit tests).

func PingVerifier

func PingVerifier(baseURL, org string, timeout time.Duration, maxRetries int) VerifyFunc

PingVerifier returns a VerifyFunc that confirms a session by making a real authenticated request to the instance. This is the sole success signal for capture: only an authenticated response proves the captured state works.

It takes plain values rather than a config.Defaults so this package stays free of pkg/config (and so of yaml.v3). Callers pass d.Timeout, d.MaxRetries.

Directories

Path Synopsis
Package cdp captures an OpenObserve browser session by driving a Chromium-family browser over the Chrome DevTools Protocol.
Package cdp captures an OpenObserve browser session by driving a Chromium-family browser over the Chrome DevTools Protocol.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL