Sessions, flash, and CSRF
UI-mode projects in both project types ship encrypted
cookie sessions (gin-contrib/sessions), one-shot flash messages, and CSRF
protection wired into the application. SESSION_SECRET (32+ bytes) drives both the signing
and encryption keys; in development an ephemeral secret is generated with a
warning, outside development it is required.
// Session values_ = session.Set(c, "theme", "dark")theme := session.Get(c, "theme")
// Flash messages survive exactly one redirect_ = session.PutFlash(c, "success", "Task created.")// in the next handler:flashes := session.Flashes(c) // returns and clearsEvery state-changing request (POST/PUT/PATCH/DELETE) outside /api/ must
carry the per-session CSRF token — in the _csrf form field or the
X-CSRF-Token header — or it is rejected with 403 csrf_token_mismatch
(constant-time comparison). Safe methods mint the token lazily.
In HTML forms, render the hidden field:
<form method="post" action="/tasks"> {{.csrf_field}} ...</form>c.HTML(http.StatusOK, "tasks.html", gin.H{ "csrf_field": session.TemplateField(c), "flashes": session.Flashes(c),})JSON APIs under /api/ are exempt by default (they authenticate with Bearer
tokens, which browsers cannot send cross-site automatically); customize with
CSRFOptions.Skipper.
Projects generated with --auth --oauth also use the encrypted session for
social sign-in in API mode. Once a browser is signed in, state-changing /api/
requests require the X-CSRF-Token returned by GET /api/v1/auth/csrf.
Bearer-token requests remain exempt. See OAuth social sign-in.

