The flagship 5-line-integration example. It shows how securityhttp.NewHandler assembles the entire security middleware chain — secure headers, session-backed authentication, CSRF, default-deny authorization, and a JSON login endpoint — around a plain application handler, with secure defaults and fail-loud validation.

The five lines

CSRF is on by default (synchronizer token, session-backed), security headers are on, the session cookie is Secure+HttpOnly+SameSite=Lax, and authorization is default-deny (AnyRequest().Authenticated()) — none of which the integrator has to remember to enable.

Full source

The example listens on :8443 (see http.ListenAndServe(":8443", handler)), served over plain HTTP for local testing — no TLS certificate is configured in this example. Because the session cookie defaults to Secure, a browser will not send it back over plain HTTP; use curl, which doesn’t enforce that, or configure TLS termination for a real deployment.

Trying it out

Verified by running the example: that second command returns 403, not a successful login. WithAuthorize() here is AnyRequest().Authenticated() with no PermitAll carve-out for /login, and CSRF defaults to the session-backed synchronizer token — but nothing in this exact five-line configuration ever creates a session or issues a token before login, because every anonymous request (including GET / and GET /login) is already denied by the authz leg. There is no bare-curl path through this literal configuration that reaches the login handler.To see the chain’s pieces work end-to-end against real HTTP requests, use examples/playground or examples/webapp instead — both add an explicit PermitAll (or an unguarded mux) for the login path, and playground pairs it with a double-submit CSRF repository that doesn’t need a pre-existing session. To exercise this exact configuration, either add authz.Match("/login").PermitAll() to authz.Routes(...), or see securityhttp_test.go’s TestIntegration_CookieSecureDefaults, which drives the login handler directly with securityhttp.CSRFDisabled() and securityhttp.AllowLoginWithoutCSRF().
Once a session exists (e.g. by adjusting the authorize rules as above, or in a test that seeds one directly), the rest of the chain behaves as documented:

What you get for free

  • X-Content-Type-Options: nosniff, X-Frame-Options: DENY, and the other security-header defaults on every response
  • Session cookie with Secure; HttpOnly; SameSite=Lax
  • CSRF synchronizer token (session-backed) protecting every unsafe request
  • Default-deny authorization: AnyRequest().Authenticated() means an unmatched path requires a session, not open access
  • Session fixation protection: the session ID rotates on login
  • Fail-loud assembly: New() or NewHandler() — a misconfigured chain (e.g. no terminal authorization rule) errors at startup, not at request time