Skip to main content

splent_feature_auth

The auth feature of a SPLENT product line.

Accounts, login, logout and sessions. It owns the User model, the login page, the accounts screen for administrators (/admin/users), a person's own account page (/account), the login throttle and the password policy. Every SPLENT product installs it.

A SPLENT feature is a Python package that a product composes with others. Its models, routes, services, templates and hooks are registered when the product starts. What this feature provides and requires is listed in the [tool.splent.contract] section of pyproject.toml, which splent feature:contract --write keeps in sync with the source.

The login page

The login page opens three slots, so other features add to it without overriding the template. A callback takes no arguments and returns HTML, or an empty string to add nothing on this request.

Slot Where it renders When
auth.login.providers After the submit button, under the words "or continue with" Only when a callback returns something. Otherwise nothing is drawn, not even the words
auth.login.error_hint Under the error, inside the form Only after a wrong email or password. Never for a throttled attempt or an account that is not active, whose messages stay as they are
auth.login.form_footer At the bottom of the form Always

A sign-in provider puts its button in auth.login.providers.

# hooks.py of a provider feature
from flask import render_template
from splent_framework.hooks.template_hooks import register_template_hook


def login_button():
    return render_template("hooks/login_button.html")


register_template_hook("auth.login.providers", login_button, order=20)

A hint reads what was typed from the request.

from flask import render_template, request


def password_hint():
    email = request.form.get("email", "")
    if not signs_in_with_a_provider(email):
        return ""
    return render_template("hooks/password_hint.html")


register_template_hook("auth.login.error_hint", password_hint)

A hint that depends on the address tells whoever types it whether an account exists there. A feature that adds one should let the product turn it off.

Menus and shells

The feature declares its entries in the framework's menu registry, and an application shell that draws menu_sections() and user_menu_sections() shows them.

Key Menu Section Order Opens Shown to
login Sidebar anonymous 10 auth.login Visitors who are not signed in
auth_users Sidebar admin 20 auth.admin_users The roles the accounts screen asks for, administrators
auth_my_account Sidebar account 50 auth.my_account Every signed-in account
logout Sidebar account 900 auth.logout Every signed-in account
user_login User menu anonymous 10 auth.login Visitors who are not signed in
user_logout User menu account 900 auth.logout Every signed-in account

A product hides or reorders them by key, without overriding a template.

[tool.splent.layout.menu]
hide = ["auth_my_account"]

The sidebar and navbar hooks (layout.anonymous_sidebar, layout.authenticated_sidebar, layout.navbar.anonymous and layout.navbar.authenticated) still draw the same entries for one minor, for the shells that draw those slots. A shell draws the registry or those slots, never both, or every entry shows twice. The next minor drops the hooks.

The login page extends shell('login'), which is AUTH_LOGIN_LAYOUT when the product names one and the application shell otherwise. My account and the accounts screen extend shell('app'), so they follow SPLENT_SHELL_APP.

Password policy

One rule for every place that sets a password. The accounts screen, My account and the create-user and set-password commands apply it, and so does any feature that sets a password and imports it. It applies when a password is set, never at login, so an account whose password predates a longer minimum keeps signing in.

Setting Default Meaning
AUTH_PASSWORD_MIN_LENGTH 8 The shortest password accepted, from 8 to 128. A value below 8 becomes 8 and one above 128 becomes 128, with a warning in the log
AUTH_PASSWORD_CONFIRM false Whether a form that sets a password asks for it twice

No password longer than 128 characters (MAX_LENGTH) can be set, whatever the minimum. That leaves room for a passphrase or a password manager's output, and a form that sets a password never hashes a pasted megabyte.

AUTH_PASSWORD_CONFIRM adds a second box where a form would ask once. My account always asks twice. The commands ask twice whenever they prompt.

A product sets them in its own [tool.splent.config].

[tool.splent.config]
AUTH_PASSWORD_MIN_LENGTH = 12
AUTH_PASSWORD_CONFIRM = true

The API lives in splent_io.splent_feature_auth.passwords.

Name What it does
password_problem(password, confirmation=None) The translated reason a new password cannot be used, or None. A confirmation of None is not compared, and an empty one does not match
PasswordPolicy(repeats=None) WTForms validator built on password_problem. With repeats, it checks that this field repeats the one named
confirmation_required() Whether the product asks for a new password twice
min_length() The shortest password the product accepts, never below MIN_LENGTH_FLOOR (8) nor above MAX_LENGTH (128)
MAX_LENGTH The longest password accepted, 128 characters

A form that sets a password.

from flask_babel import lazy_gettext as _l
from flask_wtf import FlaskForm
from wtforms import PasswordField
from wtforms.validators import DataRequired

from splent_io.splent_feature_auth.passwords import (
    PasswordPolicy,
    confirmation_required,
)


class SignupForm(FlaskForm):
    password = PasswordField(
        _l("Password"), validators=[DataRequired(), PasswordPolicy()]
    )
    confirm_password = PasswordField(
        _l("Repeat the password"), validators=[PasswordPolicy(repeats="password")]
    )

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        if not confirmation_required():
            del self.confirm_password

The template draws the second box only when the form still has it, with {% if form.confirm_password %}. A length error sits under the first box and a mismatch under the second. Put Optional() instead of DataRequired() on a field that may stay blank, such as a new password on an edit form.

Code that is not a form calls the helper directly.

from splent_io.splent_feature_auth.passwords import password_problem

problem = password_problem(password, request.form.get("confirm_password", ""))
if problem:
    flash(problem, "danger")

Use it in a product

splent feature:add splent_feature_auth

Develop

splent feature:test splent_feature_auth
splent feature:contract splent_feature_auth

Release

splent feature:release splent_feature_auth --dry-run --bump patch
splent feature:release splent_feature_auth

The first command rehearses the release and changes nothing. The second publishes it to the git forge and to PyPI, and a PyPI version is permanent.

Metadata

Release files for splent-feature-auth 1.21.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for splent-feature-auth 1.21.0
File Size Uploaded Provenance
splent_feature_auth-1.21.0.tar.gz 64.9 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for splent-feature-auth 1.21.0
File Interpreter ABI Platform
splent_feature_auth-1.21.0-py3-none-any.whl Python 3 none any Details

Total release size: 144.6 kB

Release files / splent_feature_auth-1.21.0.tar.gz

Download URL splent_feature_auth-1.21.0.tar.gz
Size 64.9 kB
Tags Source
SHA-256 checksum
How to use checksums
87249011025c2b34839ad10ae27eaed66074c417bbc9a6df8534c09c85e84efb
BLAKE2b-256 checksum
How to use checksums
b7159c4c6f1bbfa1dc42dddf8486a02c4fa1f2e45a82c5265b3463ebee575b9d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.16

Release files / splent_feature_auth-1.21.0-py3-none-any.whl

Download URL splent_feature_auth-1.21.0-py3-none-any.whl
Size 79.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4be4ed697894468482ffb8b8a88af7e58dd7a12bc522305b73185da10b8add61
BLAKE2b-256 checksum
How to use checksums
eaafe2fc66b7b176149b1c9c4061bd7c80357a27aca90c7d534bfef097ee4dc7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.16

Security for splent-feature-auth 1.21.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

1.21.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page