# How to Configure SessionMiddleware for User Sessions in Air

> Configure SessionMiddleware for user sessions in Air with a secret key to enable signed cookie-based sessions accessible via request.session. Optimize your application today.

- Repository: [Feldroy/air](https://github.com/feldroy/air)
- Tags: how-to-guide
- Published: 2026-03-01

---

**Add `air.SessionMiddleware` to your application with a `secret_key` parameter to enable signed cookie-based sessions accessible via `request.session` on every incoming request.**

Configuring SessionMiddleware for user sessions in the `feldroy/air` framework requires minimal boilerplate while providing secure, stateful interactions across HTTP requests. Air implements session handling as a thin wrapper around **Starlette's** `SessionMiddleware`, exposing a familiar API for storing user-specific data in signed browser cookies. This guide demonstrates the exact implementation details found in the source code and provides production-ready patterns for session management.

## Understanding Air's Session Architecture

Air’s session handling is intentionally lightweight, delegating core functionality to Starlette’s battle-tested implementation. In [`src/air/middleware.py`](https://github.com/feldroy/air/blob/main/src/air/middleware.py), the `SessionMiddleware` class inherits directly from `starlette.middleware.sessions.SessionMiddleware` without overriding behavior, ensuring complete compatibility with Starlette’s session protocol.

When you register this middleware on an `air.Air` application instance, it performs three critical operations on every request:

1. **Deserializes** the incoming signed cookie into a mutable dictionary attached to `request.session`
2. **Validates** the cookie signature using your configured `secret_key` to prevent tampering
3. **Serializes** any modifications back into the response cookie when the request completes

The session object requires **JSON-serializable values** only—strings, numbers, lists, and dictionaries. Complex Python objects must be converted before storage.

## Basic Configuration

Enable sessions by calling `add_middleware()` on your Air application instance. The `secret_key` parameter is mandatory and serves as the cryptographic signing key for cookie integrity.

```python
import air

app = air.Air()
app.add_middleware(air.SessionMiddleware, secret_key="change-me-in-production")

```

The middleware re-export in [`src/air/__init__.py`](https://github.com/feldroy/air/blob/main/src/air/__init__.py) makes `air.SessionMiddleware` available as a public API, so you do not need to import from the middleware submodule directly.

## Reading and Writing Session Data

Once configured, every `air.Request` object includes a `session` attribute behaving like a standard Python dictionary. The framework automatically handles cookie parsing and persistence, allowing you to focus on business logic.

```python
from time import time
import air

app = air.Air()
app.add_middleware(air.SessionMiddleware, secret_key="change-me")

@app.page
async def set_timestamp(request: air.Request):
    # Store data in the session dictionary

    request.session["first-visited"] = time()
    return air.H1("Session initialized")

@app.page
async def show_timestamp(request: air.Request):
    # Retrieve data safely using .get() to handle missing keys

    timestamp = request.session.get("first-visited")
    return air.H1(f"First visited: {timestamp}")

@app.page
async def clear_session(request: air.Request):
    # Remove specific keys or clear the entire session

    request.session.pop("first-visited", None)
    return air.H1("Session cleared")

```

The cookie is sent to the client only when the response modifies the session. Clearing all keys or setting `request.session = {}` removes the cookie entirely.

## Building Authentication Flows

The session middleware supports complete authentication workflows, as demonstrated in [`docs/learn/cookbook/authentication.md`](https://github.com/feldroy/air/blob/main/docs/learn/cookbook/authentication.md) and validated in [`tests/test_middleware.py`](https://github.com/feldroy/air/blob/main/tests/test_middleware.py). Store user identifiers and metadata after verification, then check for their presence on protected routes.

```python
import air
from time import time

app = air.Air()
app.add_middleware(air.SessionMiddleware, secret_key="change-me")

@app.page
async def index(request: air.Request):
    if "username" in request.session:
        return air.layouts.mvpcss(
            air.H1(f"Welcome {request.session['username']}"),
            air.P(air.A("Logout", href="/logout")),
        )
    
    return air.layouts.mvpcss(
        air.Form(
            air.Label("Name:", for_="username"),
            air.Input(name="username", type_="text", required=True),
            air.Button("Login", type_="submit"),
            action="/login",
            method="post",
        )
    )

@app.post("/login")
async def login(request: air.Request):
    form = await request.form()
    if username := form.get("username"):
        request.session["username"] = username
        request.session["logged_in_at"] = time()
    return air.RedirectResponse("/", status_code=302)

@app.page
async def logout(request: air.Request):
    request.session.pop("username", None)
    return air.RedirectResponse("/")

```

This pattern leverages the immutable nature of signed cookies to maintain authentication state without server-side storage.

## Summary

- **Air's SessionMiddleware** is a direct subclass of Starlette's implementation located in [`src/air/middleware.py`](https://github.com/feldroy/air/blob/main/src/air/middleware.py), providing signed cookie-based session storage.
- **Configuration requires** a `secret_key` parameter passed to `app.add_middleware(air.SessionMiddleware, secret_key="...")` to cryptographically sign session cookies.
- **Data access** occurs through `request.session`, a mutable dictionary available on all incoming requests that automatically persists changes to the client cookie.
- **Storage constraints** limit values to JSON-serializable types only; the cookie is cleared when the session becomes empty.
- **Authentication patterns** follow standard session-based workflows: store identifiers on login, validate presence on protected routes, and delete keys on logout.

## Frequently Asked Questions

### What is the difference between air.SessionMiddleware and Starlette's SessionMiddleware?

`air.SessionMiddleware` inherits directly from `starlette.middleware.sessions.SessionMiddleware` without modifications, as defined in [`src/air/middleware.py`](https://github.com/feldroy/air/blob/main/src/air/middleware.py). Air re-exports this class in [`src/air/__init__.py`](https://github.com/feldroy/air/blob/main/src/air/__init__.py) to provide a unified namespace while maintaining 100% API compatibility with Starlette's session implementation.

### What data types can be stored in request.session?

The session dictionary accepts only **JSON-serializable values**: strings, integers, floats, booleans, lists, and dictionaries. Attempting to store custom objects, datetime instances, or binary data will raise a serialization error when Air processes the response. Convert complex types to strings or ISO timestamps before storage.

### How do I clear or delete a session?

Remove specific keys using `request.session.pop("key", None)` to avoid KeyError exceptions. To clear the entire session, either delete all keys individually or set `request.session` to an empty dictionary. The middleware detects empty sessions and instructs the browser to delete the cookie automatically.

### Where is the session data stored?

Session data resides entirely in the **client-side signed cookie**. Air does not maintain server-side session storage by default. The `secret_key` signs the cookie to prevent client tampering, but the data payload is visible to the user (though cryptographically verified). Keep session data small and avoid storing sensitive information like passwords or credit card numbers.