microdot.session — signed cookie sessions

A per-user key/value store backed by a jwt in a single session cookie. The JWT is signed with a secret known only to the application, so the client can read the cookie but cannot tamper with the payload without the server detecting it.

class Session

class microdot.session.Session(app: Microdot | None = None, secret_key: bytes | str | None = None, cookie_options: dict | None = None)
app

The microdot.Microdot instance to install on. Optional; call initialize() later if not given.

secret_key

Symmetric key used to sign the session JWT. Required before any session is read or written – accessing get() without one raises ValueError. Store it outside source control; on a camera this is typically a file on the FAT filesystem.

cookie_options

Dict of options forwarded to microdot.Response.set_cookie() whenever the session cookie is written. Defaults set path='/' and http_only=True. Add secure=True for HTTPS-only deployments.

initialize(app: Microdot, secret_key=None, cookie_options=None)

Attach to app if construction was deferred. secret_key / cookie_options override constructor values if given.

get(request) SessionDict

Return the session dictionary for request. The dictionary is lazily decoded from the session cookie on first access and cached on request.g._session for the rest of the request. Tampered / unsignable cookies return an empty dict.

encode(payload: dict, secret_key=None) str

Encode payload as a JWT with the session’s secret. Used internally; exposed for callers that want to mint compatible tokens.

decode(session: str, secret_key=None) dict

Verify and decode a JWT-string session value. Returns {} on any verification failure.

secret_key: bytes | str | None

The signing secret used to sign and verify the session JWT. Settable post-construction. None until set; reading the session without it raises ValueError.

cookie_options: dict

The dict of options applied to the session cookie when it is written, forwarded to microdot.Response.set_cookie(). Defaults set path='/' and http_only=True after initialize() runs.

class SessionDict

class microdot.session.SessionDict(request, session_dict)

The dict-like object returned by Session.get(). Subclasses dict, so all standard mutations work; two extra methods commit the changes back into the response.

save()

Write the (possibly mutated) session back into the response as a new session cookie. Without this call, in-place edits are lost when the request ends.

delete()

Remove the session by emitting a cookie-deletion header on the response.

Module-level decorators

microdot.session.with_session(f)

Decorator that passes the session dictionary to the route handler as a second argument:

from microdot import Microdot
from microdot.session import Session, with_session

app = Microdot()
Session(app, secret_key=load_secret())

@app.get('/counter')
@with_session
async def counter(request, session):
    session['n'] = session.get('n', 0) + 1
    session.save()
    return {'n': session['n']}

The decorator does not auto-save – call SessionDict.save() when the session was modified.

The session payload itself is a regular Python dict serialized as JSON inside the JWT. Keep it small: every request and every response carries the full cookie, and JWTs are not designed for storing large objects. For per-user state larger than a few hundred bytes, store the data server-side keyed by a small session identifier.