Skip to content

Identity sessions

reauth.identity_session

IdentitySession dataclass

IdentitySession(
    id: Any | None,
    token_identifier: str,
    token_verifier: str,
    expires_at: int,
    identity_id: Any,
    amr: list[AuthenticationMethodReference],
    context: dict[str, Any] | None = None,
    refresh_token_identifier: str | None = None,
    refresh_token_verifier: str | None = None,
    refresh_token_expires_at: int | None = None,
    family_id: Any | None = None,
    replaced_by_id: Any | None = None,
    revoked_at: int | None = None,
)

The authenticated state of an identity, accessed through a session token.

Attributes:

Name Type Description
id Any | None

The stored session ID, or None before insertion.

token_identifier str

The public lookup identifier of the session token.

token_verifier str

The opaque access-token secret verifier.

expires_at int

The access token expiration as a Unix timestamp in seconds.

identity_id Any

The ID of the authenticated identity.

amr list[AuthenticationMethodReference]

The authentication methods used to authenticate the identity.

context dict[str, Any] | None

Optional additional data stored with the session.

refresh_token_identifier str | None

The refresh token identifier, or None if renewal is disabled.

refresh_token_verifier str | None

The opaque refresh verifier, or None if disabled.

refresh_token_expires_at int | None

The family's absolute deadline, or None if this session has no refresh token. Replacements inherit the deadline.

family_id Any | None

The initial session's ID, or None before initial insertion.

replaced_by_id Any | None

The replacement session's ID, or None if not replaced.

revoked_at int | None

The revocation timestamp, or None if not revoked.

id instance-attribute

id: Any | None

token_identifier instance-attribute

token_identifier: str

token_verifier instance-attribute

token_verifier: str

expires_at instance-attribute

expires_at: int

identity_id instance-attribute

identity_id: Any

amr instance-attribute

amr: list[AuthenticationMethodReference]

context class-attribute instance-attribute

context: dict[str, Any] | None = None

refresh_token_identifier class-attribute instance-attribute

refresh_token_identifier: str | None = None

refresh_token_verifier class-attribute instance-attribute

refresh_token_verifier: str | None = None

refresh_token_expires_at class-attribute instance-attribute

refresh_token_expires_at: int | None = None

family_id class-attribute instance-attribute

family_id: Any | None = None

replaced_by_id class-attribute instance-attribute

replaced_by_id: Any | None = None

revoked_at class-attribute instance-attribute

revoked_at: int | None = None

is_expired

is_expired() -> bool

Check if the access token has expired.

Returns:

Type Description
bool

True if the current time is at or past expiration, False otherwise.

IdentitySessionException

IdentitySessionException(message: str | None = None)

Bases: ReauthException

Base exception for identity session errors.

InvalidSessionTokenException

InvalidSessionTokenException(message: str | None = None)

Bases: IdentitySessionException

Raised when an access token is unknown, malformed, revoked, or replaced.

ExpiredSessionException

ExpiredSessionException(message: str | None = None)

Bases: IdentitySessionException

Raised when an access token has expired.

InvalidRefreshTokenException

InvalidRefreshTokenException(message: str | None = None)

Bases: IdentitySessionException

Raised when a refresh token is unknown, malformed, disabled, or revoked.

ExpiredRefreshTokenException

ExpiredRefreshTokenException(message: str | None = None)

Bases: IdentitySessionException

Raised when a refresh token's absolute deadline has passed.

ReusedRefreshTokenException

ReusedRefreshTokenException(message: str | None = None)

Bases: IdentitySessionException

Raised after revoking a family because a consumed refresh token was reused.

IdentitySessionService

IdentitySessionService(
    *,
    token_provider: TokenProvider,
    refresh_token_provider: TokenProvider,
    lifetime: timedelta = datetime.timedelta(hours=24),
    refresh_token_lifetime: timedelta = datetime.timedelta(
        days=30
    ),
)

Bases: ABC

Abstract base class for managing identity sessions and optional refresh tokens.

Implementers provide token lookups, initial insertion, atomic replacement, and family revocation. Retain replaced sessions until the family's absolute deadline so their identifiers and verifiers can identify refresh token reuse.

Initialize the identity session service.

Parameters:

Name Type Description Default
token_provider TokenProvider

Access token generation and verification.

required
refresh_token_provider TokenProvider

Independent refresh token generation and verification.

required
lifetime timedelta

The access token lifetime. Defaults to 24 hours.

timedelta(hours=24)
refresh_token_lifetime timedelta

The absolute lifetime of a refreshable family, measured from initial issuance. Defaults to 30 days.

timedelta(days=30)

token_provider instance-attribute

token_provider = token_provider

refresh_token_provider instance-attribute

refresh_token_provider = refresh_token_provider

lifetime instance-attribute

lifetime = lifetime

refresh_token_lifetime instance-attribute

refresh_token_lifetime = refresh_token_lifetime

issue async

issue(
    identity_id: Any,
    *,
    amr: list[AuthenticationMethodReference],
    refresh_token: bool = False,
    **context: Any,
) -> tuple[str, str | None, IdentitySession]

Issue and persist a session for an authenticated identity.

The caller is responsible for authenticating the identity before issuance. Only token identifiers and verifiers are persisted; plaintext tokens are returned to the caller.

Parameters:

Name Type Description Default
identity_id Any

The ID of the authenticated identity.

required
amr list[AuthenticationMethodReference]

The authentication methods used to authenticate the identity.

required
refresh_token bool

Whether to issue a refresh token. Defaults to False.

False
**context Any

Optional additional data to store with the session.

{}

Returns:

Type Description
str

A tuple of (token, refresh_token, IdentitySession instance). The

str | None

refresh token is None when renewal is disabled.

Raises:

Type Description
TokenGenerationException

If credential generation repeatedly collides.

validate async

validate(token: str) -> IdentitySession

Validate an access token and return its identity session.

Parameters:

Name Type Description Default
token str

The access token to validate.

required

Returns:

Type Description
IdentitySession

The corresponding IdentitySession instance.

Raises:

Type Description
InvalidSessionTokenException

If the token is malformed, unknown, revoked, or belongs to a replaced session.

ExpiredSessionException

If the access token has expired.

refresh async

refresh(
    token: str, *, refresh_token: bool = True
) -> tuple[str, str | None, IdentitySession]

Consume a refresh token and atomically replace its session.

Both previous tokens become invalid. The replacement retains the identity, AMR, context, family, and absolute deadline, even if access has expired. Reuse of a consumed refresh token revokes its whole family.

Commit the caller's transaction before exposing the replacement tokens. Catch ReusedRefreshTokenException inside the transaction and commit the family revocation before reporting the authentication failure.

Parameters:

Name Type Description Default
token str

The refresh token to consume.

required
refresh_token bool

Whether to issue another refresh token. Defaults to True. False issues a final session whose expiry is still capped by the family's deadline, with no further renewal capability.

True

Returns:

Type Description
str

A tuple of (token, refresh_token, IdentitySession instance). The

str | None

refresh token is None when renewal is disabled.

Raises:

Type Description
InvalidRefreshTokenException

If the token is malformed, unknown, revoked, or otherwise no longer refreshable.

ExpiredRefreshTokenException

If the absolute deadline has passed.

ReusedRefreshTokenException

If the token was already consumed. Family revocation is pending in the caller's transaction and must be committed despite this exception.

TokenGenerationException

If credential generation repeatedly collides.

revoke async

revoke(token: str) -> None

Revoke an entire family identified by an access or refresh token.

Expired and replaced tokens can still identify a family. Unknown, malformed, and already-revoked tokens succeed without error. Commit the caller's transaction before reporting successful revocation.

Parameters:

Name Type Description Default
token str

An access token or refresh token from the family to revoke.

required

insert abstractmethod async

insert(identity_session: IdentitySession) -> typing.Any

Atomically insert a session and initialize its family ID.

Parameters:

Name Type Description Default
identity_session IdentitySession

The complete session model to insert.

required

Returns:

Type Description
Any

The ID of the inserted session.

Raises:

Type Description
TokenIdentifierCollision

If the access or refresh identifiers already exist in the store.

Implementation contract

If family_id is None, set the stored family_id to the generated record ID in the same transaction. Preserve an explicitly supplied family ID. For a new member of an existing family, acquire family protection before insertion and reject a missing or revoked family root. Retain that protection until the transaction ends. Enforce uniqueness of token identifiers (and non-null refresh identifiers). Return the inserted ID and leave transaction commit and rollback to the caller. On identifier collision, raise TokenIdentifierCollision without persisting changes and leave the transaction usable for retry.

update_verifier abstractmethod async

update_verifier(identity_session: IdentitySession) -> None

Upgrade an access-token verifier.

Parameters:

Name Type Description Default
identity_session IdentitySession

The session containing the replacement access verifier.

required
Implementation contract

Update only token_verifier by session ID in the transaction that protects the record. Leave commit and rollback to the caller.

get_by_token_identifier abstractmethod async

get_by_token_identifier(
    token_identifier: str,
) -> IdentitySession | None

Retrieve a session by its access token identifier, regardless of its validity.

Parameters:

Name Type Description Default
token_identifier str

The access token identifier to look up.

required

Returns:

Type Description
IdentitySession | None

The stored session, including expired, replaced, or revoked rows,

IdentitySession | None

or None if the session or its family root is missing.

Implementation contract

Match the access token identifier without filtering out expired, replaced, or revoked sessions. Acquire family protection before locking session rows and return current state protected from competing mutations until the caller's transaction ends. Leave commit and rollback to the caller.

get_by_refresh_token_identifier abstractmethod async

get_by_refresh_token_identifier(
    refresh_token_identifier: str,
) -> IdentitySession | None

Retrieve a session by its refresh token identifier, regardless of its validity.

Parameters:

Name Type Description Default
refresh_token_identifier str

The refresh token identifier to look up.

required

Returns:

Type Description
IdentitySession | None

The stored session, including expired, replaced, or revoked rows,

IdentitySession | None

or None if the session or its family root is missing.

Implementation contract

Match the refresh token identifier without filtering out expired, replaced, or revoked sessions; retained rows are needed for reuse detection. Acquire family protection before locking session rows and return current state protected from competing mutations until the caller's transaction ends. Leave commit and rollback to the caller.

replace abstractmethod async

replace(
    previous_session: IdentitySession,
    new_session: IdentitySession,
) -> typing.Any | None

Atomically replace a session if its refresh token is still usable.

Parameters:

Name Type Description Default
previous_session IdentitySession

The previously retrieved session to replace.

required
new_session IdentitySession

The complete replacement model to persist.

required

Returns:

Type Description
Any | None

The replacement ID, or None with no changes if the previous session

Any | None

is no longer eligible.

Raises:

Type Description
TokenIdentifierCollision

If the new session's access or refresh identifiers already exist in the store.

Implementation contract

Serialize with all replacements and revocations in the same family, for example by locking the retained initial session row before any child rows. Reload the previous session under that protection: its refresh identifier and verifier must still match, its refresh deadline must be in the future, and it must be neither revoked nor replaced. Reject a revoked or missing family root. The supplied previous_session is a snapshot, not proof of eligibility.

Insert new_session with the same family ID and set the previous row's replaced_by_id to the new ID atomically in the caller's transaction. Retain family and session protection until the transaction ends. Leave commit and rollback to the caller. Return None without changes if the previous session is no longer eligible. Propagate storage failures. On identifier collision, raise TokenIdentifierCollision without persisting changes and leave the transaction usable for retry.

revoke_family abstractmethod async

revoke_family(identity_session: IdentitySession) -> None

Persist revocation of every session in the supplied session's family.

Parameters:

Name Type Description Default
identity_session IdentitySession

The session identifying the family and revocation time.

required
Implementation contract

Use the supplied identity_session.revoked_at for rows not yet revoked. Preserve earlier revocation timestamps, identifiers, verifiers, and lineage. Serialize with all replacements and revocations in the family, for example by locking its retained initial session row before any child rows.

Apply revocation in the caller's transaction and retain family and session protection until the transaction ends. Leave commit and rollback to the caller. Revocation becomes durable on commit; a rollback restores the previous state. Missing or already-revoked families succeed without error.