# Sessions, Cookies, Flash, and CSRF

Iwf sessions are signed-cookie-backed. In normal apps the runner and `render`
own the lifecycle: every controller receives a `ControllerContext`, handlers
update session state through context helpers, and rendered responses commit the
signed cookie.

## 1. Session Storage Contract

Iwf's built-in session store is the signed session cookie. Session entries,
flash messages, the framework session identity, and the CSRF token are
serialized into the cookie value and verified with the configured
`SessionConfig.secret` on every request.

There is no implicit server-side session table in the framework runtime. If an
application needs revocation, server-side invalidation, large session payloads,
or audit trails, store those records in application tables and keep only stable
identifiers in the signed session. Production applications must use a
non-default secret and secure cookie settings.

## 2. SessionConfig

```idris
sessionConfig : SessionConfig
sessionConfig =
  secureSessionConfig sessionSecret
```

Session config controls:

- cookie name
- signing secret
- `Secure`
- `HttpOnly`
- `SameSite`

Use secure session cookies in production.

## 3. Cookie Defaults

The framework provides two canonical cookie profiles:

- `defaultSessionConfig` and `defaultCookieOptions` are local-development
  defaults: `Secure = False`, `HttpOnly = True`, `SameSite = "Lax"`, and the
  session secret is intentionally unsafe.
- `secureSessionConfig secret` and `secureCookieOptions` are production
  defaults: `Secure = True`, `HttpOnly = True`, `SameSite = "Lax"`, and the
  application provides the secret.

Production deployments should fail configuration validation when they use the
development session secret or non-secure session cookies.

## 4. Reading And Writing Session Data

```idris
response : Response
response =
  commitContextSession context
    (putSession "theme" "dark")
    (seeOther "/settings")
```

Helpers:

- `lookupSession`
- `putSession`
- `deleteSession`
- `commitContextSession`

Most handlers do not need to commit a session directly. `render`,
`renderFragment`, validation rendering, flash helpers, and auth helpers commit
the session they return.

## 5. Controller Session Lifecycle

`render` and `renderFragment` commit the controller session so rendered forms
and the signed session cookie stay in sync.

`loginUserInContext`, `loginUserWithFlashInContext`, and `logoutUserInContext`
start a fresh signed session, rotate the framework session id, and rotate the
CSRF token. This prevents a pre-authentication cookie value from being promoted
unchanged into an authenticated session.

## 6. Raw Cookies

Use raw cookie helpers for feature-specific cookies:

- `lookupCookie`
- `withCookie`
- `clearCookie`

Cookie values are URL encoded and decoded by the HTTP layer.
Signed session-cookie verification is framework lifecycle plumbing. Import the
advanced cookie/session modules only when writing framework integrations or
low-level tests.

## 7. Flash Messages

Flash messages are session entries with a framework-owned prefix:

```idris
let session = flashNotice "Article published" oldSession
let session = flashError "Could not save article" oldSession
```

Read and clear:

```idris
let (notice, sessionAfterFlash) = takeFlash "notice" session
```

The default shell has a stable flash host outside `#main-content`. HTMX
fragment responses can update the flash host out-of-band.

## 8. CSRF

Controller rendering injects the hidden field into non-GET forms:

```idris
settingsForm : ControllerContext -> Html
settingsForm context =
  <form method="post" action="/settings">
    <input name={settingsFormEmailField} type="email" />
    <button type="submit">Save</button>
  </form>
```

Low-level helpers:

- `csrfInput`
- `putSessionCsrfToken`
- `validateSessionCsrf`

Validate submitted forms before mutating state. CSRF tokens live in the signed
session and are posted back as hidden form fields added by `render` or
`renderFragment`. Controller helpers validate against the session token with
`validateSessionCsrf`; there is no static controller-level CSRF token.

## Next

Read [Authentication and Authorization](authentication-and-authorization.md).
