From 2eadb54724e2ba96806e285cfa977be76f2b4e54 Mon Sep 17 00:00:00 2001 From: Brandon Corbett Date: Sun, 1 Nov 2026 21:09:28 -0500 Subject: [PATCH 1/2] docs(compare): reflect the v0.21 OpenID Provider on comparison pages The Auth0, Keycloak, Cognito and Better Auth pages still said Seamless Auth is not an OpenID Provider and issues no machine-to-machine tokens. That has been false since v0.21. Describe the optional provider service, state that it is off by default and not OpenID certified, and keep the incumbent ahead where certification or maturity is the requirement. Seamless Auth details rechecked at API v0.21.1. --- src/content/docs/compare/auth0.mdx | 34 +++++++++++++-------- src/content/docs/compare/better-auth.mdx | 15 ++++++---- src/content/docs/compare/cognito.mdx | 35 ++++++++++++++-------- src/content/docs/compare/keycloak.mdx | 38 ++++++++++++++---------- 4 files changed, 77 insertions(+), 45 deletions(-) diff --git a/src/content/docs/compare/auth0.mdx b/src/content/docs/compare/auth0.mdx index b3a910f..62d72f4 100644 --- a/src/content/docs/compare/auth0.mdx +++ b/src/content/docs/compare/auth0.mdx @@ -18,7 +18,7 @@ on the Seamless Auth managed service. It does much less than Auth0, on purpose. This page is for an engineer or technical lead deciding whether to move off Auth0, or whether to start on it. Every Auth0 detail links to Auth0's or Okta's own docs or pricing page, and the [Sources](#sources) section gives the date each one was checked. Seamless Auth details were checked -against the source repositories. Prices, plan contents, and feature limits change, so confirm them +against the source repositories at Seamless Auth API v0.21.1 on 2026-11-01. Prices, plan contents, and feature limits change, so confirm them on [auth0.com/pricing](https://auth0.com/pricing) before you decide. --- @@ -29,11 +29,12 @@ on [auth0.com/pricing](https://auth0.com/pricing) before you decide. OpenID Connect, AD/LDAP, ADFS, Microsoft Entra ID, Google Workspace, and other enterprise connections, which can be enabled per Organization, and inbound SCIM on selected enterprise connections. Seamless Auth has no SAML and no SCIM. -- **You need an identity provider for other applications.** Auth0 is an OAuth 2.0 and OpenID Connect - authorization server: it issues tokens for your APIs, supports the client credentials flow for - machine-to-machine access, and is a certified FAPI OpenID Provider. Seamless Auth signs users in to - your application only. It is not an OpenID Connect provider for third-party clients and issues no - machine-to-machine tokens. +- **You need a certified or long-proven identity provider for other applications.** Auth0 is an + OAuth 2.0 and OpenID Connect authorization server: it issues tokens for your APIs, supports the + client credentials flow for machine-to-machine access, and is a certified FAPI OpenID Provider. + Since v0.21, Seamless Auth also ships an OpenID Provider: a separate service, off by default, with + the authorization code flow and `S256` PKCE, client credentials, the device grant for first-party + apps, and JWT access tokens for your APIs. It is new (provider 0.1.0) and not OpenID certified. - **You need password sign-in.** Auth0 supports passwords in database connections. Seamless Auth has no password flow, by design. - **You want to run custom code inside the login flow.** Auth0 Actions are Node.js functions on @@ -96,7 +97,7 @@ page. | Social and OIDC login | Yes, instance-wide; CLI presets for Google, GitHub, Microsoft (Entra ID), GitLab | Yes, social and enterprise connections | | SAML enterprise SSO | No | Yes, as an enterprise connection. 1 on Free, 3 on B2B Essentials, 5 on B2B Professional, extra connections a paid add-on; the B2C feature table lists none on Essentials or Professional | | SCIM provisioning | No | Inbound SCIM on SAML, OIDC, Okta Workforce, and Entra ID connections; needs a plan with enterprise connections | -| Acts as an OAuth/OIDC provider, machine-to-machine tokens | No | Yes | +| Acts as an OAuth/OIDC provider, machine-to-machine tokens | Yes, since v0.21, through the separate OpenID Provider service (off by default): authorization code with PKCE, client credentials, device grant (first-party), RFC 9068 access tokens; not OpenID certified | Yes; certified FAPI OpenID Provider | | Organizations | Yes: memberships, per-organization roles and scopes, active organization on the session | Yes: members, roles, invitations, per-organization connections and branding; 5 on Free, 10 on B2C paid plans, unlimited (subject to system limits) on B2B paid plans | | Extensibility | Logic in your own backend, behind the server adapter | Actions (Node.js) on login, registration, password, and machine-to-machine triggers; 5 on Free up to 30 on Enterprise | | Prebuilt UI | Built-in auth routes (`AuthRoutes` in React; equivalents in Angular, Vue, Svelte), or headless | Universal Login on Auth0's authorization server, Classic Login, and embedded login | @@ -158,8 +159,13 @@ apps use bearer tokens in the platform keystore). Your backend verifies sessions auth API's JWKS. Authorization stays in your own code. See [What Is Seamless Auth?](/start/overview#how-the-pieces-connect). +Since v0.21 you can also run the optional [OpenID Provider](/build/openid-provider), a separate +service in front of the auth API. Apps that speak OpenID Connect redirect to its hosted login pages +and receive tokens from it, the way they would from Auth0, with no Seamless SDK. + The practical consequence: Auth0 is a central identity provider that many apps and APIs can trust; -Seamless Auth is sign-in for your application, and the sign-in pages are yours. +Seamless Auth is sign-in for your application by default, with sign-in pages that are yours, and +becomes a provider for other apps only when you turn on its OpenID Provider. --- @@ -172,10 +178,10 @@ today, stay on Auth0 or choose another product. Connect providers are configured instance-wide, not per customer organization. - **You provision users from a customer's directory with SCIM.** Seamless Auth has no SCIM. Bulk changes go through the CSV import. -- **Other applications or services use Auth0 as their identity provider.** Seamless Auth is not an - OpenID Connect provider and does not issue tokens to third-party apps or machine-to-machine - clients. Anything that logs in through Auth0 today, other than your own application, needs another - home. +- **Other applications or services need a certified identity provider.** Seamless Auth's OpenID + Provider (v0.21, off by default) can sign other OpenID Connect apps in and issue client credentials + tokens, but it is new and not OpenID certified, and it has nothing like Actions to shape their + tokens. Test each app that logs in through Auth0 today against it before you move that app. - **Your users sign in with passwords and you cannot change that.** There is no password flow, and no password hashes are imported. - **You depend on Actions to shape tokens or gate login.** There is no hook system; you move that @@ -227,7 +233,7 @@ Auth0 and Okta details, each checked on the date shown: - [Universal Login](https://auth0.com/docs/authenticate/login/auth0-universal-login), checked 2026-10-20: login on Auth0's authorization server - [Okta customer identity product page](https://www.okta.com/products/customer-identity/), checked 2026-10-20: redirects to auth0.com -Seamless Auth details: +Seamless Auth details (Seamless Auth API v0.21.1, checked 2026-11-01): - [What Is Seamless Auth?](/start/overview), including [When Seamless Auth Is Not The Right Choice](/start/overview#when-seamless-auth-is-not-the-right-choice) - [Migrating Off Auth0](/operate/migrate-from-auth0), including [What You Give Up Or Must Plan For](/operate/migrate-from-auth0#what-you-give-up-or-must-plan-for) @@ -235,5 +241,7 @@ Seamless Auth details: - [Environment Variables](/reference/environment-variables) (`LOGIN_METHODS`, SMS providers) - [How To Use Organizations And Memberships](/build/organizations-memberships) - [OAuth Login](/build/oauth-login) +- [OpenID Provider](/build/openid-provider) +- [v0.21 Release Notes](/reference/release-v0-21) - [Auth Events and Auditing](/understand/authevents) - Source: [fells-code on GitHub](https://github.com/fells-code) diff --git a/src/content/docs/compare/better-auth.mdx b/src/content/docs/compare/better-auth.mdx index a38c4df..cb40e62 100644 --- a/src/content/docs/compare/better-auth.mdx +++ b/src/content/docs/compare/better-auth.mdx @@ -16,7 +16,8 @@ languages. This page is for an engineer choosing between the two. Better Auth details were checked against its official docs, pricing page, and GitHub repository as of October 2026, and each one links to its -source at the bottom. Seamless Auth details were checked against the source repositories. +source at the bottom. Seamless Auth details were checked against the source repositories at +Seamless Auth API v0.21.1 on 2026-11-01. --- @@ -30,8 +31,10 @@ source at the bottom. Seamless Auth details were checked against the source repo - **You need SAML or SCIM.** Better Auth has an SSO plugin (`@better-auth/sso`) supporting SAML 2.0 and OIDC with per-organization providers, and a SCIM 2.0 plugin (`@better-auth/scim`). Seamless Auth has neither. -- **You want your app to be an OAuth or OIDC provider for other apps.** Better Auth has an - `oauth-provider` plugin. Seamless Auth is not an authorization server for third-party clients. +- **You want your app itself to be an OAuth or OIDC provider for other apps.** Better Auth has an + `oauth-provider` plugin that runs inside your server. Seamless Auth has shipped an OpenID Provider + since v0.21, but as a separate service that is off by default, and it is new (provider 0.1.0) and + not OpenID certified. - **You want a large ecosystem and a 1.x release line.** Better Auth is on its 1.7 release line, has about 30,000 GitHub stars, and lists dozens of first-party and community plugins (payments, API keys, multi-session, anonymous users, Sign-In With Ethereum, and more). Seamless Auth is 0.x @@ -82,7 +85,7 @@ Better Auth column as of October 2026. | Social and OIDC login | Yes, instance-wide; CLI presets for Google, GitHub, Microsoft (Entra ID), GitLab | Yes, built-in social providers and a `generic-oauth` plugin | | SAML enterprise SSO | No | Yes, `@better-auth/sso` plugin | | SCIM directory sync | No | Yes, `@better-auth/scim` plugin | -| Acts as an OAuth/OIDC provider | No | Yes, `oauth-provider` plugin | +| Acts as an OAuth/OIDC provider | Yes, since v0.21, as a separate OpenID Provider service (off by default); not OpenID certified | Yes, `oauth-provider` plugin | | Organizations | Yes: memberships with per-organization roles and scopes, and an active organization on the session | Yes, `organization` plugin: roles, invitations, teams, custom access control | | Prebuilt UI | Built-in auth routes (`AuthRoutes` in React; equivalents in Angular, Vue, Svelte), or headless | No official components in the core docs; community projects such as Better Auth UI exist | | Admin dashboard | Yes, open source app you run | `admin` plugin APIs; dashboard via Better Auth Infrastructure (paid service, free Starter tier) | @@ -166,11 +169,13 @@ Better Auth details checked October 2026: - [Better Auth pricing](https://better-auth.com/pricing) - [Better Auth UI](https://better-auth-ui.com/): community UI components -Seamless Auth details: +Seamless Auth details (Seamless Auth API v0.21.1, checked 2026-11-01): - [What Is Seamless Auth?](/start/overview), including [When Seamless Auth Is Not The Right Choice](/start/overview#when-seamless-auth-is-not-the-right-choice) - [What You Give Up Or Must Plan For](/operate/migrate-from-auth0#what-you-give-up-or-must-plan-for) - [Server SDKs](/build/server-sdks) and [Next.js](/build/nextjs) - [Environment Variables](/reference/environment-variables) (`LOGIN_METHODS`, SMS providers) - [How To Use Organizations And Memberships](/build/organizations-memberships) +- [OpenID Provider](/build/openid-provider) +- [v0.21 Release Notes](/reference/release-v0-21) - Source: [fells-code on GitHub](https://github.com/fells-code) diff --git a/src/content/docs/compare/cognito.mdx b/src/content/docs/compare/cognito.mdx index 13d290c..1dcd9e6 100644 --- a/src/content/docs/compare/cognito.mdx +++ b/src/content/docs/compare/cognito.mdx @@ -19,7 +19,7 @@ Cognito, and it is not tied to AWS. This page is for an engineer or technical lead deciding whether to move off Cognito, or whether to start on it. Every Cognito detail links to an AWS page, and the [Sources](#sources) section gives the date each one was checked. Seamless Auth details were checked against the source repositories -at Seamless Auth API v0.19.3. Prices, plan contents, and feature limits change, so confirm them on +at Seamless Auth API v0.21.1 on 2026-11-01. Prices, plan contents, and feature limits change, so confirm them on [aws.amazon.com/cognito/pricing](https://aws.amazon.com/cognito/pricing/) before you decide. --- @@ -32,11 +32,13 @@ at Seamless Auth API v0.19.3. Prices, plan contents, and feature limits change, credentials and no AWS service reads its sessions natively. - **You need SAML enterprise SSO.** User pools federate with SAML 2.0 and OpenID Connect identity providers on every feature plan, as well as social providers. Seamless Auth has no SAML. -- **You need an identity provider for other applications or machine clients.** A user pool with a - domain is an OAuth 2.0 and OpenID Connect authorization server, with resource servers, custom - scopes, and machine-to-machine access tokens through the client credentials grant. Seamless Auth - signs users in to your application only. It is not an OpenID Connect provider for third-party - clients and issues no machine-to-machine tokens. +- **You need a long-proven identity provider for other applications or machine clients.** A user + pool with a domain is an OAuth 2.0 and OpenID Connect authorization server, with resource servers, + custom scopes, and machine-to-machine access tokens through the client credentials grant. Since + v0.21, Seamless Auth also ships an OpenID Provider: a separate service, off by default, with + registered resources and scopes, client credentials tokens, and the authorization code flow with + `S256` PKCE. It is new (provider 0.1.0) and not OpenID certified, and API Gateway's Cognito + authorizer does not accept its tokens. - **You need password sign-in.** Cognito supports passwords, including Secure Remote Password (SRP), and can import existing bcrypt, scrypt, Argon2id, or PBKDF2-SHA256 password hashes. Seamless Auth has no password flow, by design. @@ -97,7 +99,7 @@ pool feature plans. | Passwords | No, by design | Yes, including SRP; password hash import from CSV | | Social and OIDC login | Yes, instance-wide; CLI presets for Google, GitHub, Microsoft (Entra ID), GitLab | Yes: Google, Facebook, Login with Amazon, Sign in with Apple, and OIDC providers, on all plans | | SAML enterprise SSO | No | Yes, as a SAML 2.0 service provider, on all plans | -| Acts as an OAuth/OIDC provider, machine-to-machine tokens | No | Yes: authorization server, resource servers, custom scopes, client credentials | +| Acts as an OAuth/OIDC provider, machine-to-machine tokens | Yes, since v0.21, through the separate OpenID Provider service (off by default): resources and scopes, client credentials, authorization code with PKCE; not OpenID certified | Yes: authorization server, resource servers, custom scopes, client credentials | | Organizations | Yes: memberships, per-organization roles and scopes, active organization on the session | Groups, optionally mapped to IAM roles | | Extensibility | Logic in your own backend, behind the server adapter | Lambda triggers on sign-up, authentication, token generation, migration, and messages | | Prebuilt UI | Built-in auth routes (`AuthRoutes` in React; equivalents in Angular, Vue, Svelte), or headless | Managed login on a user pool domain (Essentials and Plus); classic hosted UI on all plans | @@ -147,9 +149,14 @@ apps use bearer tokens in the platform keystore). Your backend verifies sessions auth API's JWKS. Authorization stays in your own code. See [What Is Seamless Auth?](/start/overview#how-the-pieces-connect). +Since v0.21 you can also run the optional [OpenID Provider](/build/openid-provider), a separate +service in front of the auth API. Apps that speak OpenID Connect redirect to its hosted login pages +and receive tokens from it, with no Seamless SDK. + The practical consequence: Cognito is an identity provider wired into AWS that many apps, APIs, and -AWS services can trust; Seamless Auth is sign-in for your application, the sign-in pages are yours, -and anything AWS-side goes through your backend. +AWS services can trust; Seamless Auth is sign-in for your application by default, the sign-in pages +are yours, and anything AWS-side goes through your backend. It becomes a provider for other apps +only when you turn on its OpenID Provider. --- @@ -164,8 +171,10 @@ requirement today, stay on Cognito or choose another product. read Seamless Auth sessions. Each one needs replacing with verification in your backend. - **A customer requires SAML SSO into your app.** Seamless Auth has no SAML. Its OAuth and OpenID Connect providers are configured instance-wide, not per customer organization. -- **Other applications or machine clients use Cognito as their authorization server.** Seamless Auth - is not an OpenID Connect provider and issues no client credentials tokens. +- **Other applications or machine clients need a certified authorization server.** Seamless Auth's + OpenID Provider (v0.21, off by default) issues authorization code and client credentials tokens, + but it is new and not OpenID certified. Test each client that uses Cognito today against it before + you move that client. - **Your users sign in with passwords and you cannot change that.** There is no password flow, and no password hashes are imported. - **You depend on Lambda triggers to shape tokens or gate sign-in.** There is no hook system; you @@ -215,7 +224,7 @@ Amazon Cognito details, each checked on the date shown: - [Data protection in Amazon Cognito](https://docs.aws.amazon.com/cognito/latest/developerguide/data-protection.html), checked 2026-10-21: encryption at rest with AWS owned or customer managed keys in the user pool's Region - [Compliance validation for Amazon Cognito](https://docs.aws.amazon.com/cognito/latest/developerguide/compliance-validation.html), checked 2026-10-21: SOC, PCI, FedRAMP, HIPAA, AWS Artifact -Seamless Auth details (Seamless Auth API v0.19.3): +Seamless Auth details (Seamless Auth API v0.21.1, checked 2026-11-01): - [What Is Seamless Auth?](/start/overview), including [When Seamless Auth Is Not The Right Choice](/start/overview#when-seamless-auth-is-not-the-right-choice) - [Migrating Off Amazon Cognito](/operate/migrate-from-cognito), including [What You Give Up Or Must Plan For](/operate/migrate-from-cognito#what-you-give-up-or-must-plan-for) @@ -223,5 +232,7 @@ Seamless Auth details (Seamless Auth API v0.19.3): - [System Config Reference](/reference/system-config), including [Authenticator Policy](/reference/system-config#authenticator-policy), and [Environment Variables](/reference/environment-variables) (`LOGIN_METHODS`, SMS providers) - [How To Use Organizations And Memberships](/build/organizations-memberships) - [OAuth Login](/build/oauth-login) +- [OpenID Provider](/build/openid-provider) +- [v0.21 Release Notes](/reference/release-v0-21) - [Auth Events and Auditing](/understand/authevents) - Source: [fells-code on GitHub](https://github.com/fells-code) diff --git a/src/content/docs/compare/keycloak.mdx b/src/content/docs/compare/keycloak.mdx index 7cc0c38..425ecb0 100644 --- a/src/content/docs/compare/keycloak.mdx +++ b/src/content/docs/compare/keycloak.mdx @@ -19,7 +19,8 @@ self-hosted identity. Every Keycloak statement below links to a Keycloak-owned p the `keycloak/keycloak` GitHub repository), and the [Sources](#sources) list gives the date each page was checked. Keycloak details reflect Keycloak 26.8.1, the release listed on Keycloak's downloads page on 2026-10-20. Seamless Auth details were checked against the source repositories -at Seamless Auth API v0.19.1. Keycloak ships often, so check its release notes for anything newer. +at Seamless Auth API v0.21.1 on 2026-11-01; the [Footprint](#footprint) figures were measured at +v0.19.1. Keycloak ships often, so check its release notes for anything newer. --- @@ -31,13 +32,13 @@ at Seamless Auth API v0.19.1. Keycloak ships often, so check its release notes f Directory directories (and Kerberos) through User Federation, and offers a User Storage SPI for other user databases. Seamless Auth has no LDAP, Active Directory, or Kerberos integration; users live in its own Postgres database. -- **You need a standards-based OIDC provider today.** Keycloak is an OpenID Connect and OAuth 2.0 - provider, so any application with an OIDC relying party or SAML service provider library can sign - in through it, and one Keycloak realm can give many applications single sign-on. Seamless Auth is - not an OIDC provider: it publishes a JWKS for its own tokens, but has no authorization endpoint and - no OpenID discovery document, and its OAuth support is inbound only (signing users in with Google, - GitHub, and similar providers). Applications integrate through a Seamless Auth adapter or its - HTTP API instead. +- **You need a long-proven OIDC provider, or OIDC and SAML from one server.** Keycloak is an OpenID + Connect and OAuth 2.0 provider, so any application with an OIDC relying party or SAML service + provider library can sign in through it, and one Keycloak realm can give many applications single + sign-on. Seamless Auth has shipped an OpenID Provider since v0.21: a separate service, off by + default, with discovery, the authorization code flow with `S256` PKCE, client credentials, the + device grant for first-party apps, and hosted login and consent pages. It is new (provider 0.1.0), + not OpenID certified, and has no SAML side. - **You need SCIM provisioning.** Keycloak 26.8.0 promoted its SCIM API from preview to supported. It exposes SCIM 2.0 user and group endpoints per realm, once you turn the SCIM API on in that realm's settings. Seamless Auth has no SCIM endpoints. @@ -64,8 +65,9 @@ at Seamless Auth API v0.19.1. Keycloak ships often, so check its release notes f application, through the SDK's built-in screens (themed with `--seamless-*` CSS custom properties) or your own components on the headless client. There are no server-side templates to keep in step with each server release. -- **You want a smaller runtime.** Seamless Auth is one Node.js container plus Postgres, and the same - image serves the admin console at `/console`. See [Footprint](#footprint) for measured figures and +- **You want a smaller runtime.** Seamless Auth is one Node.js container plus Postgres (a second, + database-free container if you turn on the OpenID Provider), and the same image serves the admin + console at `/console`. See [Footprint](#footprint) for measured figures and how they compare with Keycloak's published sizing guidance. - **Your applications are built on a stack Seamless Auth has an adapter for.** Adapters exist for Node.js (Express, Fastify, Next.js), Python (FastAPI, Django), Go (`net/http`), and Rust (Axum), @@ -91,7 +93,7 @@ Keycloak column as of Keycloak 26.8.1, checked 2026-10-20. | Passwords | No, by design | Yes | | Other methods | Magic links, email OTP, SMS OTP, TOTP as a second factor and for step-up | TOTP and HOTP, recovery codes, X.509 certificates, step-up authentication, Kerberos | | Social and external OIDC login | Yes, inbound only; CLI presets for Google, GitHub, Microsoft (Entra ID), GitLab | Yes, social login and brokering to external OIDC and SAML providers | -| Acts as an OIDC / OAuth 2.0 provider | No | Yes | +| Acts as an OIDC / OAuth 2.0 provider | Yes, since v0.21, through the separate OpenID Provider service (off by default); not OpenID certified | Yes | | SAML | No | Yes, SAML 2.0 for applications and for identity brokering | | LDAP / Active Directory federation | No | Yes, plus Kerberos and a User Storage SPI | | SCIM | No | Yes, SCIM 2.0 users and groups per realm; supported since 26.8.0 (preview in 26.7.0) | @@ -217,7 +219,9 @@ browser or native app -> Postgres ``` -There is no redirect to a separate login domain. Your backend forwards auth calls with a service +By default there is no redirect to a separate login domain. If you turn on the optional +[OpenID Provider](/build/openid-provider) (v0.21), apps that speak OpenID Connect redirect to its +hosted login pages instead, as they would to Keycloak. Otherwise, your backend forwards auth calls with a service token, keeps the browser session in signed `httpOnly` cookies (native apps use bearer tokens in the platform keystore), and verifies sessions against the auth API's JWKS. See [What Is Seamless Auth?](/start/overview#how-the-pieces-connect). @@ -230,8 +234,10 @@ Keycloak's `kc.sh export` writes realms and users to JSON files and must run whi stopped. Seamless Auth imports no passwords or credentials of any kind, so a migration imports identities (email, external id, phone, roles, organization memberships) with `seamless migrate csv`, then gets each user onto a passkey through enrollment prompts and invites. Passkeys and OTP devices -registered with Keycloak do not carry over, and applications that rely on Keycloak as an OIDC or SAML -provider need a different integration, since Seamless Auth is neither. +registered with Keycloak do not carry over. Applications that rely on Keycloak as a SAML provider +need a different integration, since Seamless Auth has no SAML. Applications that use Keycloak as an +OIDC provider can be registered with the Seamless Auth OpenID Provider instead; test each one +against it first, since it is new and not OpenID certified. Follow [Migrate Users From Another Identity System](/operate/migrate-users); the [Auth0 migration guide](/operate/migrate-from-auth0) shows the full pattern for one provider. @@ -256,11 +262,13 @@ Keycloak details, each page checked on 2026-10-20: - [Importing and exporting realms](https://www.keycloak.org/server/importExport) (checked 2026-10-20): `kc.sh export`, server must not be running - [keycloak/keycloak on GitHub](https://github.com/keycloak/keycloak) (checked 2026-10-20): Apache-2.0 license -Seamless Auth details (Seamless Auth API v0.19.1): +Seamless Auth details (Seamless Auth API v0.21.1, checked 2026-11-01; footprint measured at v0.19.1): - [What Is Seamless Auth?](/start/overview), including [When Seamless Auth Is Not The Right Choice](/start/overview#when-seamless-auth-is-not-the-right-choice) - [System Config Reference](/reference/system-config) and [Environment Variables](/reference/environment-variables) - [How To Use Organizations And Memberships](/build/organizations-memberships) - [OAuth Login](/build/oauth-login) +- [OpenID Provider](/build/openid-provider) +- [v0.21 Release Notes](/reference/release-v0-21) - [Custom Auth UI](/build/custom-auth-ui) - Source: [fells-code on GitHub](https://github.com/fells-code) From 3f53eb6c182fae40db9a2baecfdc4a74a06ef49f Mon Sep 17 00:00:00 2001 From: Brandon Corbett Date: Sun, 1 Nov 2026 21:20:13 -0500 Subject: [PATCH 2/2] docs: score the OpenID Provider against RFC 9700 and refresh the compatibility matrix The RFC 9700 page still called the OpenID Provider planned for v0.21 and left every authorization server row unscored. Score each row against provider 0.1.1 with the test behind it, fix four section numbers that were off by one, and mark the state replay row met since 0.21.0 (#414). Update the compatibility matrix to the latest releases. Provider 0.2.0 speaks /oidc contract version 3 and refuses to start against auth API 0.21.1, so the matrix says which pair to run, and the provider guide pins the image to v0.1.1 instead of latest. --- src/content/docs/build/ecosystem.mdx | 27 +++++--- src/content/docs/build/openid-provider.mdx | 7 ++- src/content/docs/understand/oauth-rfc9700.mdx | 63 ++++++++++--------- 3 files changed, 58 insertions(+), 39 deletions(-) diff --git a/src/content/docs/build/ecosystem.mdx b/src/content/docs/build/ecosystem.mdx index 273333a..b380585 100644 --- a/src/content/docs/build/ecosystem.mdx +++ b/src/content/docs/build/ecosystem.mdx @@ -174,18 +174,18 @@ packages, which require Node.js 18 or later. | Package | Latest release | Declares on other Seamless packages | Other peer ranges | | --------------------------------- | -------------- | ------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------- | | `seamless-auth-api` | 0.21.1 | `@seamless-auth/types` ^0.34.0, `@seamless-auth/messaging`, `-aws`, `-twilio` ^0.3.1 | None | -| `@seamless-auth/oidc-provider` | 0.1.1 | `@seamless-auth/express` and `core` ^0.23.0, `@seamless-auth/types` ^0.34.0 | None | -| `@seamless-auth/core` | 0.23.0 | `@seamless-auth/types` ^0.34.0 | None | -| `@seamless-auth/express` | 0.23.0 | `@seamless-auth/core` ^0.23.0 | `express` >=5.0.0 | -| `@seamless-auth/fastify` | 0.14.0 | `@seamless-auth/core` ^0.23.0 | `fastify` >=5.0.0 | -| `@seamless-auth/nextjs` | 0.7.0 | `@seamless-auth/core` ^0.23.0, `@seamless-auth/types` ^0.34.0 | None | +| `@seamless-auth/oidc-provider` | 0.2.0 | `@seamless-auth/express` and `core` ^0.23.0, `@seamless-auth/types` ^0.35.0 | None | +| `@seamless-auth/core` | 0.24.0 | `@seamless-auth/types` ^0.35.0 | None | +| `@seamless-auth/express` | 0.24.0 | `@seamless-auth/core` ^0.24.0 | `express` >=5.0.0 | +| `@seamless-auth/fastify` | 0.15.0 | `@seamless-auth/core` ^0.24.0 | `fastify` >=5.0.0 | +| `@seamless-auth/nextjs` | 0.8.0 | `@seamless-auth/core` ^0.24.0, `@seamless-auth/types` ^0.35.0 | None | | `@seamless-auth/client` | 0.8.2 | `@seamless-auth/types` ^0.34.0 | None | | `@seamless-auth/react` | 0.19.2 | `@seamless-auth/client` ^0.8.2, `@seamless-auth/types` ^0.34.0 | `react` and `react-dom` 18 or 19, optional `react-router-dom` 6.4+ or 7.15.1+ | | `@seamless-auth/angular` | 0.4.1 | `@seamless-auth/client` ^0.8.1 | `@angular/core`, `common`, `router` 20, 21, or 22, and `rxjs` 7 | | `@seamless-auth/vue` | 0.3.1 | `@seamless-auth/client` ^0.8.1 | `vue` 3.5+, optional `vue-router` 4.4+ or 5 | | `@seamless-auth/svelte` | 0.3.1 | `@seamless-auth/client` ^0.8.1 | `svelte` 5, optional `@sveltejs/kit` 2.26+ or 3 | | `@seamless-auth/react-native` | 0.4.2 | `@seamless-auth/client` ^0.8.2, `@seamless-auth/types` ^0.34.0 | `react` 18 or 19 | -| `@seamless-auth/types` | 0.34.0 | None | None | +| `@seamless-auth/types` | 0.35.0 | None | None | | `@seamless-auth/messaging` | 0.3.1 | `@seamless-auth/types` ^0.34.0 | None | | `@seamless-auth/messaging-aws` | 0.3.1 | `@seamless-auth/messaging` ^0.3.1 | None | | `@seamless-auth/messaging-twilio` | 0.3.1 | `@seamless-auth/messaging` ^0.3.1 | None | @@ -199,9 +199,18 @@ How to read it: bumped and released. - `@seamless-auth/express`, `fastify`, and `nextjs` declare `@seamless-auth/core` as `workspace:^`, which pnpm rewrites at publish to a caret on the core version in the same release - (`^0.23.0` today). -- Every package that depends on `@seamless-auth/types` declares ^0.34.0, so an install of any mix - of them resolves a single copy of it. + (`^0.24.0` today). +- `@seamless-auth/types` is split across two minors. `core`, `nextjs` and `oidc-provider` declare + ^0.35.0. The auth API, `client`, `react`, `react-native`, the messaging packages, the CLI and the + dashboard still declare ^0.34.0. An app that installs packages from both groups gets two copies + of it. +- `@seamless-auth/oidc-provider` 0.2.0 still declares `@seamless-auth/express` and `core` ^0.23.0. + If you embed it in an Express app that uses `@seamless-auth/express` 0.24.0, the app gets two + copies of each. +- `@seamless-auth/oidc-provider` 0.2.0 speaks OpenID Provider contract version 3 + (`@seamless-auth/types` 0.35.0), and it refuses to start against an auth API on another version. + Auth API 0.21.1 speaks version 2, so run the provider at 0.1.1 with API 0.21.1. Move to 0.2.0 + together with the first auth API release after 0.21.1. - The messaging packages are used by `seamless-auth-api` to deliver email and SMS. Your application does not install them. - The auth API exposes an HTTP contract, not a package range. No package declares a range on diff --git a/src/content/docs/build/openid-provider.mdx b/src/content/docs/build/openid-provider.mdx index 8ce6cc7..1175f60 100644 --- a/src/content/docs/build/openid-provider.mdx +++ b/src/content/docs/build/openid-provider.mdx @@ -108,9 +108,14 @@ ceremonies on the hosted pages are checked against that list. ### 3. Run the edge ```bash -docker run -p 5314:5314 --env-file edge.env ghcr.io/fells-code/seamless-auth-oidc-provider:latest +docker run -p 5314:5314 --env-file edge.env ghcr.io/fells-code/seamless-auth-oidc-provider:v0.1.1 ``` +Pin the edge to the version that matches your API. With auth API 0.21.x, use edge `v0.1.1`. Edge +`v0.2.0`, which is also the `latest` tag, speaks a newer `/oidc/*` contract and refuses to start +against auth API 0.21.1. The [Compatibility Matrix](/build/ecosystem#compatibility-matrix) lists +the pairs. + | Variable | Required | What | | ----------------------------- | -------- | ------------------------------------------------------------------------------------------------------------ | | `SEAMLESS_API_URL` | yes | The private API, as the edge reaches it. | diff --git a/src/content/docs/understand/oauth-rfc9700.mdx b/src/content/docs/understand/oauth-rfc9700.mdx index 9645166..b5a7c0d 100644 --- a/src/content/docs/understand/oauth-rfc9700.mdx +++ b/src/content/docs/understand/oauth-rfc9700.mdx @@ -1,6 +1,6 @@ --- title: 'OAuth Client and RFC 9700' -description: 'How the Seamless Auth API, as an OAuth 2.0 and OpenID Connect client for social and enterprise sign-in, measures against the RFC 9700 OAuth 2.0 Security Best Current Practice, row by row, each linked to the code at v0.19.2.' +description: 'How Seamless Auth measures against the RFC 9700 OAuth 2.0 Security Best Current Practice, row by row: the auth API as an OAuth client for social and enterprise sign-in, and the OpenID Provider (v0.21) as an authorization server, each row linked to the code or test behind it.' sidebar: order: 6 --- @@ -11,15 +11,19 @@ import { Aside } from '@astrojs/starlight/components'; Practice. It gives recommendations for clients, for authorization servers, and for resource servers. This page checks the Seamless Auth API against the ones that apply to it today. -Today the Seamless Auth API is an OAuth **client** only. When a provider is configured (Google, -GitHub, Microsoft Entra ID, or any OAuth 2.0 or OpenID Connect provider, see -[OAuth Login](/build/oauth-login)), the API sends the user to that provider, exchanges the -authorization code, reads the profile, and then issues its own Seamless Auth session. It is not an -authorization server for other applications until the OpenID Provider planned for v0.21, so the -authorization server recommendations are listed below as "applies from v0.21", not as passes or -gaps. +Seamless Auth plays two OAuth roles: -Every code link points at the +- **Client.** When a provider is configured (Google, GitHub, Microsoft Entra ID, or any OAuth 2.0 + or OpenID Connect provider, see [OAuth Login](/build/oauth-login)), the auth API sends the user + to that provider, exchanges the authorization code, reads the profile, and then issues its own + Seamless Auth session. The [client recommendations](#client-recommendations) cover this. +- **Authorization server.** Since v0.21, the optional [OpenID Provider](/build/openid-provider) + (`seamless-auth-oidc-provider`, off by default) signs other applications in and issues tokens + for your APIs. The [authorization server recommendations](#authorization-server-recommendations) + cover this. + +The client table was written against API v0.19.2. Rows that have changed since then say so. Every +client code link points at the [v0.19.2](https://github.com/fells-code/seamless-auth-api/tree/v0.19.2) tag of the API. The flow lives in [`oauthService.ts`](https://github.com/fells-code/seamless-auth-api/blob/v0.19.2/src/services/oauthService.ts), [`oauth.ts`](https://github.com/fells-code/seamless-auth-api/blob/v0.19.2/src/controllers/oauth.ts) @@ -48,13 +52,13 @@ Status values: | [4.11](https://www.rfc-editor.org/rfc/rfc9700#section-4.11) | Do not expose an open redirector | **Meets** | A requested `redirectUri` must exactly match the provider's `redirectUris`, or, when a provider lists none, share an origin with a configured origin ([`allowedRedirect`](https://github.com/fells-code/seamless-auth-api/blob/v0.19.2/src/lib/redirectAllowlist.ts#L40-L48)). `returnTo` must share an origin with a configured origin ([`allowedReturnTo`](https://github.com/fells-code/seamless-auth-api/blob/v0.19.2/src/controllers/oauth.ts#L37-L46)), and is read back from the signed state at the callback rather than from the callback request ([`finishOAuthLogin`](https://github.com/fells-code/seamless-auth-api/blob/v0.19.2/src/controllers/oauth.ts#L178-L184)). Configure exact `redirectUris` in production. | | [4.6](https://www.rfc-editor.org/rfc/rfc9700#section-4.6) | Validate ID tokens, so a token issued for another client or sign-in is not accepted | **Meets** | An OpenID Connect provider's ID token is checked for signature against its JWKS, issuer, audience (this client), expiry, issued-at, subject, `azp` when there are several audiences, and the nonce. Only asymmetric algorithms are accepted, so `none` and shared-key algorithms are refused ([`verifyOAuthIdToken`](https://github.com/fells-code/seamless-auth-api/blob/v0.19.2/src/services/oauthService.ts#L499-L555)). | | [4.9](https://www.rfc-editor.org/rfc/rfc9700#section-4.9) | Send an access token only to the resource it is meant for, in a header rather than a URL | **Meets** | The provider access token is sent only to the provider's configured `userInfoUrl` (and, for GitHub, the email list on the same origin), in an `Authorization: Bearer` header ([`fetchOAuthProfile`](https://github.com/fells-code/seamless-auth-api/blob/v0.19.2/src/services/oauthService.ts#L637-L664)). An OpenID Connect provider's profile comes from the verified ID token and the access token is not used at all. | -| [4.13](https://www.rfc-editor.org/rfc/rfc9700#section-4.13) | Protect refresh tokens | **Not used** | The API reads only `access_token` and `id_token` from the provider's token response ([`exchangeOAuthTokens`](https://github.com/fells-code/seamless-auth-api/blob/v0.19.2/src/services/oauthService.ts#L468-L480)). A provider refresh token is never kept, and the provider access token is used once during the callback, then dropped. Neither is stored, logged, or returned to the client. | +| [4.14](https://www.rfc-editor.org/rfc/rfc9700#section-4.14) | Protect refresh tokens | **Not used** | The API reads only `access_token` and `id_token` from the provider's token response ([`exchangeOAuthTokens`](https://github.com/fells-code/seamless-auth-api/blob/v0.19.2/src/services/oauthService.ts#L468-L480)). A provider refresh token is never kept, and the provider access token is used once during the callback, then dropped. Neither is stored, logged, or returned to the client. | | [2.2](https://www.rfc-editor.org/rfc/rfc9700#section-2.2) | Use sender-constrained access tokens (mTLS or DPoP) | **Not used** | Provider access tokens are plain bearer tokens. Each is used once, server to server, within the callback, which leaves little window for replay. DPoP and mTLS are not supported. | | [2.3](https://www.rfc-editor.org/rfc/rfc9700#section-2.3) | Request only the privileges the client needs | **Operator setting** | The scopes sent are the provider's configured `scopes` ([`buildOAuthAuthorizationUrl`](https://github.com/fells-code/seamless-auth-api/blob/v0.19.2/src/services/oauthService.ts#L401-L403)). The API needs a subject and a verified email, so `openid email` (or the provider's equivalent, such as `user:email` on GitHub) is enough. | | [2.5](https://www.rfc-editor.org/rfc/rfc9700#section-2.5) | Authenticate the client, preferably with an asymmetric method (mTLS or `private_key_jwt`) | **Partial** | The client authenticates with `client_secret_post` ([`exchangeOAuthTokens`](https://github.com/fells-code/seamless-auth-api/blob/v0.19.2/src/services/oauthService.ts#L437-L449)). The secret is read from the environment variable the provider's `clientSecretEnv` names, never stored in `system_config`, and never returned by the API. Asymmetric client authentication is not supported. | | [4.2](https://www.rfc-editor.org/rfc/rfc9700#section-4.2), [4.3](https://www.rfc-editor.org/rfc/rfc9700#section-4.3) | Keep the authorization code and state out of `Referer` headers and browser history | **Application** | The provider redirects to the application's own callback page, which then posts `code` and `state` to its backend. That page is not served by the API, so this is up to the application: load no third-party content on it and leave the URL once the sign-in is finished. The code is single use at the provider and, with PKCE, useless without the verifier only the API holds. | | [4.1](https://www.rfc-editor.org/rfc/rfc9700#section-4.1) | Use TLS for every endpoint of the flow | **Operator setting** | Provider `authorizationUrl`, `tokenUrl`, `userInfoUrl`, `issuer` and `jwksUri` must be URLs, but `http` is not refused ([provider schema](https://github.com/fells-code/seamless-auth-types/blob/v0.29.0/src/schemas/systemConfig/schema.ts#L55-L76)). Configure `https` endpoints, which every public provider uses. | -| [4.7](https://www.rfc-editor.org/rfc/rfc9700#section-4.7) | Treat a `state` as single use | **Partial**, tracked in [#414](https://github.com/fells-code/seamless-auth-api/issues/414) | A consumed state is remembered for ten minutes, but only by the API instance that consumed it ([`consumeOAuthState`](https://github.com/fells-code/seamless-auth-api/blob/v0.19.2/src/services/oauthService.ts#L322-L346)). With several instances, another instance could accept a replayed callback inside that window. The state is still signed and expiring, and the provider's code is single use. Until #414 moves the cache to shared storage, keep OAuth callbacks on one instance. | +| [4.7](https://www.rfc-editor.org/rfc/rfc9700#section-4.7) | Treat a `state` as single use | **Meets**, since 0.21.0 | A consumed state is recorded in the database, so a replayed callback is refused by every API instance, not only the one that consumed it ([`consumeOAuthState`](https://github.com/fells-code/seamless-auth-api/blob/v0.21.1/src/services/oauthService.ts#L352-L373)). Callbacks no longer need sticky routing. In 0.19.2 the record lived only in the consuming instance's memory, so another instance could accept a replay inside the ten-minute window ([#414](https://github.com/fells-code/seamless-auth-api/issues/414)). |