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.
OAuth 2.0
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.
// 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!, });
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}
# 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.
{ "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.