Skip to content

Passwords

The rules every new password must meet, and the context a validator can read. See Passwords for where they apply and the 422 they produce.

crudauth.password.PasswordPolicy dataclass

PasswordPolicy(
    min_length: int = MIN_PASSWORD_LENGTH,
    require_uppercase: bool = False,
    require_lowercase: bool = False,
    require_digit: bool = False,
    require_special: bool = False,
    validators: Sequence[PasswordValidator] = (),
)

The rules a new password must meet, on registration, set, change and reset.

The built-in rules run first and every unmet one is reported. validators run after them, in order, only once the built-in rules pass, and stop at the first that fails. A validator is a sync or async function that raises ValueError with the message to show. It's called with (password), or with (password, context) and a PasswordContext when it takes two required positional arguments.

Attributes:

Name Type Description
min_length int

The fewest characters allowed, at least 1.

require_uppercase bool

Require an uppercase letter.

require_lowercase bool

Require a lowercase letter.

require_digit bool

Require a decimal digit.

require_special bool

Require a character that isn't a letter or a digit, spaces included.

validators Sequence[PasswordValidator]

Extra checks, such as a breached-password lookup.

Example
async def not_breached(password: str) -> None:
    if await breach_count(password):
        raise ValueError("This password has appeared in a data breach")

auth = CRUDAuth(..., password_policy=PasswordPolicy(min_length=12, validators=[not_breached]))

description property

description: str

The built-in rules as a sentence, shown on password fields in OpenAPI.

body_field

body_field() -> Any

The request-body type for a new password.

It documents the policy in OpenAPI without validating in pydantic, so a rejected password is never echoed back in the error body; routes call enforce instead.

check async

check(
    password: str, context: PasswordContext
) -> list[dict[str, Any]]

Return one error per unmet built-in rule, or the first failing validator's error.

Rules and validators see the NFKC-normalized password, the form that gets hashed.

enforce async

enforce(
    password: str,
    context: PasswordContext,
    *,
    field: str = "password",
) -> None

Raise PasswordPolicyException (422) when password fails.

crudauth.password.PasswordContext dataclass

PasswordContext(
    source: PasswordSource,
    username: str | None = None,
    email: str | None = None,
    user: Any = None,
)

Who a new password is for, passed to validators that take a second argument.

Attributes:

Name Type Description
source PasswordSource

The flow setting the password: "register", "set", "change" or "reset".

username str | None

The account's username, or None when the account shape has none.

email str | None

The account's email, or None when the account shape has none.

user Any

The user row, or None on registration.

for_user classmethod

for_user(
    repo: UserRepository, source: PasswordSource, user: Any
) -> PasswordContext

The context for an existing user, with its username and email read through repo.