For front-line developers

Auth that works the way you'd expect it to.

Standard OIDC. Open REST API. JWTs that standard libraries parse correctly. Webhook events with signatures. A local dev server. If you've been surprised by a vendor's non-standard behavior before, Bastionary is for you.

Read the docs → Start free trial
OIDC/
OAuth 2.0
Standard protocol
Any library works
~1 week
Typical integration time
From zero to production
6 SDKs
Node, Python, Go, Ruby, PHP, Java
All open source
100%
API-first
Everything the UI does, the API does

Works with your stack.

Drop-in integration for the frameworks you already use. No proprietary middleware, no magic — standard OIDC that plugs into the auth layer you already understand.

TypeScript app/api/auth/[...bastionary]/route.ts
// app/api/auth/[...bastionary]/route.ts
import { BastionaryProvider } from '@bastionary/next';

export const { GET, POST } = BastionaryProvider({
  clientId: process.env.BASTIONARY_CLIENT_ID!,
  clientSecret: process.env.BASTIONARY_CLIENT_SECRET!,
  issuer: process.env.BASTIONARY_ISSUER!,
});
Python main.py
from bastionary import AsyncClient

client = AsyncClient(
    client_id=os.getenv("BASTIONARY_CLIENT_ID"),
    client_secret=os.getenv("BASTIONARY_CLIENT_SECRET"),
    issuer=os.getenv("BASTIONARY_ISSUER"),
)

@app.get("/protected")
async def protected(token: str = Depends(client.require_auth)):
    return {"user": token.sub}
Bash any OIDC-compliant library
# Discovery endpoint exposes all standard metadata
curl https://your-domain.bastionary.com/.well-known/openid-configuration

# Works with next-auth, passport.js, django-allauth, omniauth, etc.
# If it speaks OIDC, it works with Bastionary.

Built for developer happiness.

The features that matter when you're actually building — not the ones on a feature comparison spreadsheet.

Local dev server

bastionary dev starts a local auth server that mirrors production. Test login flows, MFA, webhooks, and edge cases without hitting the cloud.

Typed webhook events

Every webhook event has a published JSON schema. SDKs include TypeScript types for every payload. No parsing surprises.

Good error messages

Auth errors include error codes, human-readable messages, and links to docs. invalid_grant tells you why the grant was invalid, not just that it was.

Test users API

Create and delete test users via API. Write E2E tests without mocking auth. No test user cleanup left in prod.

Event log in the dashboard

Every auth event in your dashboard, searchable by user, IP, or event type. Debug integration issues without digging through logs.

PKCE out of the box

PKCE is required for all public clients (SPAs, mobile). No config needed — it's the default, not the opt-in.

No vendor lock-in. Just OIDC.

Bastionary issues standard RFC-compliant JWTs. Your middleware, your WAF, your API gateway — if they validate JWTs, they work with Bastionary without modification. When you switch IDPs, your token-consuming code doesn't change.

JWT Payload
{
  "sub": "usr_01h2xyz...",
  "iss": "https://auth.example.com",
  "aud": "https://api.example.com",
  "exp": 1735689600,
  "iat": 1735686000,
  "email": "user@example.com",
  "org_id": "org_01h2...",
  "roles": ["admin"]
}

Standard claims.

sub, iss, aud, exp, iat — exactly where RFC 7519 says they should be. No proprietary wrappers.

Standard algorithms.

RS256 and ES256. Verified by jsonwebtoken, PyJWT, golang-jwt, or any spec-compliant JWT library.

Zero migration overhead.

Change your OIDC issuer URL. Your token-validation middleware doesn't change — not a single line.

Standard claims. Standard algorithms (RS256, ES256). Verified by any JWT library.

Start in minutes, not days.

Full API reference, SDK quickstarts, and a local dev setup guide are in the docs. Or start a free trial and have auth running before lunch.

Read the docs → Start free trial