Skip to content

Models

Package litestar_auth.models exposes the reference User and OAuthAccount ORM models plus the side-effect-free mixins behind the bundled model family. Names are loaded lazily (PEP 562) when accessed on the package.

Import paths

Goal Import
Shared auth-model mixins without registering reference mappers from litestar_auth.models import UserModelMixin, UserAuthRelationshipMixin, OAuthAccountMixin, AccessTokenMixin, RefreshTokenMixin
Bundled AccessToken / RefreshToken mapper bootstrap from litestar_auth.models import import_token_orm_models
OAuth table contract without loading reference User from litestar_auth.models.oauth import OAuthAccount
Reference User (and typical tests / quickstarts) from litestar_auth.models import User or from litestar_auth.models.user import User

Use Configuration as the canonical ORM setup guide for token bootstrap lifecycle, custom model families, SQLAlchemyUserDatabase, and the supported password-column hook. Use the Custom user + OAuth cookbook when the application owns the user table.

Avoid from litestar_auth.models import User (or the user submodule) in apps that already map table user to a custom model. That import registers the bundled reference mapper and conflicts with an app-owned mapping. Likewise, importing OAuthAccount from litestar_auth.models.oauth only keeps the reference User lazy; when the app owns a different user class, table, or registry, prefer an OAuthAccountMixin subclass that points back at the custom user contract.

import_token_orm_models() remains the canonical explicit helper for bundled token metadata bootstrap and Alembic-style autogenerate. LitestarAuth.on_app_init() now calls the same helper lazily for plugin-managed runtime when bundled DB-token models are active, so no extra import side effect is required only to make the plugin work.

For custom SQLAlchemy models, compose the mixins on your own declarative base instead of copying columns or relationship wiring from the reference classes. Configuration covers the full support matrix and migration notes.

UserModelMixin hook

UserModelMixin keeps the runtime attribute contract on hashed_password. When an app-owned user table uses a different SQL column name, set auth_hashed_password_column_name on the custom user class instead of redefining hashed_password = mapped_column(...):

class LegacyUser(UserModelMixin, UserAuthRelationshipMixin, AppUUIDBase):
    __tablename__ = "legacy_user"
    auth_hashed_password_column_name = "password_hash"

BaseUserManager, SQLAlchemyUserDatabase, and JWT password fingerprinting still read and write user.hashed_password; only the SQL column name changes. Direct field redefinition remains compatibility-only for older models that already depend on it.

UserAuthRelationshipMixin hooks

UserAuthRelationshipMixin keeps the bundled inverse relationship contract by default: back_populates="user" on access_tokens, refresh_tokens, and oauth_accounts, with SQLAlchemy's normal loader behavior and inferred foreign-key linkage. Override only the narrow class hooks the mixin documents:

  • auth_access_token_model, auth_refresh_token_model, auth_oauth_account_model point those inverse relationships at custom mapped classes, or to None when a branch is intentionally omitted.
  • auth_token_relationship_lazy forwards one optional lazy= setting to both token collections.
  • auth_oauth_account_relationship_lazy forwards one optional lazy= setting to oauth_accounts.
  • auth_oauth_account_relationship_foreign_keys forwards one optional foreign_keys= hint to oauth_accounts.

The mixin does not accept arbitrary relationship() kwargs. For behavior outside those hooks, keep an app-owned explicit relationship definition.

Canonical oauth_account shape

The library table (bundled OAuthAccount) includes at least:

  • id — UUID primary key (from UUIDBase)
  • user_id — FK to user.id, not null
  • oauth_nameString(100)
  • account_idString(255)
  • account_emailString(320)
  • access_tokenEncryptedString-backed (length 2048), Fernet when a key is configured
  • expires_at — integer epoch or null
  • refresh_token — optional, same encryption type as access token
  • Unique constraint uq_oauth_account_provider_identity on (oauth_name, account_id)

Token encryption uses litestar_auth.oauth_encryption and OAuthConfig.oauth_token_encryption_key (see OAuth guide).

For audit columns (created_at / updated_at), use one mapped class per table; see OAuth guide — audit columns.

litestar_auth.models

ORM models package.

Use :func:import_token_orm_models from this package as the canonical explicit bootstrap helper for the bundled token tables so mapper discovery stays under the models boundary. The strategy layer still exposes the same helper only as a compatibility re-export for existing imports.

Import :mod:litestar_auth.models.oauth when you need :class:~litestar_auth.models.oauth.OAuthAccount without registering the library :class:~litestar_auth.models.user.User (for example, with a custom user table).

For custom user, token, or OAuth classes, compose the side-effect-free ORM mixins exposed here on your own registry instead of copying fields or relationships from the reference models. When those custom token tables back :class:~litestar_auth.authentication.strategy.DatabaseTokenStrategy, pair them with :class:~litestar_auth.authentication.strategy.DatabaseTokenModels.

The package still supports from litestar_auth.models import User, OAuthAccount via lazy attributes (PEP 562). Static type checkers use the TYPE_CHECKING imports below.

AccessTokenMixin

Bases: _TokenModelMixin

Shared mapped attributes for access-token models.

OAuthAccount

Bases: OAuthAccountMixin, UUIDBase

OAuth account linked to a local user.

Provider identity (oauth_name, account_id) is globally unique: one provider identity can only be linked to one local user. Enforced at the persistence layer via UniqueConstraint and upsert logic.

The user relationship targets the declarative class named User in the same registry (the bundled :class:~litestar_auth.models.user.User or your replacement). The default inverse side lives in :class:~litestar_auth.models.user_relationships.UserAuthRelationshipMixin. Configure foreign_keys / overlaps on subclasses if you remap relationships (see the custom user + OAuth cookbook).

OAuthAccountMixin

Shared columns and relationship wiring for OAuth account models.

access_token = mapped_column(oauth_access_token_type) class-attribute instance-attribute

OAuth provider access token. Fernet-encrypted at rest when configured.

refresh_token = mapped_column(oauth_refresh_token_type, default=None, nullable=True) class-attribute instance-attribute

OAuth provider refresh token. Fernet-encrypted at rest when configured.

__table_args__()

Create the provider-identity uniqueness constraint for each subclass.

Returns:

Type Description
tuple[UniqueConstraint]

The unique constraint tuple for (oauth_name, account_id).

Source code in litestar_auth/models/mixins.py
@declared_attr.directive
def __table_args__(cls) -> tuple[UniqueConstraint]:  # noqa: N805, PLW3201
    """Create the provider-identity uniqueness constraint for each subclass.

    Returns:
        The unique constraint tuple for ``(oauth_name, account_id)``.
    """
    constraint_name = cls.auth_provider_identity_constraint_name
    if constraint_name is None:
        constraint_name = f"uq_{cls.__tablename__}_provider_identity"
    return (UniqueConstraint("oauth_name", "account_id", name=constraint_name),)

user()

Map the relationship back to the configured user model.

Returns:

Type Description
Mapped[Any]

The relationship descriptor for the configured user model.

Source code in litestar_auth/models/mixins.py
@declared_attr
def user(cls) -> Mapped[Any]:  # noqa: N805
    """Map the relationship back to the configured user model.

    Returns:
        The relationship descriptor for the configured user model.
    """
    return relationship(
        cls.auth_user_model,
        back_populates=cls.auth_user_back_populates,
        foreign_keys=lambda: [cast("Mapped[Any]", cls.user_id)],
    )

user_id()

Map the foreign key to the configured user table.

Returns:

Type Description
Mapped[UUID]

The mapped user_id foreign-key column.

Source code in litestar_auth/models/mixins.py
@declared_attr
def user_id(cls) -> Mapped[uuid.UUID]:  # noqa: N805
    """Map the foreign key to the configured user table.

    Returns:
        The mapped ``user_id`` foreign-key column.
    """
    return mapped_column(ForeignKey(f"{cls.auth_user_table}.id"), nullable=False)

RefreshTokenMixin

Bases: _TokenModelMixin

Shared mapped attributes for refresh-token models.

User

Bases: UserModelMixin, UserAuthRelationshipMixin, UUIDBase

Base user model for authentication and authorization flows.

UserAuthRelationshipMixin

Declare the inverse relationships expected by the auth ORM model families.

Override the auth_*_model class variables when a custom user model needs to point at custom token or OAuth classes instead of the bundled defaults. Configure the supported relationship-option hooks when a custom user model needs non-default loader strategies or an explicit OAuth foreign_keys setting without redefining the declared_attr methods. Set a model hook to None when the custom user only composes part of the auth model family and should omit that inverse relationship entirely.

access_tokens()

Map the inverse side of the configured access-token model when enabled.

Returns:

Type Description

The relationship descriptor, or None when access-token integration is disabled.

Source code in litestar_auth/_auth_model_mixins.py
@declared_attr
def access_tokens(cls):  # noqa: ANN202, N805
    """Map the inverse side of the configured access-token model when enabled.

    Returns:
        The relationship descriptor, or ``None`` when access-token integration is disabled.
    """
    return cls._relationship(
        cls.auth_access_token_model,
        lazy=cls.auth_token_relationship_lazy,
    )

oauth_accounts()

Map the inverse side of the configured OAuth-account model when enabled.

Returns:

Type Description

The relationship descriptor, or None when OAuth-account integration is disabled.

Source code in litestar_auth/_auth_model_mixins.py
@declared_attr
def oauth_accounts(cls):  # noqa: ANN202, N805
    """Map the inverse side of the configured OAuth-account model when enabled.

    Returns:
        The relationship descriptor, or ``None`` when OAuth-account integration is disabled.
    """
    return cls._relationship(
        cls.auth_oauth_account_model,
        lazy=cls.auth_oauth_account_relationship_lazy,
        foreign_keys=cls.auth_oauth_account_relationship_foreign_keys,
    )

refresh_tokens()

Map the inverse side of the configured refresh-token model when enabled.

Returns:

Type Description

The relationship descriptor, or None when refresh-token integration is disabled.

Source code in litestar_auth/_auth_model_mixins.py
@declared_attr
def refresh_tokens(cls):  # noqa: ANN202, N805
    """Map the inverse side of the configured refresh-token model when enabled.

    Returns:
        The relationship descriptor, or ``None`` when refresh-token integration is disabled.
    """
    return cls._relationship(
        cls.auth_refresh_token_model,
        lazy=cls.auth_token_relationship_lazy,
    )

UserModelMixin

Shared non-primary-key columns used by the bundled User model.

Set auth_hashed_password_column_name on a subclass to keep the public hashed_password attribute while mapping it to a different SQL column name such as password_hash.

hashed_password()

Map the password-hash attribute to the configured SQL column name.

Returns:

Type Description
Mapped[str]

The mapped hashed_password column.

Source code in litestar_auth/_auth_model_mixins.py
@declared_attr
def hashed_password(cls) -> Mapped[str]:  # noqa: N805
    """Map the password-hash attribute to the configured SQL column name.

    Returns:
        The mapped ``hashed_password`` column.
    """
    column_name = cls.auth_hashed_password_column_name
    if column_name == "hashed_password":
        return mapped_column(String(length=255))
    return mapped_column(column_name, String(length=255))

__dir__()

Return public model names for discovery.

Source code in litestar_auth/models/__init__.py
def __dir__() -> list[str]:
    """Return public model names for discovery."""
    return sorted(__all__)

__getattr__(name)

Load lazy model exports on demand.

Returns:

Type Description
object

The requested ORM model or mixin.

Raises:

Type Description
AttributeError

If name is not a public export.

Source code in litestar_auth/models/__init__.py
def __getattr__(name: str) -> object:
    """Load lazy model exports on demand.

    Returns:
        The requested ORM model or mixin.

    Raises:
        AttributeError: If ``name`` is not a public export.
    """
    module_name = {
        "AccessTokenMixin": "litestar_auth.models.mixins",
        "OAuthAccount": "litestar_auth.models.oauth",
        "OAuthAccountMixin": "litestar_auth.models.mixins",
        "RefreshTokenMixin": "litestar_auth.models.mixins",
        "User": "litestar_auth.models.user",
        "UserAuthRelationshipMixin": "litestar_auth.models.mixins",
        "UserModelMixin": "litestar_auth.models.mixins",
    }.get(name)
    if module_name is None:
        msg = f"module {__name__!r} has no attribute {name!r}"
        raise AttributeError(msg)
    return getattr(import_module(module_name), name)

import_token_orm_models()

Return the bundled token ORM models for explicit and plugin-owned bootstrap.

This remains the canonical public helper for metadata bootstrap and Alembic-style autogenerate flows. LitestarAuth.on_app_init() also calls it lazily when bundled DB-token models are active, so plugin-managed runtime no longer depends on a separate app-level import side effect. The helper keeps token-model discovery under litestar_auth.models without importing the reference User mapper.

Source code in litestar_auth/models/tokens.py
def import_token_orm_models() -> tuple[type[AccessToken], type[RefreshToken]]:
    """Return the bundled token ORM models for explicit and plugin-owned bootstrap.

    This remains the canonical public helper for metadata bootstrap and Alembic-style
    autogenerate flows. ``LitestarAuth.on_app_init()`` also calls it lazily when bundled
    DB-token models are active, so plugin-managed runtime no longer depends on a separate
    app-level import side effect. The helper keeps token-model discovery under
    ``litestar_auth.models`` without importing the reference ``User`` mapper.
    """
    db_models_module = importlib.import_module("litestar_auth.authentication.strategy.db_models")

    return db_models_module.import_token_orm_models()