Skip to main content

Authentication for hayate as a pure fetch(Request) -> Response handler: email+password, sessions, CSRF

Project description

hayate-auth

Standards-first authentication for hayate — a mountable, better-auth-style auth handler built on the WHATWG Request/Response model.

Status: alpha (0.5.x). Email+password, sessions, CSRF, email verification, password reset, OAuth 2.1 + PKCE (Google / GitHub), TOTP two-factor, and API keys are implemented and attack-regression-tested; a generate CLI and a Cloudflare D1 adapter ship too. Not yet security-audited — see SECURITY.md. The internal design memo (Japanese) lives in DESIGN.md.

import os

from hayate import Hayate
from hayate_auth import Auth
from hayate_auth.adapters.sqlite import SQLiteAdapter

adapter = SQLiteAdapter("app.db")
adapter.create_tables()

auth = Auth(secret=os.environ["AUTH_SECRET"], adapter=adapter)

app = Hayate()
auth.register(app)  # serves /api/auth/* (sign-up, sign-in, session, ...)

@app.get("/me", auth.require_session())
async def me(c):
    return c.json(c.get("user"))

The same file runs under any ASGI server and on Cloudflare Python Workers — see examples/todo.

Endpoints

Method / path (under /api/auth) Purpose
POST /sign-up/email Register with email + password, start a session
POST /sign-in/email Verify credentials, start a session
GET /get-session Current {user, session} (or nulls)
POST /sign-out Revoke the session server-side
POST /forget-password/reset-password Reset flow via a one-shot hashed token
GET /verify-email Confirm an email with a one-shot token
POST /sign-in/social → GET /callback/:provider OAuth 2.1 + PKCE (Google / GitHub)
POST /two-factor/enable · /verify · /disable TOTP (RFC 6238) enrollment
POST /sign-in/two-factor Second step when 2FA is on
POST /api-key/create · /verify · /delete · GET /api-key/list API keys (hashed, scoped, expiring)

API keys double as the bridge to hayate-mcp: auth.verify_api_key plugs straight into its OAuth Resource Server, so an API key protects an MCP server in one line:

from hayate_mcp import Authorization, McpMount
McpMount(server, authorization=Authorization(
    resource="https://mcp.example.com",
    authorization_servers=["https://auth.example.com"],
    verify_token=auth.verify_api_key,
)).register(app)

With TOTP enabled, /sign-in/email returns {"two_factor_required": true} plus a short-lived signed challenge cookie instead of a session; the client then posts the authenticator code to /sign-in/two-factor to get the session — so a stolen password alone never signs in.

Email delivery is your callback (send_reset_password / send_verification_email); the core mints and verifies tokens but never builds URLs or sends mail. Generate migration DDL with python -m hayate_auth generate --dialect sqlite|postgres|d1.

OAuth providers are injected; the token exchange runs over hayate-fetch, so it works on ASGI and Workers alike:

from hayate_auth import Auth, google, github

auth = Auth(
    secret=os.environ["AUTH_SECRET"],
    adapter=adapter,
    providers=[
        google(client_id=..., client_secret=...),
        github(client_id=..., client_secret=...),
    ],
)

Why

  • Python has no equivalent of better-auth: a framework-agnostic, self-hosted, schema-owning auth library. django-allauth is Django-only; fastapi-users is in maintenance mode.
  • better-auth works on every JS framework because its core is a single fetch(Request) -> Response handler. hayate is the only Python framework whose user-facing surface is WHATWG Request/Response — so that architecture finally maps 1:1 to Python.
  • Zero-dependency core (its only dependency is hayate, itself zero-dependency). Databases, KDFs, and email are injected protocols.

Security posture

  • Passwords: scrypt at OWASP parameters (N=2^17, r=8, p=1) on every runtime, PBKDF2-HMAC-SHA256 (600k) fallback; PHC-style strings make the backends mutually verifiable. Length-only policy per NIST SP 800-63B.
  • Sessions: opaque 256-bit tokens, only their SHA-256 stored; __Host--prefixed HttpOnly SameSite=Lax cookies on HTTPS.
  • CSRF: SameSite + Origin (RFC 6454) + Fetch Metadata — no token embedding.
  • Sign-in failures are uniform in body and KDF timing (enumeration defense).
  • Coverage ledger: docs/asvs.md (OWASP ASVS V6/V7, ratcheted).
  • You must rate-limit /api/auth/* (hayate middleware or your infrastructure): brute-force throttling is deliberately out of core.

License

MIT

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

hayate_auth-0.5.0.tar.gz (23.2 kB view details)

Uploaded Source

Built Distribution

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

hayate_auth-0.5.0-py3-none-any.whl (33.0 kB view details)

Uploaded Python 3

File details

Details for the file hayate_auth-0.5.0.tar.gz.

File metadata

  • Download URL: hayate_auth-0.5.0.tar.gz
  • Upload date:
  • Size: 23.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for hayate_auth-0.5.0.tar.gz
Algorithm Hash digest
SHA256 79f2e0983f76bdc720b5d4e89d1d6c7fd1dc73521c35015ecca448dfd205118b
MD5 cf5cd7c64d7a668fa97bdc3c1652f72f
BLAKE2b-256 6d13b9db8e17ca0f815216adc9f55cfc6fcb12fdb810b3afdb4781ec0b0e8275

See more details on using hashes here.

Provenance

The following attestation bundles were made for hayate_auth-0.5.0.tar.gz:

Publisher: release.yml on hayatepy/hayate-auth

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file hayate_auth-0.5.0-py3-none-any.whl.

File metadata

  • Download URL: hayate_auth-0.5.0-py3-none-any.whl
  • Upload date:
  • Size: 33.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for hayate_auth-0.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 4cb401f684509157ff98ff9d4681583974f597a8d826bd06a81b71c90640af4e
MD5 0552320d8a764f49915ad856d1c1dd21
BLAKE2b-256 a4d76e583c85ccd42006f4529371771c412f1d9c600cd7f0ba67120da3c26baf

See more details on using hashes here.

Provenance

The following attestation bundles were made for hayate_auth-0.5.0-py3-none-any.whl:

Publisher: release.yml on hayatepy/hayate-auth

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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