- Google. The user signs in with their Google account. You need OAuth credentials from a Google Cloud project.
- Email. The user types their address and gets a link that signs them in. You need no Google Cloud project, only a way to send email.
SIGN_IN_METHOD in config.py,
or with feather new --sign-in email.
Setup: Google
1
Create OAuth credentials
In the Google Cloud Console.
2
Add the redirect URI
http://localhost:5173/auth/google/callback for development, or your production URL.3
Add credentials to .env
.env
4
Create your admin user
Setup: email
1
Choose email sign-in
feather new --sign-in email sets it for a new app. In an existing one, set it in
config.py:config.py
2
Give it a way to send the email
Feather uses the first of these that is set:
3
Create your admin user
seeds.py.How a sign-in code works
/auth/email/loginasks for an address and emails a six-digit code. The page asks for the code whether or not the address has an account, so the form can’t be used to find out who does.- The code page has a box per digit. Typing the last digit, pasting the code, or letting a phone fill it in from the email signs the person in straight away, with no button to press. Without JavaScript it’s one field and a Sign in button.
- New addresses are handled exactly as a first Google sign-in would be: created, and approved or held for approval.
SIGN_IN_CODE_MINUTES (15), and stops working after five
wrong tries; Send a new code replaces it. The tries and “works once” are counted in the
cache, so with several workers configure Redis (REDIS_URL) to make them hold across all
of them.
To change how the pages look, copy feather/templates/auth/email_sign_in.html to
templates/auth/email_sign_in.html in your app.
Routes
Only the routes for your
SIGN_IN_METHOD answer; the others return 404. Pages behind
@auth_required send signed-out visitors to the right one.
Approval workflows
In a single-tenant app, the address inADMIN_EMAIL (in config.py, filled in from
feather new --admin-email) is an active admin from its first sign-in, so the app’s owner
is never held for approval. Everyone else follows the rules below.
New users can be approved automatically or held for admin review.
Manual approval creates users in a suspended state. They see a pending-approval page
until an admin approves them in the admin panel. This keeps
drive-by signups out and leaves you in control of who has access.
Auto-approve activates users on first login. Choosing it during scaffolding sets
AUTO_APPROVE_USERS = True in config.py, and the framework handles the rest. There are
no callback files or environment variables to add.
Status pages
Both pages are scaffolded with a message and a logout button, and use
@login_only so
users stay authenticated while they read them. Edit the templates in
templates/pages/account/ to match your branding.
Decorators
Which one to use
|
@role_required('editor') | Checking by role name, with inheritance |
| @permission_required('resources.create') | Checking by action, which reads more clearly |
| @admin_required | Shorthand for @role_required('admin') |
Roles
These defaults suit most apps, and you can add, remove or rename them.
Roles inherit permissions, so
@role_required('editor') admits editors and admins.
To customize, edit the hierarchy in feather/auth/roles.py:
@role_required('reviewer'). The User model’s role field is a plain string,
so adding a role needs no migration.
Permissions
Access control by action, mapped onto roles.feather/auth/permissions.py and extend the same way roles do.
Seeds
seeds.py populates initial data. The scaffolded version creates your admin user with
the email you gave during feather new. Extend it for your own data:
seeds.py
python seeds.py or feather db seed. The scaffolded seed is idempotent,
updating existing users rather than duplicating them.
Callbacks
Post-login callback
Post-login callback
For apps that need account setup after OAuth.Use it to create Account or Membership records, assign tenants to users with public
email addresses, or drive an onboarding flow.
.env
myapp/auth.py
Pre-register callback
Pre-register callback
Block new registrations before the account is created. This runs during signup for
new users only. Existing users logging in are unaffected.A returned string blocks registration, shows the message as a toast error, and creates
no user record.
.env
myapp/auth.py
None lets registration proceed. Errors raised inside the callback
are logged but don’t block signups.