Skip to content

fix(auth-guard): lazy provider + enforce secret minimum length at startup#439

Merged
cssbruno merged 3 commits into
mainfrom
codex/fix-auth-guard-lazy-provider
Jun 15, 2026
Merged

fix(auth-guard): lazy provider + enforce secret minimum length at startup#439
cssbruno merged 3 commits into
mainfrom
codex/fix-auth-guard-lazy-provider

Conversation

@cssbruno

@cssbruno cssbruno commented Jun 15, 2026

Copy link
Copy Markdown
Owner

Summary

Fixes the init-time crash in examples/auth-guard and the follow-up regression it exposed: a misconfigured session secret should fail at startup with a clean error, never an init-time panic and never a deferred first-request failure.

Commit 1 — defer session setup out of the init hook

The generated app registers the auth provider from its init() hook, before env-contract validation runs. The hook called authguard.MustAuthProvider(), which built Sessions eagerly and panicked when GOWDK_AUTH_SESSION_SECRET was unset/short — crashing with a stack trace instead of the clean startup error.

  • Replace MustAuthProvider() with a lazy AuthProvider() returning a gowdkauth.ProviderFunc that resolves Sessions() inside Principal on first use.
  • Point the generated hook at authguard.AuthProvider().

Commit 2 — enforce SecretEnv minimum length (build + startup)

Deferring construction meant a present-but-too-short secret no longer failed at init, and the env contract only rejected empty secrets — so a weak key let the binary start and only failed the first guarded request (flagged in review).

  • Add SecretEnv.MinBytes; enforce it in build-time validation (gowdk.EnvConfig.Validate) and the generated runtime contract (internal/appgen validateEnvContract).
  • Parse MinBytes from both executable and AST configs (internal/project); register the new short_secret diagnostic.
  • Set MinBytes: 32 on the auth-guard example's session and CSRF secrets.

Verification

  • go test ./... — all packages pass; new tests in internal/publicapi (build-time Validate) and internal/appgen (generated contract).
  • make build + run the built binary:
    • secret unsetGOWDK_AUTH_SESSION_SECRET is required but is not set, exits.
    • secret set but 8 bytesGOWDK_AUTH_SESSION_SECRET must be at least 32 bytes, exits (1).
    • no init-time panic in either case.

The generated app registers the auth provider from its init() hook, before
the env-contract validation runs. The hook called authguard.MustAuthProvider(),
which constructed Sessions eagerly and panicked when GOWDK_AUTH_SESSION_SECRET
was unset or shorter than the required 32 bytes — so a secret misconfiguration
crashed the binary with a stack trace at startup instead of returning the
generated env-contract error.

Replace MustAuthProvider with a lazy AuthProvider that resolves Sessions inside
Principal on the first request, and point the generated hook at it. A missing
or short secret now surfaces as the clean "GOWDK_AUTH_SESSION_SECRET is required"
startup error (verified by running the built binary with the secret unset).
@cssbruno cssbruno added examples Examples and sample applications auth Authentication and session addon work labels Jun 15, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 78a279179c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

// the clean startup error. Deferring construction to Principal keeps secret
// misconfiguration on the normal validation path.
func AuthProvider() gowdkauth.Provider {
return gowdkauth.ProviderFunc(func(request *http.Request) (*gowdkauth.Principal, error) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Validate short session secrets before serving

When GOWDK_AUTH_SESSION_SECRET is set but shorter than the 32-byte minimum, this lazy provider means Sessions() is no longer constructed during generated-app initialization. I checked the generated env contract in internal/appgen/source_env.go, and it only rejects empty required secrets, so a non-empty short secret now lets the binary start and only fails the first login/guarded request with a session error instead of the documented startup failure; keep a post-env startup validation for Sessions() or teach the env contract about the minimum length before deferring construction.

Useful? React with 👍 / 👎.

Follow-up to the lazy auth provider: deferring Sessions() construction meant a
present-but-too-short GOWDK_AUTH_SESSION_SECRET no longer failed at init, and
the env contract only checked for empty secrets — so a weak signing key let the
binary start and only failed the first guarded request.

Add SecretEnv.MinBytes and enforce it in both the build-time env validation
(gowdk.EnvConfig.Validate) and the generated runtime contract
(internal/appgen validateEnvContract), parse it from executable and AST configs
(internal/project), register the new short_secret diagnostic, and set
MinBytes: 32 on the auth-guard example's session and CSRF secrets.

A short secret now fails fast with "GOWDK_AUTH_SESSION_SECRET must be at least
32 bytes" at startup (verified by running the built binary). Tests added for
both the build-time validation and the generated contract.
@cssbruno cssbruno changed the title fix(examples): defer auth-guard session setup out of the init hook fix(auth-guard): lazy provider + enforce secret minimum length at startup Jun 15, 2026
Comment thread internal/project/config.go Fixed
CodeQL flagged the unchecked int64->int conversion when parsing
SecretEnv.MinBytes from the AST config path. Route it through a new
parseInt helper that clamps out-of-range values to the platform int
range so a malformed config value cannot wrap into a small or negative
length on 32-bit platforms. Add a LoadConfigFile regression test that
enforces MinBytes end-to-end through the AST path.
@cssbruno cssbruno merged commit 943828f into main Jun 15, 2026
5 checks passed
@cssbruno cssbruno deleted the codex/fix-auth-guard-lazy-provider branch June 15, 2026 13:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

auth Authentication and session addon work examples Examples and sample applications

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants