Protect application routes
A complete browser security wrapper for your own HTTP endpoints.
Protect application routes
Use Auth.Protect(pattern, handler) for authenticated application endpoints.
It composes the configured rate limiter, mandatory signed double-submit and
Origin/Referer checks, session authentication (including transparent refresh),
and current email-verification policy. It also supplies CORS headers.
mux := http.NewServeMux()
auth.Mount(mux)
pattern := "POST /widgets/{id}/publish"
mux.Handle(pattern, auth.Protect(pattern, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
user := middleware.GetUserFromContext(r.Context())
widgetID := r.PathValue("id")
// Check ownership in your application before writing this user's widget.
_ = user
_ = widgetID
w.WriteHeader(http.StatusNoContent)
})))
// Preflight must run before the mux selects a method-specific route.
server := &http.Server{Addr: ":8080", Handler: auth.CORS(mux)}Import github.com/nazimdjebloun/go-auth/middleware for context access.
Protect establishes identity; it cannot infer ownership of application data.
The WithRateLimitRoute key uses the same pattern if a custom rate is needed.
Without an override, the configured fallback rate applies. Explicitly disabled
rate limits and configured exemptions are respected.
Authorization runs after authentication
pattern := "POST /reports/{id}/publish"
mux.Handle(pattern, auth.Protect(pattern,
auth.RequireAppPermission("reports.publish")(publishReport)))
pattern = "GET /private-admin"
mux.Handle(pattern, auth.Protect(pattern, auth.RequireAdmin(adminPage)))
pattern = "POST /orgs/{orgID}/widgets"
mux.Handle(pattern, auth.ProtectOrgScope(pattern, "org.widgets.create",
func(w http.ResponseWriter, r *http.Request, scope goauth.OrgScope) {
// Pass scope into the repository; every query must include scope.OrgID.
w.WriteHeader(http.StatusNoContent)
}))Permission and organization features must be enabled and provisioned as
documented in their guides. The wrappers retain their existing live checks;
Protect does not grant a role or permission. Include the authenticated user
and organization in application queries rather than trusting IDs in JSON.
ProtectActiveOrgScope(pattern, key, handler) instead selects the authenticated
session's active organization. Both helpers check live membership, permission
role and grants, and supply the fixed owner/admin/member classification as
scope.Role. A custom permission role is represented by the member classification;
it does not become an owner or admin. Incomplete scope fails with 500 before the
application handler runs.
For applications intentionally using fixed roles, compose
auth.Protect(pattern, auth.RequireOrgScope(domain.OrgRoleMember, handler))
or RequireActiveOrgScope. Repeated authentication from the same Auth instance
reuses the successful result while credentials, selected session context and
identity remain unchanged. Separate requests and separate instances authenticate
independently; public context setters do not bypass authentication.
Route helper reference
Protect is the complete browser route wrapper. RequireAuth is one layer:
it validates the selected session, refreshes expired access credentials when
possible, loads user/session context and enforces email verification. It adds
no CORS, CSRF, origin or rate-limit protection and grants no application or org
permission. Prefer Protect or its scoped variants for browser endpoints.
Helper on *Auth | What it does |
|---|---|
Protect(pattern, handler) | Complete browser chain plus route matching, Pattern and path parameters. Add resource authorization inside it. |
ProtectOrgScope(pattern, key, handler) | Complete chain plus a live org permission check for {orgID}; passes OrgScope. |
ProtectActiveOrgScope(pattern, key, handler) | Complete chain plus a live permission check for the session's active org; passes OrgScope. |
RequireAuth(handler) | Session authentication, transparent refresh, identity context and email verification. |
RequireAdmin(handler) | Current app-admin authorization and required second-factor assurance; run after authentication. |
RequireAppPermission(key)(handler) | Live application permission check; run after authentication. |
RequireOrgPermission(key)(handler) | Live org permission check using {orgID}, then authorized org context; stores org ID and membership role. Run after authentication. |
RequireActiveOrgPermission(key)(handler) | Live org permission check using the session's active org ID; stores the live ID/role. Run after authentication. |
RequireOrg(role)(handler) | Membership plus minimum fixed role; reads {orgID}, falling back to org_id query. Run after authentication. |
RequireActiveOrg(role)(handler) | Active-session org and minimum fixed role; run after authentication. |
RequireOrgScope(role, handler) | Authentication plus fixed-role org checks; passes OrgScope. Add Protect for browser protections. |
RequireActiveOrgScope(role, handler) | Same fixed-role scope adapter for the session's active org. |
RequireOrgPermissionScope(key, handler) | Authentication plus live org permission checks; passes OrgScope. Prefer ProtectOrgScope for browser routes. |
RequireActiveOrgPermissionScope(key, handler) | Same permission scope adapter for the active org. Prefer ProtectActiveOrgScope for browser routes. |
RequireCSRF(handler) | Signed double-submit CSRF and Origin/Referer checks. |
CORS(handler) | Configured origin/credential headers and preflight handling; place outside a method-based router for application preflights. |
RateLimit(handler) | Configured limiter using the router's route pattern. |
RateLimitWithPattern(pattern)(handler) | Configured limiter with an explicit, validated pattern for custom routers. |
Mount(mux) | Registers enabled built-in auth routes and their middleware. |
Handler(pattern) | Looks up an enabled built-in wrapped handler; custom routers must populate its path parameters. |
SetSessionCookies(w, r, sessionID, sessionToken, refreshToken) | Issues credentials and session-bound CSRF protection after trusted session creation. |
ClearSessionCookies(w, r) | Clears browser credentials and issues anonymous CSRF protection; revoke the session first. |
RotateCSRFToken(w, r) | Replaces request CSRF protection; credential cookie helpers already rotate it. |
middleware.GetUserFromContext, GetSessionFromContext, GetOrgID and
GetOrgRole read values established by preceding middleware. Missing values
return nil or the zero value; getters do not authorize or validate scope. For
tenant-owned data, accept OrgScope and pass it explicitly to repositories.
Client flow and failures
First call GET /auth/csrf-token with credentials, then send its token as
X-CSRF-Token on mutations, with credentials. Honor replacement tokens in the
same response header. Keep X-GoAuth-Session: admin on every request from an
independent admin client; the ordinary application uses the app context.
| Situation | Result |
|---|---|
| Missing, expired, or revoked credentials | 401; display sign-in. |
| Valid session whose email now requires verification | 403 email_not_verified; display verification, then retry using that session. |
| Missing/invalid double-submit token or denied Origin/Referer | 403 CSRF error; the business handler does not run. |
| Valid identity without the requested authorization | The inner authorization wrapper's error, usually 403. |
| Rate budget exhausted | 429 with Retry-After. |
| Request outside the declared route | 404 before rate accounting. |
Verification, sign-in and logout retain their built-in route policies. Do not
wrap Auth.Mount routes in Protect: authentication and verification endpoints
must remain reachable before the caller has full application access.
Patterns use Go ServeMux syntax. Invalid patterns or a nil handler panic during
setup. On third-party routers, adapt the returned http.Handler normally and
ensure OPTIONS reaches it, or put auth.CORS around the complete router.
Request.Pattern and PathValue are populated by the wrapper even if the outer
router does not supply them. Existing low-level middleware stays available for
custom transport arrangements.