Documentation
¶
Overview ¶
Package auth is the mAPI-ng dashboard authentication layer: OIDC login (GitHub/Google, no passwords — CONTEXT Member / roles), HMAC-signed session cookies, and a middleware that gates the dashboard to the caller's org.
It is only wired in when a control plane is present (main.go). Three modes are selected at startup:
- No control plane: auth is OFF (constant dev tenant, Part 1 behavior).
- Control plane, no OIDC creds: dev-login only — a button that starts a session as the seeded dev-org admin, for session-gated local testing.
- Control plane + OIDC creds: real GitHub/Google login; dev-login disabled.
The session is a self-contained HMAC-signed cookie (no server-side store): base64(payload) + "." + base64(hmac-sha256(payload)). The org id in the verified session is what web.Config.Tenant reads, so a member only ever sees their own org's data. Secrets and access tokens are never logged.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func TenantFromContext ¶
TenantFromContext returns the authenticated org id for a request, satisfying web's TenantResolver signature shape via the request context. main wires this into web.Config.Tenant, so the dashboard renders only the caller's org.
Types ¶
type Auth ¶
type Auth struct {
// contains filtered or unexported fields
}
Auth is the mAPI-ng dashboard auth layer. It mounts open login routes, verifies session cookies in its Middleware, and exposes TenantFromContext for the web layer's tenant resolver.
func New ¶
New builds the auth layer. Dev-login is enabled ONLY when no real provider is configured, so a production deployment with GitHub/Google never exposes the bypass. Returns an error for a too-short session key.
func (*Auth) Authenticated ¶
Authenticated reports whether the request carries a valid session cookie, without requiring the Middleware to have run. The composition root uses it at "/" to serve the public home to anonymous visitors while routing signed-in users to the dashboard.
func (*Auth) Enabled ¶
Enabled reports the active auth configuration: the enabled provider names and whether dev-login is on. main logs it at startup so the active mode is clear.
func (*Auth) Middleware ¶
Middleware verifies the session cookie and, on success, stores the identity in the request context before calling next. On failure it redirects a browser request to /login, or returns 401 JSON for an /api/ path (so htmx/fetch callers get a machine-readable status instead of an HTML redirect body).
func (*Auth) Register ¶
Register mounts the OPEN auth routes on mux. None of these sit behind the session gate (a logged-out user must reach the login flow). main mounts the session-gated dashboard separately at "/".
func (*Auth) SetSession ¶
func (a *Auth) SetSession(w http.ResponseWriter, orgID, memberID, role string)
SetSession signs and writes the dashboard session cookie for a resolved member, implementing PostAuthContext so a composed LoginInterceptor can start a session through the same path the core first-login uses.
type Config ¶
type Config struct {
// Store is the control-plane member store (required).
Store MemberStore
// SessionKey signs session cookies (>= 32 bytes required).
SessionKey []byte
// Providers holds the per-provider OAuth credentials + base URL.
Providers ProviderConfig
// DevOrgName is the seeded dev org used by dev-login (when enabled).
DevOrgName string
// Secure sets the Secure cookie flag; main sets it true when the base URL
// is https.
Secure bool
// HTTPClient performs the token exchange and userinfo calls. main supplies
// one with an explicit timeout.
HTTPClient *http.Client
// Logger is the structured logger (defaults to slog.Default()).
Logger *slog.Logger
// Interceptor is the composed post-auth hook the callback consults after the
// identity is verified (nil = plain login).
Interceptor LoginInterceptor
}
Config bundles the auth layer's dependencies and startup options. main builds it from the environment.
type LoginInterceptor ¶
type LoginInterceptor interface {
Handle(pa PostAuthContext, w http.ResponseWriter, r *http.Request, oidcSubject, email string) (handled bool)
}
LoginInterceptor is an optional post-authentication hook the OIDC callback consults after the identity is verified, before the default first-login flow. Handle returns true when it fully handled the response (the callback then returns); false falls through to UpsertMemberFromOIDC. pa lets it start a session. A nil interceptor means plain login only.
type MemberStore ¶
type MemberStore interface {
// UpsertMemberFromOIDC resolves (creating on first login) the member behind
// an OIDC identity, returning its org id, member id, role, and whether this
// call created the member (first login) — which triggers the key interstitial.
UpsertMemberFromOIDC(ctx context.Context, oidcSubject, email string) (orgID, memberID, role string, isNew bool, err error)
// DevOrgAdmin returns the seeded dev org's admin member, for dev-login.
DevOrgAdmin(ctx context.Context, devOrgName string) (orgID, memberID string, err error)
// IssueKey mints an ingest key for an org and returns its plaintext secret
// once (only the hash is stored). Used to auto-issue the first key at signup.
IssueKey(ctx context.Context, orgID, label string) (secret string, err error)
}
MemberStore is the control-plane surface the auth layer needs. control.Store satisfies it. Keeping it an interface here means auth never imports control (auth sits above the control plane in the wiring only through main) and the handlers are unit-testable against a fake.
type PostAuthContext ¶
type PostAuthContext interface {
// SetSession signs and writes the dashboard session cookie for a resolved
// member, exactly as the core first-login path does.
SetSession(w http.ResponseWriter, orgID, memberID, role string)
}
PostAuthContext is the capability surface a LoginInterceptor uses to complete a post-authentication flow — today, starting a dashboard session for a member it resolved out of band (e.g. by accepting an invite). It keeps the session signer private to auth while letting a composed feature finish the login.
type ProviderConfig ¶
type ProviderConfig struct {
GitHubClientID string
GitHubClientSecret string
GoogleClientID string
GoogleClientSecret string
BaseURL string
}
ProviderConfig is the raw per-provider credential input read from the environment by main and passed to newAuth.