caddy-atproto-auth#
A native Caddy module that provides Identity-Aware Proxy (IAP) capabilities using the atproto (Bluesky) OAuth 2.1 ecosystem.
Turn any atproto identity into a "Web Passport" for your self-hosted services. The module acts as an OAuth Confidential Client, managing the DPoP cryptographic handshake, session persistence, and DID-based authorization without requiring external authentication sidecars like Authelia.
Features#
- Zero-Dependency: Plugs directly into Caddy, no external databases (uses embedded SQLite).
- Stateless Verification: Uses signed, domain-scoped cookies for lightning-fast request verification at the edge without database lookups.
- Transparent Session Refresh: Automatically uses OAuth Refresh Tokens to extend sessions in the background, minimizing forced re-logins.
- Two Deployment Modes:
- Standalone: Add to any individual app's Caddyfile route directly.
- Centralized Hub: Act as an Identity Provider (
auth.example.com) granting SSO access to many subdomains (app.example.com).
- Full Customization: Fully override the login and forbidden pages with your own HTML templates.
Usage#
Build a custom Caddy binary with xcaddy:
xcaddy build \
--with tangled.org/vvill.dev/caddy-atproto-auth
Configuration#
Global Options#
The atproto global block configures the shared storage and security settings.
{
atproto {
# Path to the SQLite database.
# Default: "atproto.db"
storage_path /var/lib/caddy/atproto.db
# A random 32+ character string used to sign session cookies.
# REQUIRED.
cookie_secret "change-me-to-a-secure-random-string-at-least-32-chars"
}
}
Authentication Portal (atproto_portal)#
The atproto_portal directive configures the central authentication server. This handles the OAuth flow, serves the login page, and issues session cookies.
auth.example.com {
atproto_portal {
# The public domain of the portal.
# REQUIRED.
domain auth.example.com
# The display name shown on the login page.
# Default: "Authentication Portal"
name "My Services"
# Custom UI templates (optional)
ui {
# Path to a custom HTML template for the login page.
login_template /path/to/login.html
}
}
}
Authentication Gate (atproto_gate)#
The atproto_gate directive protects your services. It verifies the session cookie and enforces access control.
app.example.com {
atproto_gate {
# List of allowed identities (DIDs or Handles).
# REQUIRED.
allow @alice.bsky.social
allow did:plc:1234abcd...
# URL of the central Auth Portal.
# Requests without a valid session will be redirected here.
# REQUIRED (unless in Standalone Mode).
portal_url https://auth.example.com
# Standalone Mode Configuration (Alternative to portal_url)
# If set, this gate acts as its own portal.
# domain app.example.com
# Custom UI templates (optional)
ui {
# Path to a custom HTML template for the "Access Denied" page.
forbidden_template /path/to/forbidden.html
}
}
reverse_proxy localhost:8080
}
Documentation#
See the docs/ folder for detailed architectural constraints and implementation details.