Repository navigation
v1.0.0
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/sessionsand the signing keys are gone; one 32-byteEncryptionKeyremains (openssl rand -base64 32). An ownsession.Backendimplements five methods,CompareAndSwapincluded;ErrSessionRevokedissession.ErrRevoked. - Session cookie: a Secure, host-only cookie on
/is named__Host-<CookieName>(__Host-auth_session,__Host-forwardauth_session);SameSiteDefault is refused, andStrictis refused byoidc.Newandgithub.New(the callback would arrive without the cookie), so it is for password-only stores. A refresh that keeps failing for longer thanGuardOptions.MaximumUnverifiedAge(default 1 h,SESSION_MAXIMUM_UNVERIFIED_AGE_SECONDS) ends the session. - One identity type,
auth.Identity, replacesbasicauth.User,oidc.SessionData,jwt.Userand the GitHub session user. Onesession.Guardreplaces the per-provider middleware; there is no global middleware and noPathRules, you mount the Guard on route groups. - Route prefixes:
/auth/password/*,/auth/oidc/<name>/*,/auth/github/*, each aPathPrefixof plain segments without a trailing/. Redirect URIs are derived fromExternalURL; register the new callback URLs at your IdP and GitHub.ErrorURLandPostLogoutURLbecome absolute and refuse fragments. - One error body
{"code","message"}with stable codes (tfa_*becametotp_*,unauthorizedbecameunauthenticated); translatedMessagesare gone. - Hooks are
auth.Hook(OnLogin) andauth.LogoutHook;UserTransformeris an application middleware after the Guard. Libraries no longer log; they call an optionalauth.Observer. password: default minimum length 12 characters without composition rules;Storagetakes acontext.Context, gainsUpdatePasswordHash(compare-and-swap),ConsumeTOTPStep(atotp_stepcolumn; every TOTP code is accepted once) andErrUserExists, matches usernames and emails ignoring case, andSetTOTPreturns(bool, error): it enables TOTP only while it is off, atomically (... WHERE id = $1 AND NOT totp_enabled);OnLoginmust keepUserID;TOTP.Requiredenrolls during login and registration; TOTP routes exist only withTOTP.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);MaximumAttemptsis a lockout across logins until a verified code orResetTOTPAttempts, with no unlimited mode; new limitsPeriod<= 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) refusesSec-Fetch-Site: cross-sitewith 403, so logout links must live on the app's own site, GitHubAllowedTeamsis required (an empty list no longer admits everyone), GitHubScopesmust include one that lists teams (read:org,write:org,admin:org,user,repo), the endpoints OIDC discovery names must behttps(or loopbackhttp), 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 tooidc/keycloakand defaults to client credentials, GitHubUserProfileand 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: Beareris matched in any case, so a foreign bearer token on a route behindapikeyis 401. - JWT: RS512 only, jwx v3,
exprequired, default lifetime 5 minutes (was 30), issuer defaults toEXTERNAL_URL, GitHubsubis the numeric user ID and the login ispreferred_username(uidis gone), JWKS at/auth/jwks, no generated signing key,Signrefuses an inactive identity, the verifier uses only RSA JWKS keys with an RS*/PS*algand akidand answers 401 withWWW-Authenticate: Bearer. - Forward-auth: one image
ghcr.io/govengers/forwardauthselected byPROVIDERreplacesoidc-fwd-authandgithub-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_KEYis required when JWT is on, API keys needAPI_KEYS_ENABLED=true(API_KEYSalone is ignored) and carry permissions (API_KEY_PERMISSIONS) but no roles.EXTERNAL_URLis an origin without a path, a route with a trailing/is 404 (no redirect),SESSION_SAME_SITEtakeslaxornone,SHUTDOWN_DELAY_SECONDSat most 10, the boot fails when Redis does not answer or when a plainhttpEXTERNAL_URLoff loopback comes withoutSESSION_INSECURE_COOKIE=true; listX-API-Keynext toAuthorizationinauthResponseHeaders.
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.