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)
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)
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)
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.