Authentication
User authentication and security in ReadyKit.
Overview
ReadyKit uses Flask-Security-Too for authentication and Flask-Dance for OAuth. New OAuth accounts receive a workspace; admin-created accounts do not receive one automatically.
Authentication Methods
Email/Password
Admins create email/password accounts. Self-registration, email confirmation, and email password recovery are disabled in enferno/settings.py.
- Argon2 password hashing (configured in settings)
- Email-only login (no usernames)
- Password changes for authenticated users; admin resets through the CLI
- Minimum password length configured as 12 characters
OAuth (Social Login)
Supported providers:
- Google (profile and email scopes)
- GitHub (user:email scope)
New OAuth accounts receive a workspace. Linking OAuth to an existing account keeps its existing memberships.
OAuth Setup
Google OAuth
- Go to Google Cloud Console
- Create credentials → OAuth client ID
- Add authorized redirect URI:
https://yourdomain.com/login/google/authorized
# .env
GOOGLE_AUTH_ENABLED=true
GOOGLE_OAUTH_CLIENT_ID=your_client_id
GOOGLE_OAUTH_CLIENT_SECRET=your_secretGitHub OAuth
- Go to GitHub Developer Settings
- New OAuth App
- Set callback URL:
https://yourdomain.com/login/github/authorized
# .env
GITHUB_AUTH_ENABLED=true
GITHUB_OAUTH_CLIENT_ID=your_client_id
GITHUB_OAUTH_CLIENT_SECRET=your_secretTwo-Factor Authentication
ReadyKit supports multiple 2FA methods:
TOTP (Authenticator Apps)
Users can enable TOTP via their security settings. Works with any authenticator app (Google Authenticator, Authy, 1Password, etc.).
WebAuthn (Passkeys/Security Keys)
Hardware security keys and passkeys are supported via WebAuthn. Users can register multiple devices.
Recovery Codes
When 2FA is enabled, users receive 3 recovery codes. These can be regenerated if lost.
Session Management
Local setup stores sessions in the SQLAlchemy database. The full setup uses Redis:
# .env
REDIS_SESSION=redis://localhost:6379/1Install Redis support with uv sync --extra dev --extra full. If both REDIS_URL and REDIS_SESSION are set, REDIS_URL takes precedence.
Session security features:
- Strong protection: IP + user agent validation
- Cookies: HttpOnly and SameSite=Lax; Secure is disabled for local HTTP setup
- Workspace context: Cleared on login/logout; protected routes recheck membership
Platform Roles vs Workspace Roles
ReadyKit has two role systems:
Platform Roles
Platform access uses User.is_superadmin, a Boolean field:
| Role | Access |
|---|---|
| is_superadmin=True | Platform administration and user management |
| admin role record | Legacy role; assigning it alone does not grant superadmin access |
Workspace routes still require workspace membership and the appropriate role.
Create a superadmin:
uv run flask install
# or
uv run flask create -e admin@example.com --super-admin # Prompts for a passwordWorkspace Roles
Applied to membership within a workspace (see Teams):
| Role | Access |
|---|---|
| admin | Billing, members, settings, all data |
| member | Standard workspace access |
Route Protection
Require Login
from flask_security import auth_required
@app.route("/account/")
@auth_required()
def account():
return render_template("account.html")Require Platform Role
from enferno.services.auth import require_superadmin
@app.route("/admin/")
@require_superadmin()
def admin_panel():
return render_template("admin/index.html")Require Workspace Access
from enferno.services.workspace import require_workspace_access
@app.route("/workspace/<int:workspace_id>/data/")
@require_workspace_access("member") # or "admin"
def workspace_data(workspace_id):
return render_template("data.html")Security Configuration
Key settings in .env:
# Auto-generated by setup.sh
SECRET_KEY=your_secure_key
SECURITY_PASSWORD_SALT=your_salt
SECURITY_TOTP_SECRETS=your_totp_secrets
# Session settings
SESSION_COOKIE_SECURE=True # HTTPS deployments
SESSION_COOKIE_HTTPONLY=True
SESSION_COOKIE_SAMESITE=LaxRegistration, recovery, password policy, session protection, and the one-hour session lifetime are configured in enferno/settings.py. Setting similarly named variables in .env does not override constants that Config does not read.
Email Configuration
Mail configuration available through .env:
# .env
MAIL_SERVER=your_smtp_host
MAIL_USERNAME=your_email
MAIL_PASSWORD=your_app_password
SECURITY_EMAIL_SENDER=noreply@yourdomain.comThe current settings use SMTP over SSL on port 465. Change Config if your provider requires another transport. Mail credentials alone do not enable password recovery or confirmation flows.
User Model
from enferno.user.models import User
# Get user's workspaces
workspaces = user.get_workspaces()
# Get role in specific workspace
role = user.get_workspace_role(workspace_id)
# Check if superadmin
if user.is_superadmin:
# Platform admin access
passImportant Security Notes
WARNING
Email changes are disabled (SECURITY_EMAIL_CHANGEABLE=False); email is the login identity.
INFO
Selected workspace context is cleared on login/logout. Workspace routes must still check membership and scope every data query.
CLI Commands
# Create admin user (interactive)
uv run flask install
# Create user with specific options
uv run flask create -e user@example.com
uv run flask create -e admin@example.com --super-admin
# Reset password
uv run flask reset -e user@example.com
# Add platform role
uv run flask add-role -e user@example.com -r admin