Skip to main content

Passwordless authentication for Flask using magic links (and future passkeys).

Project description

Flask-Pass0

Alpha software and not ready for production. Passwordless authentication for Flask.

What It Does

Handles magic link authentication flow with built-in security:

  • Token hashing (HMAC-SHA256)
  • Single-use enforcement
  • Secure generation (256-bit entropy)
  • 10-minute expiry

What You Add

  • HTTPS (required)
  • Email sending
  • Rate limiting
  • CSRF protection
  • Any other security

Install

pip install flask-pass0

Quick Start

from flask import Flask
from flask_pass0 import Pass0
from flask_pass0.utils import login_required

app = Flask(__name__)
app.config['SECRET_KEY'] = 'your-secret-key'
app.config['PASS0_DEV_MODE'] = True  # Shows links in console and not by email

pass0 = Pass0(app)

@app.route('/')
@login_required
def index():
    return "Protected page"

Configuration

Option Default Description
SECRET_KEY required For token hashing
PASS0_DEV_MODE False Show links in console vs by email
PASS0_TOKEN_EXPIRY 10 Token expiry (minutes)
PASS0_TOKEN_LENGTH 32 Token bytes (32 = 256 bits)

Storage

SQLAlchemy

from flask_sqlalchemy import SQLAlchemy
from flask_pass0.storage import SQLAlchemyStorageAdapter

db = SQLAlchemy(app)

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    email = db.Column(db.String(255), unique=True)
    
    def to_dict(self):
        return {"id": self.id, "email": self.email}

storage = SQLAlchemyStorageAdapter(
    user_model=User,
    session=db.session,
    secret_key=app.config['SECRET_KEY']
)
pass0 = Pass0(app, storage_adapter=storage)

Custom

Implement StorageAdapter interface for Redis, MongoDB, etc. See flask_pass0/storage.py.

Email Setup

app.config['MAIL_SERVER'] = 'smtp.gmail.com'
app.config['MAIL_PORT'] = 587
app.config['MAIL_USE_TLS'] = True
app.config['MAIL_USERNAME'] = 'user@gmail.com'
app.config['MAIL_PASSWORD'] = 'app-password'
app.config['MAIL_DEFAULT_SENDER'] = 'noreply@example.com'
app.config['PASS0_DEV_MODE'] = False  # Send real emails

Security

Built-in:

  • Tokens hashed with HMAC-SHA256
  • Single-use enforcement
  • 10-minute expiry
  • 256-bit entropy

Your responsibility:

  • HTTPS (tokens in URLs)
  • Email security
  • Rate limiting (use Flask-Limiter)
  • CSRF protection (use Flask-WTF)
  • Strong SECRET_KEY
  • All other security

Attack scenarios:

Database compromised: Tokens are hashed, can't be reversed without SECRET_KEY.

Token intercepted: Can be used once within 10 minutes. HTTPS required. For high security applications, add 2FA separately.

Brute force: 2^256 space makes guessing impossible.

Routes

  • GET /auth/login - Login page
  • POST /auth/request-magic-link - Request link (JSON: {"email": "user@example.com"})
  • GET /auth/verify/<token> - Verify token
  • GET /auth/logout - Logout

Notes

Magic links are bearer tokens. Device/email compromise allows token interception. For sensitive apps, implement 2FA after login.

Power users with password managers may prefer passwords. Consider offering both.

Examples

See examples/ directory.

License

MIT

Issues

Found a bug? Open an issue on GitHub. Security issue? Contact maintainer directly.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

flask_pass0-0.1.0.tar.gz (11.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

flask_pass0-0.1.0-py3-none-any.whl (11.7 kB view details)

Uploaded Python 3

File details

Details for the file flask_pass0-0.1.0.tar.gz.

File metadata

  • Download URL: flask_pass0-0.1.0.tar.gz
  • Upload date:
  • Size: 11.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.0

File hashes

Hashes for flask_pass0-0.1.0.tar.gz
Algorithm Hash digest
SHA256 1856bb1b4ef127feac2c3c580e2b796641e1640ebd2e2acb48e369b757fafc21
MD5 9f1d9bb891c47eb0e7c91647199e965a
BLAKE2b-256 c40422ddd0fbbd0a5962056632a67df13445c7f3f76842ed85c7c9a98cf37d6f

See more details on using hashes here.

File details

Details for the file flask_pass0-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: flask_pass0-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 11.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.0

File hashes

Hashes for flask_pass0-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 ce35f1224b1e9c662ab44dd2feda8030bd8ef953b4ea07f869d4520ab007ff1f
MD5 300af3e5d2ad16a7cd6815a5854aeeb6
BLAKE2b-256 85c04f3c03612f155dd67ea92f71bc375796fa0d7ae19364075fde8d12557d94

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page