One engine.
Eight ways in.

Authkestra orchestrates passkeys, OAuth2, TOTP, device flow and more behind a single Rust engine — chain the strategies you need, and a flow that doesn't hold together simply won't compile.

One engine, dispatched at compile time

Every request lands on the same Engine. It hands off to whichever strategy you configured — a passkey, an authenticator code, an OAuth2 provider, a device flow — verifies the credential, mints a session or token, and returns the result. Below, the diagram cycles through all four so you can see one engine carry every route, and the panel beside it shows the code that registers whichever strategy is active. Three of them are the same builder; the device flow is its own object, because there is no browser session to hang it off.

  • Passkey
  • Authenticator code
  • OAuth2
  • Device flow

Request → Engine → strategy → verified → minted → returned

let engine = Authkestra::builder()    .provider(OAuth2Flow::new(github_provider))    .session_store(session_store)    .build();

Why Authkestra

Compile-time safety

The typestate builder pattern turns a misconfigured engine into a compiler error, not a 2am runtime surprise.

Stateless OAuth

State and nonce live in encrypted cookies, never your database — so the engine scales horizontally without a shared session store.

Flexible chaining

Token, session, basic, and custom strategies chain together in the engine, so a complex flow is composed, not bolted on.

Framework & database agnostic

The engine is pure Rust logic. Axum and Actix are isolated adapters, and storage is a trait you implement — no schema is ever assumed.

Eleven ways to prove who someone is

Each one is a strategy you hand to the same engine. Mix them, chain them, or ship just one — the shape of your code doesn't change.

Authkestra vs. the world

In the Rust ecosystem you generally choose between a standalone identity provider and a library you embed. Authkestra sits in between: a modular identity engine, embedded in your binary, that plays all three OAuth2/OIDC roles — provider, client, and resource server — in one crate. Here is how it compares to a well-scoped embedded library and to the standalone servers, both of which are good at what they set out to do.

Feature comparison between Authkestra, oauth2-passkey, and standalone servers Rauthy and Kanidm
FeatureAuthkestraoauth2-passkeyRauthy / Kanidm
CategoryEmbedded identity engineEmbedded auth libraryStandalone IdP server
OAuth2 / OIDC roleProvider, client, and resource server — one crateRelying party onlyFull provider support
Resource serverNative — DPoP (RFC 9449) & mTLS (RFC 8705) bindingNot offeredAPI validation
Configuration safetyStrict — typestate builderNot documentedN/A — external config
State managementStateless, encrypted cookiesStateful — Redis or in-memoryStateful, dedicated DB
Data architectureAgnostic, trait-based — any DBSQLite / PostgreSQL built in100% yours
Passwordless methods5 — passkeys, TOTP, magic link, email/SMS OTP, recovery codesPasskeys (WebAuthn)Passkeys, plus MFA
Fresh proof to enrol a factorRequired — closes the session-hijack-then-enrol gapNot documentedNot documented
Device signaturesBuilt in — proof-of-possession + attestationNot offeredNot offered
Bot / abuse protectionCAPTCHA — Turnstile, hCaptcha, reCAPTCHANot offeredRate-limit & IP-block (Rauthy)

vs. oauth2-passkey

A clean, framework-agnostic core for signing users in with Google-style OAuth2 and passkeys, backed by its own Redis/SQL session store. It's a relying party, not a provider — there's no OP to issue tokens for your own other services, and no resource-server side to validate them. Authkestra plays all three roles from one crate, with the same passkey ceremony plus four more passwordless methods alongside it.

vs. Rauthy & Kanidm

Both are excellent, fast standalone identity servers — the right call when you want a dedicated IdP microservice, and both take security at least as seriously as Authkestra does. Authkestra gives you the same OP capability without the extra service to deploy, the network hop, or the database to back up — plus a resource-server SDK and an OIDC client for your own app's other logins, which a standalone IdP doesn't hand you.

Working GitHub login, four lines in

Add the facade crate with the features you need, then build the engine. The typestate builder only lets you call .build() once every prerequisite it needs is actually in place.

Read the full quickstart guide
Cargo.toml
authkestra = { version = "0.13", features = ["axum", "memory", "github"] }
src/main.rs
let github_provider = GithubProvider::new(client_id, client_secret, redirect_uri);let session_store: Arc<dyn SessionStore> = Arc::new(MemoryStore::default()); let auth_engine = Authkestra::builder()    .provider(OAuth2Flow::new(github_provider))    .session_store(session_store)    .build();