Authorization-code flow with PKCE through an idp adapter (with a fake), ID token validation, identity and roles resolved from the directory with a short cache, refusal of unknown, disabled and locked accounts with one generic page, sessions that end when the account becomes unavailable, sign-out that ends the server-side session, role decorators and the trusted-proxy client address rule. Adds the OIDC_* and PUBLIC_BASE_URL configuration. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N3t4WL7bd9bdHHNjEsxzqC
33 lines
1.1 KiB
Python
33 lines
1.1 KiB
Python
"""Database session store that fills the username and created_at columns."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from datetime import UTC, datetime
|
|
|
|
from django.contrib.sessions.backends.db import SessionStore as DBSessionStore
|
|
from django.utils import timezone
|
|
|
|
from .models import UserSession
|
|
|
|
USER_KEY = "session_user_key"
|
|
USER_SAM = "session_user_sam"
|
|
CREATED_AT = "session_created_at" # epoch seconds, UTC
|
|
DISPLAY_NAME = "session_display_name"
|
|
ROLES = "session_roles" # {"publisher": bool, "admin": bool, "checked": epoch seconds}
|
|
LOGIN_FLOW = "session_login_flow" # state, nonce and PKCE verifier between redirect and callback
|
|
|
|
|
|
class SessionStore(DBSessionStore):
|
|
@classmethod
|
|
def get_model_class(cls):
|
|
return UserSession
|
|
|
|
def create_model_instance(self, data):
|
|
obj = super().create_model_instance(data)
|
|
obj.username = str(data.get(USER_KEY, "")).lower()
|
|
created = data.get(CREATED_AT)
|
|
obj.created_at = (
|
|
datetime.fromtimestamp(created, tz=UTC) if created is not None else timezone.now()
|
|
)
|
|
return obj
|