Skip to content

Product documentation

Thoryn — The Sovereign Identity Platform

A multi-tenant SaaS CIAM and identity-broker platform, available as a managed sovereign service or self-managed. Product white paper.

Thoryn — The Sovereign Identity Platform

Draft v1 — the flagship narrative for the fresh documentation program. Every claim below is grounded in the sources above and marked shipped vs. roadmap. Sections carry their own source anchors; deep detail links to the reference docs and ADRs rather than being restated here.

1. Executive summary

Thoryn is a multi-tenant SaaS platform for customer and workforce identity — an OAuth 2.0 / OpenID Connect authorization hub that brokers sign-in across a tenant's own users and any external identity provider, issues standards-compliant tokens, and governs access with role- and relationship-based authorization.

Two things make it distinctive:

  • It is sovereign. Thoryn runs as an EU-operated managed service, and the same product can be self-managed by the customer for full data-residency and air-gap control. Delivery is dual and co-equal — you are never locked into someone else's cloud.
  • The hub owns no user data. Thoryn is a broker: it issues tokens and moves claims, but user profiles, credentials, and organisation data live with the identity source. This is a deliberate architecture that keeps the trust surface small and the tenant boundary crisp.

It is a credible, sovereign alternative to Auth0, Okta Customer Identity, Microsoft Entra External ID, WorkOS, and Amazon Cognito — built on the same open standards, without the US-hyperscaler dependency.

2. Positioning

Who it is for. SaaS builders who need customer identity (CIAM) and B2B SSO; enterprises consolidating workforce access; and regulated or public-sector organisations for whom data sovereignty is a procurement requirement, not a nice-to-have.

The wedge — sovereign, and yours. The incumbent platforms are excellent and US-hosted. For a growing set of European buyers — public sector, finance, healthcare, defence-adjacent — that hosting is disqualifying (Schrems II, sector procurement rules, "buy European" mandates). Thoryn offers the same protocol surface and developer experience with EU-sovereign operation or self-hosting. You choose where your identity layer runs.

What it is not. Thoryn is a Hub identity product. It is not a verifiable-credentials or digital-wallet platform — that surface was deliberately separated out. The Hub does one thing: broker and govern identity, well.

Sources: CLAUDE.md, adrs/2026-07-01-hub-product-agnostic-platform.md.

3. Product overview — the identity-broker thesis

A traditional identity product stores your users and authenticates them. Thoryn brokers instead:

Relying party (your app)
    │  OAuth 2.0 / OIDC
    ▼
Thoryn Authorization Hub          ← tokens, claims, protocol only — no user data
    │  PAR + OIDC (RFC 9126)
    ▼
Federation member                 ← owns the identity; one concern each
    ├── Thoryn Identity Service    ← Thoryn-managed users (passwords, passkeys, MFA…)
    └── Your enterprise IdP        ← Entra ID / Okta / Google Workspace / any OIDC provider

The hub speaks OAuth/OIDC to your application and federation protocols to the identity source. It mints the tokens, enforces the policy, and carries the claims — but it never becomes the system of record for a person. If a feature would require the hub to store a user table, that logic belongs in a federation member instead. This is enforced, not aspirational: the hub codebase contains no User or Organisation entities.

The benefit is a small, auditable trust surface and a clean multi-tenant boundary — the two properties a security reviewer cares about most.

Sources: servers/authorization-hub/, servers/federation-members/identity-service/, CLAUDE.md (identity-broker pattern).

4. Architecture

4.1 The four planes

  • Broker plane (authorization-hub) — the OAuth 2.0 / OIDC engine (Spring Authorization Server 7): authorize, PAR, token, revoke, introspect, userinfo, device-grant, DCR, logout, federation.
  • Identity plane (federation-members/*) — the identity sources: Thoryn's own Identity Service, plus the tenant's own IdP attached as a federation member (Entra ID, Okta, Google Workspace, or any conformant OIDC provider).
  • Customer plane (product-api + api-gateway) — the public, self-service management API and its ingress: tenant configuration, OAuth-client registration, federation management, RBAC/FGA, audit, compliance.
  • Operator plane (admin/**) — Thoryn-internal cross-tenant operations, VPN-gated and separate. For self-managed deployments this is the customer's own operator surface.

4.2 Multi-tenancy and the per-tenant issuer model

Thoryn is multi-tenant to the core: each tenant is its own OIDC issuer (https://{slug}.hub.<domain>, signed by a tenant-scoped key). A tnt claim minted at the hub rides every token and is re-checked in every downstream service; cross-tenant access returns 404, never 403 (no existence leak). The trusted-issuer allowlist is an explicit SSRF boundary — an iss is honoured only if it is a known, non-suspended tenant, and per-tenant key material is fetched from a fixed in-cluster service with only the Host header varying, never an attacker-influenced URL.

This is what lets Thoryn host thousands of tenants on one deployment while giving each the cryptographic isolation of a dedicated issuer.

Sources: adrs/2026-06-08-multi-issuer-customer-plane-token-validation.md, core/lib/common/.../security/TrustedTenantIssuers*, servers/authorization-hub/.../tenancy/.

5. Standards & protocol compliance

Thoryn is built on open standards — the same ones the incumbents implement, so your SDKs and integrations port directly.

CapabilityStandard
Authorization frameworkOAuth 2.0 (RFC 6749), OAuth 2.1 posture
OIDCOpenID Connect Core 1.0
PKCERFC 7636 (enforced)
Pushed Authorization RequestsRFC 9126 (PAR-first authorize)
Device Authorization GrantRFC 8628
Token Revocation / IntrospectionRFC 7009 / RFC 7662
Bearer / DPoP / mTLS-bound tokensRFC 6750 / 9449 / 8705
Token ExchangeRFC 8693
Rich Authorization RequestsRFC 9396
JWT access-token profileRFC 9068
Dynamic Client RegistrationRFC 7591 / 7592
Step-up authenticationRFC 9470
FAPIFAPI 1.0 / 2.0 client profiles
ProvisioningSCIM 2.0 (inbound + outbound)

A generated standards conformance matrix in the reference docs tracks the exact profile and status of each. Tokens are signed ES256 by a Vault/OpenBao Transit key — the signing key never leaves the secrets backend.

Sources: servers/authorization-hub/ endpoints, core/lib/fapi, core/starters/fapi, adrs/2026-04-26-jwt-signing-strategy.md.

6. Authentication

Through the Thoryn Identity Service (or any federated source), tenants get a modern authentication stack:

  • Passwordless-first: passkeys / WebAuthn (FIDO2), magic-link, and OATH TOTP/HOTP (including hardware tokens).
  • Passwords with per-tenant strength policy, breached-password checks, and per-account lockout.
  • Adaptive / risk-based auth: impossible-travel and geo-velocity detection, new-country notification, and risk signals that can drive step-up (RFC 9470) and LoA/ACR enforcement.
  • Account lifecycle: email verification, password reset, self-service unlock, MFA recovery codes, active-session management and revocation.

Sources: servers/federation-members/identity-service/ (passkeys/, mfa/oath/, magiclink/, risk/, lockout/, recovery/), core/lib/geoip, core/lib/sas/step-up.

7. Federation & connectors

A federation member is an identity source a tenant attaches. Provider behaviour is dispatched through a FederationProvider interface — new providers are new implementations, never if (provider == "X") branches — and per-tenant credentials are Vault-envelope-encrypted, never held in JVM heap across requests.

  • Self-service provider types: Microsoft Entra ID (entra-id), Okta (okta), Google Workspace (google), and a generic OIDC provider (oidc) covering any conformant OpenID Connect IdP. These four are what a tenant admin can attach through the federation-member API and the console wizard; the same set is enforced in product-api, in the database CHECK constraints, and by the registry's implementations.
  • Domain-based routing: email-domain → tenant → connection, with just-in-time membership.

servers/federation-members/ additionally holds standalone connector applications (JumpCloud, OneLogin, Apple, GitHub, LinkedIn, ADFS, PingFederate, a SAML 2.0 member, and LDAP / ERP connectors). These present themselves to the hub as generic OIDC providers and attach through an operator-managed path rather than the self-service API — they are source-level connectors, not a shipped self-service capability. See Federation runtime for the boundary.

Sources: servers/product-api/.../federation/FederationMemberService.kt, servers/authorization-hub/.../federation/, servers/federation-members/*, adrs/2026-05-20-multi-provider-federation-runtime.md.

8. Authorization

Thoryn ships two composable authorization models:

  • RBAC — per-tenant roles and permissions, resolved into an effective permission set and (optionally) minted into the token as a coarse claim. The right tool for "what plan / role is this user."
  • FGA (fine-grained / relationship-based authorization) — a Zanzibar-style engine: relationship tuples (object#relation@subject), an immutable authorization model, and a bounded-depth Check API that answers "can this subject do this to this object" at request time. It composes with RBAC, is never minted into a token (resolved live, fail-closed), and imports OpenFGA / Auth0-FGA models and tuples so you can migrate without rewriting your model.

Permissions ride as OAuth scopes under a tenant: namespace; operator scopes live under a separate admin: namespace that structurally cannot reach the customer plane.

Sources: servers/product-api/.../rbac, servers/product-api/.../fga, adrs/2026-07-01-rbac-authorization-model.md, adrs/2026-07-15-fine-grained-authorization-fga.md.

9. The customer plane — self-service by design

Everything a tenant configures, they configure themselves — this is what makes Thoryn a product, not a professional-services engagement.

  • Console (web) and CLI (thoryn) drive the same public product API through the API gateway.
  • Register and rotate OAuth clients (with a graceful 24-hour secret-overlap window), attach federation members, define RBAC roles / FGA models, set security and login policy, brand the hosted login page, manage users and invitations, and read a tamper-evident audit trail.
  • The API is a first-class contract: RFC 9457 problem-details, camelCase, cursor pagination, idempotency keys, a generated OpenAPI spec (drift-checked in CI), and a clean /api/v1/** surface with the tenant taken from the token, never the URL path.

Sources: servers/product-api/, servers/api-gateway/, docs/api/product-api.openapi.yaml, adrs/2026-04-25-customer-plane-product-api.md, adrs/2026-07-01-api-platform-strategy.md.

10. CIAM & B2B

  • User management — CRUD, metadata bags, bulk import (sync + async jobs), invitations, lifecycle (JML) workflows.
  • SCIM 2.0 — inbound provisioning (Entra, Okta) and outbound push, with per-connection attribute mapping.
  • Per-tenant experience — hosted-login branding, per-tenant and per-locale email templates, login-page i18n, login analytics.
  • B2B organizations — organisations as tenant-scoped sub-entities, org-scoped roles, per-organisation SSO connections, and email-domain routing with just-in-time membership (on the org's SSO connection or a verified email domain), plus organisation invitations. Managed through the product API at /api/v1/organizations.

Sources: servers/federation-members/identity-service/ (users, scim, invitations, emailtemplates, analytics), servers/product-api/.../organizations (org CRUD, connections, domains, member roles, JIT membership), adrs/2026-07-15-b2b-organizations.md, adrs/2026-07-16-b2b-organizations-org-sso-and-login-gate.md.

11. Extensibility

  • Actions / Hooks — a programmable auth pipeline configured through the product API (/api/v1/hooks): inline stages that can modify or veto a token or a registration, and async event stages, delivered as signed webhooks — HMAC or Ed25519 detached-JWS — with per-stage fail-open/closed policy, delivery-health reporting, and graceful signing-key rotation.
  • Claims enrichment webhooks — per-client token-issuance webhooks that add claims, SSRF-guarded and signed; delivered as the pipeline's inline token.pre-issuance stage.
  • Federation-provider plugins — the FederationProvider extension point.
  • OpenFGA import — bring an existing authorization model and tuple export.

Sources: servers/product-api/.../hooks, servers/authorization-hub/.../webhook/, adrs/2026-07-15-actions-hooks-pipeline.md, adrs/2026-07-20-asymmetric-hook-signing-ed25519.md, servers/product-api/.../fga.

12. Security & trust model

Security is the product. The highlights a reviewer will want:

  • Signing in the secrets backend, not the JVM. All token and audit signing is ES256 via Vault/OpenBao Transit; keys never leave it. Per-tenant cryptographic identifiers are version-prefixed so a key can be rotated without breaking historical rows.
  • Tenant isolation invariants. tnt-claim enforcement everywhere; cross-tenant → 404; the trusted-issuer allowlist as an explicit SSRF boundary.
  • Outbound-SSRF containment. Every outbound call to a tenant-influenced URL passes through a guard that rejects private / loopback / link-local / metadata addresses.
  • Token security. Refresh-token replay/family-revocation detection, fingerprint binding, atomic single-use authorization codes.
  • Error hygiene. One RFC 9457 error shape platform-wide; detail strings are sanitised by construction — no tenant ids or token contents leak.
  • Hardened by CI. A suite of build-time guards enforces these invariants (algorithm allow-lists, cookie attributes, no host-header-derived URLs, no unbounded blocking calls, no unsafe deserialization) so a regression can't merge.
  • Privacy & compliance. GDPR data export (Art. 15) and erasure (Art. 17), per-tenant retention windows, a tamper-evident hash-chained audit trail, and NIS2 incident logging.

Sources: core/lib/signing, core/lib/common/.../security (OutboundUrlGuard, TrustedTenantIssuers), servers/authorization-hub/.../{logout,authorization}, scripts/check-*.sh, adrs/2026-05-09-verifiable-audit-chain.md.

13. Delivery models

The same product, two ways — this is a first-class choice, not a footnote.

Managed (sovereign SaaS)Self-managed
Runs whereEU-operated Thoryn cloudYour Kubernetes
You operateNothing — Thoryn runs itThe full stack, via Helm
You configureTenants, clients, policy (self-service)Same, plus infra
Best forFast start, sovereign hostingAir-gap, full residency control, dedicated

Both run the identical artefacts. Thoryn's operational discipline is the same artefact a self-managing customer runs: the entire deployed state is rebuildable from git with zero manual steps — Helm charts for infrastructure, Flyway migrations for schema, config as code. Secrets are OpenBao with auto-unseal; schema drift recovery is forward-patch-only (never destructive); readiness is tiered so a cold-start dependency blip can't crash-loop a healthy pod; and a Tier-3 synthetic monitor exercises real OAuth flows continuously.

That "rebuildable from git" property is simultaneously how Thoryn runs the managed service reliably and the thing you run yourself — which is why it earns first-class billing here.

Sources: deploy/helm/, CLAUDE.md (reproducible deployments), adrs/2026-06-07-vault-to-openbao.md, servers/synthetic-monitor/.

14. Representative use cases

  • B2B SaaS SSO — let your customers bring their own OIDC IdP (Entra ID, Okta, Google Workspace, or any conformant provider) and manage their users, with org-scoped roles.
  • Customer identity (CIAM) — passwordless sign-in, social/enterprise federation, and fine-grained authorization for a consumer or prosumer app.
  • Workforce access consolidation — one broker in front of many enterprise IdPs, with step-up and adaptive risk.
  • Sovereign / regulated deployment — the self-managed model for an organisation that cannot use a US-hosted identity provider.
  • Migration from Auth0 / Okta — standards-compatible tokens, SCIM, and OpenFGA/Auth0 model import to move without a rewrite.

15. Key architecture decisions

The reasoning behind the design lives in the Architecture Decision Records. The load-bearing ones: the identity-broker / product-agnostic hub, the customer-plane boundary, multi-issuer token validation, the JWT signing strategy, the multi-provider federation runtime, the RBAC and FGA authorization models, and the OpenBao secrets cutover. The product/architecture guide and the ADR index carry the detail.

16. Roadmap

Clearly separated from shipped capability. Per-tenant test / sandbox mode — a Stripe-style livemode split where a tenant's test objects are segregated from its live objects by the credential presented, with a distinct per-tenant test signing key and test issuer. The machinery is built, but the capability is not yet generally available: the resource-server opt-in (trustTestIssuers) stays fail-safe-off pending the identity data-plane segregation, so test tokens are inert end-to-end today (see the security dossier's flip-readiness assessment). Also in build: generated SDKs from the OpenAPI spec, and the continued unification of the client-management surface. These are designed (ADRs merged) and in build; they are not described above as if they exist today.

17. Where to go next

  • Architecture guideproduct/architecture
  • Security & compliance dossiersecurity/
  • API reference (generated) — reference/api
  • Get startedget-started/