Skip to content

v1.0.0

Choose a tag to compare

@mxcd mxcd released this 30 Oct 10:45
· 10 commits to main since this release
4dd33be

First release of github.com/govengers/auth. It merges mxcd/go-basicauth (v1.5.x), mxcd/oidc-fwd-auth (v0.9.x) and mxcd/github-fwd-auth (v1.4.x) into one module and adds authorization checks, resource permissions, API keys, a gin and a Prometheus adapter, a Redis session backend and the forward-auth image. There are no compatibility shims; docs/migration.md maps every old symbol and environment variable and gives a recipe per library.

Breaking changes against all three predecessors:

  • New import path github.com/govengers/auth/...; Go 1.26.
  • Sessions are server-side for every provider; the cookie holds a random ID only; the lifetime is StoreOptions.MaximumAge (Store.MaximumAge(), SESSION_MAXIMUM_AGE_SECONDS). Existing sessions are invalid: every user logs in once after the upgrade. The cookie-only mode, gorilla/sessions and the signing keys are gone; one 32-byte EncryptionKey remains (openssl rand -base64 32). An own session.Backend implements five methods, CompareAndSwap included; ErrSessionRevoked is session.ErrRevoked.
  • Session cookie: a Secure, host-only cookie on / is named __Host-<CookieName> (__Host-auth_session, __Host-forwardauth_session); SameSite Default is refused, and Strict is refused by oidc.New and github.New (the callback would arrive without the cookie), so it is for password-only stores. A refresh that keeps failing for longer than GuardOptions.MaximumUnverifiedAge (default 1 h, SESSION_MAXIMUM_UNVERIFIED_AGE_SECONDS) ends the session.
  • One identity type, auth.Identity, replaces basicauth.User, oidc.SessionData, jwt.User and the GitHub session user. One session.Guard replaces the per-provider middleware; there is no global middleware and no PathRules, you mount the Guard on route groups.
  • Route prefixes: /auth/password/*, /auth/oidc/<name>/*, /auth/github/*, each a PathPrefix of plain segments without a trailing /. Redirect URIs are derived from ExternalURL; register the new callback URLs at your IdP and GitHub. ErrorURL and PostLogoutURL become absolute and refuse fragments.
  • One error body {"code","message"} with stable codes (tfa_* became totp_*, unauthorized became unauthenticated); translated Messages are gone.
  • Hooks are auth.Hook (OnLogin) and auth.LogoutHook; UserTransformer is an application middleware after the Guard. Libraries no longer log; they call an optional auth.Observer.
  • password: default minimum length 12 characters without composition rules; Storage takes a context.Context, gains UpdatePasswordHash (compare-and-swap), ConsumeTOTPStep (a totp_step column; every TOTP code is accepted once) and ErrUserExists, matches usernames and emails ignoring case, and SetTOTP returns (bool, error): it enables TOTP only while it is off, atomically (... WHERE id = $1 AND NOT totp_enabled); OnLogin must keep UserID; TOTP.Required enrolls during login and registration; TOTP routes exist only with TOTP.Enabled, and enrolled users cannot log in while it is off; backup codes are checked only with "backupCode": true (no fallthrough from a wrong TOTP code); MaximumAttempts is a lockout across logins until a verified code or ResetTOTPAttempts, with no unlimited mode; new limits Period <= 3600, Skew <= 10, BackupCodeCount <= 20, backup codes <= 128 bytes and >= 1,000,000 distinct codes; Argon2id hashes on outdated parameters are rehashed at login.
  • OIDC and GitHub: PKCE (and nonce) always on, GitHub logout is GET, logout (also password logout) refuses Sec-Fetch-Site: cross-site with 403, so logout links must live on the app's own site, GitHub AllowedTeams is required (an empty list no longer admits everyone), GitHub Scopes must include one that lists teams (read:org, write:org, admin:org, user, repo), the endpoints OIDC discovery names must be https (or loopback http), no component follows a redirect of its token, discovery, JWKS, Keycloak, GitHub revocation or GitHub user and team endpoint (point the URLs at the final location), Keycloak enrichment moved from gocloak to oidc/keycloak and defaults to client credentials, GitHub UserProfile and friends are gone (Identity.Teams, HTTPClient).
  • API keys are named, at least 16 bytes, unique, and grant only the roles and permissions you give them (the old "API key bypasses admin" behaviour needs Roles: []string{auth.RoleAdmin}). Authorization: Bearer is matched in any case, so a foreign bearer token on a route behind apikey is 401.
  • JWT: RS512 only, jwx v3, exp required, default lifetime 5 minutes (was 30), issuer defaults to EXTERNAL_URL, GitHub sub is the numeric user ID and the login is preferred_username (uid is gone), JWKS at /auth/jwks, no generated signing key, Sign refuses an inactive identity, the verifier uses only RSA JWKS keys with an RS*/PS* alg and a kid and answers 401 with WWW-Authenticate: Bearer.
  • Forward-auth: one image ghcr.io/govengers/forwardauth selected by PROVIDER replaces oidc-fwd-auth and github-fwd-auth; renamed environment variables, new routes (/auth/ui, /auth/api, /auth/jwks), an explicit Traefik router for /auth (without the checks and probes) is required, Google multi-provider mode is removed, JWT_PRIVATE_KEY is required when JWT is on, API keys need API_KEYS_ENABLED=true (API_KEYS alone is ignored) and carry permissions (API_KEY_PERMISSIONS) but no roles. EXTERNAL_URL is an origin without a path, a route with a trailing / is 404 (no redirect), SESSION_SAME_SITE takes lax or none, SHUTDOWN_DELAY_SECONDS at most 10, the boot fails when Redis does not answer or when a plain http EXTERNAL_URL off loopback comes without SESSION_INSECURE_COOKIE=true; list X-API-Key next to Authorization in authResponseHeaders.

New: authorization (incl. HasPermission), resource permissions (auth.Permission, ginadapter.RequireMethodPermission, the JWT permissions claim), apikey, ginadapter, prometheusadapter, session/redisbackend, TOTP enrollment during login, Refreshers that re-check teams and users every minute, IdentityHandler, wide-event and Prometheus reporting in the image, ginadapter.RedactQuery (redacts query values on the wide event; mount it or OAuth callback codes reach your logs). Agent docs: llms.txt, docs/wiki/, runnable examples/.

Migration guide: docs/migration.md. Image: ghcr.io/govengers/forwardauth:1.0.0.