Skip to content
FoxAuth

Features

Everything is in the box. Most of it is switched off.

FoxAuth ships one server with no feature editions. Authorization Code with PKCE and OpenID Connect run from the first start, and most of the rest wait behind a named flag. In practice your attack surface is the set of features you actually asked for. Each card says whether its feature is on from the first start or waits for its flag.

On FoxAuth Cloud the flags are ours to set, and a plan limits what each project may create. On your own servers both are yours, and plans are off unless you turn them on. A card marked On in FoxAuth Cloud is switched on there.

Each flag below links to its entry in the Settings reference, which is generated from the code and names the default and the consequence.

Protocol

Every grant an OAuth 2.1 client can ask for.

The grants and endpoints. Authorization Code with PKCE and OpenID Connect are always on; most of the rest wait for a flag.

Authorization Code with PKCE

PKCE is mandatory for every client, public or confidential, as OAuth 2.1 requires. Redirect URIs match exactly.

RFC 7636

OpenID Connect Core 1.0

ID tokens, the UserInfo endpoint and discovery, with the standard claim set and pairwise subjects.

OIDC Core 1.0

Issuer identification

Every authorization response carries iss, so a client cannot be tricked into accepting another issuer’s code.

RFC 9207

Resource Indicators

Audience-restrict a token with the resource parameter, and validate it at the resource server. On by default.

resourceIndicators.enabledOn in FoxAuth CloudRFC 8707

Client Credentials grant

Machine-to-machine tokens with no end-user, scoped per client.

clientCredentials.enabledOn in FoxAuth Cloud

Refresh Token grant

Long-lived sessions with rotation and reuse detection. Replay a token and the whole grant is revoked. On by default: offered while offline_access is a supported scope.

scopes

Device Authorization Grant

Sign in on a TV or a CLI by typing a user code on another device.

deviceFlow.enabledOn in FoxAuth CloudRFC 8628

CIBA

Client-initiated backchannel authentication: the client asks, the user approves out of band.

ciba.enabledCIBA Core 1.0

Pushed Authorization Requests

The client posts the request to the server first and sends only a request_uri through the browser.

par.enabledOn in FoxAuth CloudRFC 9126

Request objects

Signed request and request_uri parameters, so the authorization request itself is integrity-protected.

requestObjects.enabled

JARM

JWT-secured authorization responses, signed and optionally encrypted.

responseMode.jwt.enabledJARM

Rich Authorization Requests

Fine-grained authorization_details instead of a scope string, for payments and similar.

richAuthorizationRequests.enabledRFC 9396

Token introspection

Resource servers ask the issuer whether a token is still active, and what it carries.

introspection.enabledOn in FoxAuth CloudRFC 7662

JWT introspection responses

Signed introspection responses, for a resource server that must prove what it was told.

jwtIntrospection.enabledRFC 9701

Token revocation

A client retires an access or refresh token it no longer needs.

revocation.enabledOn in FoxAuth CloudRFC 7009

Signed UserInfo responses

Return UserInfo as a signed JWT instead of plain JSON.

jwtUserinfo.enabled

The claims parameter

Per-request claim selection, including essential claims and the acr request.

claimsParameter.enabled

RP-initiated logout

End the session from the client, with a confirmation step so a link cannot log a user out silently. On by default.

rpInitiatedLogout.enabledOn in FoxAuth Cloud

Backchannel logout

Notify every client of a session that ended, server to server.

backchannelLogout.enabledOn in FoxAuth Cloud

Security

Sender constraint, and defences that are already on.

The banking-grade profiles are flags, not editions. The rest of this list is on from the first start.

DPoP

Sender-constrained access and refresh tokens, including server nonces, so a stolen token is not enough.

dpop.enabledOn in FoxAuth CloudRFC 9449

mTLS client authentication

Client certificates for authentication and certificate-bound access tokens.

mTLS.enabledRFC 8705

FAPI profile behaviours

The stricter checks the Financial-grade API profiles require, as one switch.

fapi.enabled

Token and response encryption

Encrypted ID tokens, UserInfo and JARM responses using the client’s registered keys.

encryption.enabled

TOTP second factor

Per-project time-based one-time passwords, optionally enforced for the admin console.

RFC 6238

Pairwise subject identifiers

A different sub per sector, salted from the database, so two relying parties cannot correlate a user.

Sign-in brute-force throttle

Persisted per-identity failure counters with escalating lockouts. A throttled refusal looks exactly like a wrong password.

Per-origin rate limiting

Tiered by route class and on by default, with the trusted-proxy hop configurable.

rateLimit.enabledOn in FoxAuth Cloud

CORS closed by data

An origin is readable only if the calling application lists it among its own allowed origins. No wildcard setting opens it.

cors.enabledOn in FoxAuth Cloud

Security headers

HSTS, Permissions-Policy, framing and content-type protections on every response.

Scope-based access control

Per-client scope enforcement, checked at the authorization endpoint and again at the token endpoint.

The admin audit trail listing actor, action, target and timestamp for each change.
The audit trail. Entries are written before the mutation and the store exposes no update or delete, so an entry cannot be altered after the fact.

Administration

One management API, three front doors.

The console, the HTTP API and the MCP tools dispatch into the same routes, so the checks and the audit write cannot drift.

Administration console

Projects with their applications and APIs, administrators and their teams, end users, upstream providers, SCIM connections, settings, SMTP and signing keys. Every screen has an address. A change that could lock people out or break applications first says whom it affects, counted, and applies only once you confirm.

Append-only audit trail

Every state-changing admin action records actor, action, target and time. The entry is written before the mutation, and the store has no update or delete path.

Monthly active users per project

Each project counts the people it issued tokens to, once per UTC month and day, split into local sign-in, upstream sign-in, renewal and directory provisioning. A closed month never changes, and the history outlives the people and the project. Usage shows every project beside the team that owns it, so an instance run for other teams or customers can say who used how much.

Plans for a shared instance

A plan is a named set of limits on a project: monthly active users, applications, APIs, projects per administrator, enterprise sign-in, and whether the team names its address. A limit stops only something new: nothing that exists is switched off, and nobody is refused a sign-in. At the user cap, only new self-service sign-ups pause. A super administrator edits the plans and moves projects between them. Nothing is billed.

plans.enabledOn in FoxAuth Cloud

Administration over MCP

124 tools served to an AI agent at POST /mcp as an OAuth 2.1 protected resource, with two-call confirmation on high-consequence operations.

mcp.enabledOn in FoxAuth CloudRFC 9728

Authorization for your own MCP servers

Declare a third-party MCP server as a protected resource of a project and this server mints tokens whose audience is exactly that resource, with no code change here and no restart. In a project with an address of its own the declaration needs nothing from the resource — it can be internal, on localhost or not yet deployed — and another tenant may declare the same URL without affecting yours. Tokens are self-contained by default, so the resource verifies them against its project’s published keys without credentials of its own.

RFC 8707

Client identity documents

A client_id that is an HTTPS URL naming a JSON document describing the client, retrieved and validated on demand and never stored — the mechanism the MCP authorization specification names first for a client with no prior relationship.

clientIdMetadataDocument.enabledOn in FoxAuth Cloud

Dynamic client registration

Clients register themselves, subject to the registration policy. Deprecated by the MCP specification in favour of client identity documents.

registration.enabledRFC 7591

Registration management

Read, update and delete a registration with its registration access token.

registrationManagement.enabledRFC 7592

Database-backed clients

Clients live in the server’s own store, created through the console, the API, dynamic registration or the setup script. There is no static client file.

Team ownership

Projects are owned by a team of administrators, and so is everything in them: end users, applications and APIs. Nothing but membership of the team grants access, and it is re-resolved on every request. A project moves to another team with everything it holds, in one step.

A project addressed by a path, a subdomain or a host

Each project is its own issuer, with its own metadata and signing keys, reached at exactly one address: a path beneath the server, a subdomain of it, or a hostname of its own. A subdomain or a hostname lets the browser isolate that project’s sign-in cookie by origin and publishes one metadata location instead of two. Subdomains cost one wildcard DNS record and certificate for the whole instance; a hostname costs a record and a certificate of its own. Changing an address is its own operation: it shows you which clients it will break before it breaks them.

Deleting a project can be undone

Delete switches a project off at once and destroys it 30 days later. Until then nothing in it is destroyed, and Restore brings it back with every session and refresh token still valid.

End-user self-service

Email verification and password reset per project, each with attempt caps, cooldowns and single-use links. An address counts as verified, and applications are told email_verified: true, only once it is proven: from the mailbox, by a trusted identity provider or directory, or by an administrator who marks it.

End-user administration

Invite a person to set their own password, mark an address verified, or sign someone out of one application and leave the others. Up to 100 people can be deactivated, activated, signed out or deleted at once, each with an audit entry of their own.

Sign in with Google, Microsoft, Apple or GitHub

Connect one by name and the console shows you what to do at the provider and the exact callback address to register; you supply only the values it issues. Any other OIDC provider can be configured by hand. Per project, so each tenant uses its own application. Try sign-in shows what a real sign-in would do before anyone relies on the provider, and the callback refuses an answer from an issuer other than the one the sign-in started with. Administrators can sign in to the console through your organisation’s provider too.

federation.enabledOn in FoxAuth Cloud

Sign-out at an upstream provider ends sessions here

When a person signs out at Keycloak, Auth0 or Ping, the provider sends a logout token. The sessions here that began with that provider session end, and the applications they reached are told. Offline access is kept, because a sign-out is not a compromise. Each provider is opted in on its own, and the token must be signed with the provider’s published keys.

federation.enabledOn in FoxAuth CloudOIDC Back-Channel Logout 1.0

Okta Universal Logout

An opted-in provider sends one signed request, and everything the person holds here ends: sessions, refresh tokens, and every access token the server can revoke. The account stays active, so the person can sign in again. It follows an Internet-Draft that has expired, so it has a flag of its own.

globalTokenRevocation.enabledGlobal Token Revocation draft

SCIM 2.0 provisioning

Microsoft Entra ID, Okta or any SCIM 2.0 directory creates, updates and removes a project’s users and groups. A removal of many people at once can be held for review instead of applied, and a replaced secret or static token keeps working until the directory has switched to the new one.

scim.enabledRFC 7644

Signing key management

Each project with an address of its own signs with keys of its own, published at its own jwks_uri, so one tenant’s token never verifies at another’s resource server. The project’s owning team rotates them in one step — a new key is published before it may sign, and a retired one stays published until its tokens expire — and can revoke a compromised key at once, so nothing it signed verifies any more. The instance key set stays a super administrator’s.

The admin console settings pane showing the grant-type flags and their current values.
Settings, one pane per domain. A flag here is the same key the Reference documents; changes are validated as a whole configuration before they are saved.

Extensibility

Change behaviour without forking.

Named seams and one adapter interface, so your changes should survive an upgrade.

31 override seams

Account lookup, interaction policy, refresh-token rotation, resource resolution, pairwise identifiers, RAR handling and more, replaced at call time.

Pluggable storage

Every persisted model goes through one adapter interface. PostgreSQL, MongoDB and in-memory implementations ship; one connection string picks which.

Mountable Elysia app

Import the app and mount it in your own Bun service. There is no init step — importing is what boots it.

Built-in login and consent UI

React and Ant Design screens in English, Russian and Simplified Chinese, light or dark with the device. The consent page says who is asking and lets people choose what an app gets, and a connected-apps page lets them take it back. Theme the screens, or replace them through the interaction policy.

Operations

What you need when something is wrong.

Ship it, watch it, and find out why a request failed.

Published container image

ghcr.io/redfox-soft/oauth-server-ts, tagged per release and latest, with a Compose file that provisions the schema.

Server error store

Internal faults are recorded and readable in the console. Routine client rejections are correct behaviour and never appear.

errorStore.enabled

Optional Sentry reporting

Reporting sits off the request path entirely: a fault reaches it only after it is classified as a defect, so responses are unchanged.

sentry.enabled

Settings you can read

Every server-wide setting is documented with its type, default and consequence, and edited in the console.

Machine-readable reference

The endpoint, settings, admin API, MCP tool and environment references are generated from the code itself.

Next

Compare it with what you run today.

We keep a factual, dated comparison against the servers teams usually weigh this against.

Already running something else? We keep dated, sourced comparisons with Auth0, authentik, Keycloak, Ory Hydra and Zitadel, each listing the pages we read and the date we read them.