Source code for yasuki_core.accounts.oauth_state
from datetime import timedelta
import psycopg
[docs]
def stash_login(
conn: psycopg.Connection,
state: str,
nonce: str,
code_verifier: str,
redirect_to: str | None = None,
) -> None:
"""Record the in-flight OAuth state for a login, to be consumed at the callback.
Parameters
----------
conn : psycopg.Connection
An open accounts-database connection.
state : str
The random CSRF state Google will echo back.
nonce : str
The OIDC nonce bound into the requested id_token.
code_verifier : str
The PKCE verifier whose challenge was sent to Google.
redirect_to : str, optional
A same-site path to land on after login. Default None.
"""
with conn.cursor() as cur:
cur.execute(
"INSERT INTO oauth_logins (state, nonce, code_verifier, redirect_to) "
"VALUES (%s, %s, %s, %s)",
(state, nonce, code_verifier, redirect_to),
)
[docs]
def pop_login(conn: psycopg.Connection, state: str, max_age: timedelta) -> dict | None:
"""Consume the login state for ``state``, or None if absent or older than ``max_age``.
The row is deleted as it is read, so a state is single-use — a replayed or forged callback finds
nothing.
Parameters
----------
conn : psycopg.Connection
An open accounts-database connection.
state : str
The CSRF state returned on the callback.
max_age : datetime.timedelta
Reject a login older than this, guarding against stale or hoarded states.
Returns
-------
login : dict or None
Keys ``nonce``, ``code_verifier``, ``redirect_to`` for a fresh state, else None.
"""
with conn.cursor() as cur:
cur.execute(
"DELETE FROM oauth_logins WHERE state = %s AND created_at > now() - %s "
"RETURNING nonce, code_verifier, redirect_to",
(state, max_age),
)
return cur.fetchone()
[docs]
def purge_stale_logins(conn: psycopg.Connection, max_age: timedelta) -> int:
"""Delete abandoned login rows older than ``max_age``; return how many were removed."""
with conn.cursor() as cur:
cur.execute("DELETE FROM oauth_logins WHERE created_at <= now() - %s", (max_age,))
return cur.rowcount