Passwordless Authentication
Sign in with WebAuthn passkeys or a 6-digit email code. Offer passwordless login with a fallback for users who do not yet have a passkey.
An open-source, OpenID Certified™ Identity & Access Platform for Cloudflare Workers — authentication, authorization, and federation on an edge-first architecture.
Pre-1.0. Core protocols are implemented; production hardening and validation are ongoing.
Sign in with WebAuthn passkeys or a 6-digit email code. Offer passwordless login with a fallback for users who do not yet have a passkey.
Connect applications and existing identity providers through OpenID Connect and SAML 2.0. Create accounts at first login and link external identities.
Control access through roles (RBAC), attributes (ABAC), and relationships (ReBAC). Check permissions through an API, with policies scoped to each tenant.
Automatically expand Cloudflare D1 capacity as your user base grows. Forecast demand and add database shards so you can grow without switching platforms.
Product notes
Separate personal data to support investigation and deletion.
Product notes
This design began with an uncomfortable moment in everyday operations: investigating a failed login and seeing information you did not need to see.
If you run an identity platform, a familiar request comes in: “One of our users can't sign in.” To find the cause, you enter the customer's environment and locate the account.
You need to know whether the account is locked, and when and where the last attempt failed. Which sign-in route did the user take? Is the passkey registration still usable?
None of that involves who the person is. Yet the moment you open the account, you see a name, an email address, a phone number and linked account names on the same screen. You needed the account's state; the person's identity came with it.
"Please don't look" is not a control
while it is rendered on the page.
The investigator has done nothing wrong. The customer asked for help, the procedure was followed, and the information still appeared. The system is built to show it.
Rely on policy and training alone, and protection rests on the investigator's memory and judgment. That is not enough to prevent an eventual incident. Authrim puts personal information in a separate database because we wanted to solve this problem in the design itself.
When you build an identity system, user data naturally ends up together: names and email addresses, app permissions, signed-in devices, passkey registrations and links to external identities.
All of it concerns the user. Putting it in one database is the straightforward approach, and it works. The difficulty comes later, when someone asks you to explain where personal data lives.
“Where is personal information stored?” “What would a breach expose?” “How do you handle a deletion request?” If everything is in the same place, the answer is always “the entire user table.” You cannot give a narrower account of the scope.
Identifying data sits in a physically separate database. Not retrofitted — the repository layer is split at the source.
With storage separated, the investigator can use the left-hand side for the opening case. It holds lock state, failed attempts and device information. Access to that side can be granted without opening the right-hand side. Nobody has to remember to look away.
The same structure makes audit questions easier to answer. You can point to where names and email addresses live and describe the scope of a deletion. We set out to solve an operational problem; the clearer explanation came with it.
This distinction matters. This split is not a legal boundary between personal and non-personal data.
Core DB holds IP addresses, device information, session history, authentication events, credential metadata and stable internal user IDs. Depending on context, those are personal data too. Individually they may not identify anyone; combined with other information, they can.
What Authrim actually separates is directly identifying data from operational identity data. The goal is that an investigation can run on the second without touching the first — not that the second needs no protection.
It would be inaccurate to say that personal data exists only in the PII DB. Names, email addresses and other directly identifying data are isolated there. Troubleshooting access can be granted without opening that store.
"Delete my account" is trivial to execute. The two requests that follow are not.
One is proving the deletion — when, by whom, and why, recoverable later. The other is blocking re-registration for a retention window, which is a common business rule.
Both requests ask you to recognise someone whose account you erased. But if you keep information that identifies them, you have not fully erased it.
The implementation states its own reasoning: store no PII, keep only the fingerprint needed to prevent duplicates, expire after the retention window, and record who deleted, when, and why.
One note for engineers. Email addresses are low-entropy. Fingerprint them with a plain hash and a dictionary attack recovers the original. "Not recoverable" is not unconditional.
Authrim uses an HMAC-SHA256 blind index with a secret key, carrying a key-generation number so keys can be rotated. Without the key, brute-forcing the fingerprint is not available.
Which means key isolation is the precondition for the guarantee. Store the key beside the fingerprints and the guarantee is gone. Do not drop that condition when describing this externally.
Return to the failed-login report. The investigator needs to find where authentication stopped. They usually do not need to open a name or phone number.
Authrim separates directly identifying information so that troubleshooting access can be granted without access to that store. When an investigation does need personal information, someone with the appropriate additional permissions handles it.
Encryption and access control protect the data; audit logs record its use. Alongside those measures, an investigator should be able to finish routine work without opening personal information they do not need. Separating storage makes that the starting point for everyday operations.
Implementation. Complete — storage split and access boundary both in effect
Validation. Covered by automated tests in this repository
Operational maturity. Hardening in progress. Authrim is pre-1.0.
This design makes deletion workflows easier to run. It is not itself a statement of legal compliance. Actual conformance depends on your procedures and contracts. Keep that distinction in external material.
Why logout certification matters for both OP and RP.
Product notes
A person signs in once, but more than one session is created along the way. Logout depends on ending the relevant sessions across that entire path.
Suppose your service offers “Sign in with Google.” The user presses one button.
Behind that button, each system on the sign-in path creates and keeps its own session. Google has one, Authrim has one, and your app has one. Three in all.
If any of those sessions remains, the user may be able to keep working or sign in again without entering a password.
Logout is not printing "You have been signed out."
It means choosing the scope of logout and ending the sessions within that scope.
The "keys" here are sessions. Access tokens and refresh tokens are a different mechanism, and ending a session does not necessarily invalidate tokens already issued. Stopping a token requires revocation — a distinct operation.
In OIDC terms, session logout, token revocation and upstream account disablement are three different things. This installment covers only the session side. When a token stops working is covered in token introspection and revocation.
In this connection, the upstream provider provides login and your application requests it. Authrim's role flips depending on which way it faces.
Login flows from one system to the next. Logout does not follow unless a system passes it on.
Ending an upstream session does not automatically remove sessions in Authrim or your application. Termination needs to be communicated downstream, and each receiver must end its matching session. The next diagram shows the chain when the required notification methods and configuration are in place.
| Situation | What a broken chain produces |
|---|---|
| Offboarding | HR revokes access. The laptop still has the app open, and internal data stays visible until morning. |
| Shared terminals | Retail, hospital, call center. The previous person signed out — then a second tab shows their dashboard. |
| Lost device | "Sign out everywhere" was pressed. Only the session in hand actually ended. |
| Incident response | You cut off the compromised user. The attacker's session runs to expiry anyway. |
| Audit | "Demonstrate that logout propagates to all systems." Nothing to show. |
None of these mean logout is missing. The button exists. The screen changes. The reach is narrower than anyone assumed — that is what makes it hard to catch.
There are two main ways to notify downstream apps. The browser-based method is becoming less dependable.
Authrim's certification covers receiving the bottom method. Receiving a notice and sending it onward each need to be checked.
Authrim acts as a relying party (RP) toward the upstream provider and an OpenID Provider (OP) toward applications. Carrying logout onward requires conformant behaviour in both roles.
OP and RP logout profile certifications provide evidence for these two roles. Authrim holds logout profile certifications on both sides through the OpenID Foundation's self-certification process, using its official conformance tests.
Certification means the submitted implementation version passed the conformance tests for the submitted profiles. It does not guarantee immediate termination of every session across a customer's applications and network.
The upstream provider and each application must support the required methods, with notification endpoints and session mappings configured. Disabling an upstream account does not necessarily trigger a logout notice. Delivery failures, retries and failure visibility also need to be checked in the deployed configuration.
See the OpenID Foundation's Certified OpenID Relying Parties & Logout Profiles listing for certified versions and profiles, and its certification process for the scope of certification.
After logout, where is a session still active?
That is what matters when passing a shared terminal to the next person or ending a former employee's access. Authrim receives and sends notices between the upstream provider and applications. Certification provides evidence about the implementation. You still need to test the connected systems to confirm that the intended sessions actually end.
Connect LDAP and AD without storing passwords.
Product notes
Your passwords already live in Active Directory. How do you add modern login without copying password hashes or publishing an inbound connector endpoint?
Employee accounts are in Active Directory. So is the password policy, expiry, and the offboarding switch. It has been running for years.
You want passkeys on top. You want MFA rationalised. You want more SSO into SaaS. The goal is clear, and the first step always lands on the same question: where does password verification happen?
Some configurations sync password hashes to the cloud; others ask the internal directory to verify credentials. The useful questions are where credentials live, which side opens the connection, and who operates that route.
WordWarden keeps verification with LDAP/AD and lets you choose the route. Authrim Relay provides an outbound connection for organisations that do not want to publish a new inbound endpoint.
Authrim WordWarden is a directory connector. A small service you run next to your LDAP/AD, with one job: take a username and password, ask the directory, return the verdict.
Login UI, sessions, passkeys, email codes, federation output, audit correlation and identity mapping all stay on the Authrim side. WordWarden does verification only, next to the directory.
The direction of the connection changes the network configuration and the components you operate.
WordWarden supports three transports. What separates them is whether your network has to publish a listener.
For a new deployment that should not add inbound access, start by considering Relay. An existing publishing platform or tunnel can also be worth using. The following are deployment scenarios, not claims about customer deployments.
Consider a company running AD at its headquarters where each new public server requires a separate review, or a university that does not permit incoming connections to its campus LDAP network. WordWarden opens the connection to Authrim, so no new inbound port needs to be published on that network.
No new public endpoint or separate tunnel process is needed. Outbound WebSocket traffic must be allowed, and WordWarden's health and connection still need monitoring. Relay cannot serve a network that prohibits external communication altogether.
An organisation already publishing internal tools through Cloudflare Tunnel may have a team responsible for cloudflared updates and routing. WordWarden can fit those procedures without opening a new inbound port.
You configure the hostname and route that let requests from Authrim reach the connector, and maintain the tunnel. The internal host needs no direct inbound access, but requests arrive through a route on Cloudflare.
A company, university or research institution may already have an infrastructure team operating a DMZ and reverse proxy for external integrations. An HTTPS endpoint reachable from Authrim can use that team's existing certificate, access-log and monitoring procedures.
No separate tunnel or Relay connection needs to be maintained. In return, the organisation permits the inbound route and takes responsibility for protecting and maintaining the public endpoint. The published route is the connector's HTTPS interface, not the LDAP/AD port exposed directly to the internet.
Every method requires operating WordWarden where it can reach LDAP/AD. Being an academic institution does not determine the method; existing infrastructure and network policy do.
In relay mode, WordWarden connects to Authrim using WebSocket from inside your network. WebSocket keeps a communication connection open so that either side can send messages over it.
WordWarden keeps that connection open and waits. When someone logs in, Authrim uses the same connection to ask, "Please verify this user." WordWarden checks with the internal directory and sends back the result.
Think of making a phone call from inside the organisation and staying on the line: the other person can speak too. There is no need for a new incoming connection for each request.
In practice that means the directory side publishes no URL at all. This avoids managing a hostname, certificate and WAF for a new public endpoint. Outbound permission, WordWarden maintenance and connection monitoring are still needed.
The difference is which side starts the connection. With Direct HTTPS, the organisation provides an endpoint that Authrim can connect to. With Relay, WordWarden inside the organisation opens an encrypted WebSocket connection (wss) to Authrim's Relay.
A typical stateful firewall or NAT tracks connections initiated from inside and allows their return traffic. This lets WordWarden receive verification requests without publishing an inbound port or configuring port forwarding for new external connections to it.
This does not mean that no ports are used. A typical wss connection uses TCP port 443 at the destination. The organisation's firewall or proxy must allow outbound access to Relay and sustained WebSocket connections. Requests cannot arrive over that route while it is disconnected, so connection monitoring still matters.
Reducing endpoints for new external connections does not remove the verification requests arriving over the established connection. Peer authentication and request validation remain necessary.
Reference: The WebSocket Protocol (RFC 6455)
An outbound connection still needs authentication. Relay combines connector authentication with checks on the configured destination.
WordWarden authenticates with an HMAC response to a short-lived challenge, signing a string containing the challenge ID and nonce. It also checks that the tenant and connector IDs in the destination URL match its configuration.
HMAC is required in all three transports. Relay reduces inbound exposure; it does not remove the need for connector authentication or secret management.
This boundary needs precise language. We cannot say that the password never leaves your network.
The password entered on the login screen passes through Authrim, but neither Authrim nor WordWarden stores it. Passing through and being stored are different things.
On success, Authrim receives the verdict plus the requested attributes intersected with the connector's local allowlist. The requesting side does not decide what it can pull; the directory side decides what it will release.
That direction matters. No change on the Authrim side alone can widen what leaves your network.
This integration is a bridge for the transition.
LDAP/AD remains the password authority, so people can keep signing in with their existing accounts. Passkeys can be enrolled gradually, while email codes remain a recovery path. From the user's side, sign-in keeps working as the authentication method changes.
The documentation also states the prohibition plainly: do not export LDAP/AD password hashes into Authrim. Do that and the bridge becomes a credential copy.
Preparing for public beta. First target is v0.1.0-beta.1.
Intended for pilots — organisations that can run a small service near LDAP/AD and understand the directory, network, TLS and secret-management boundaries. It is not a managed directory service.
Requires Authrim 0.3.2 or later with Directory Authentication and Relay enabled. In the current beta, configuration changes need a process restart.
"Credentials out, or traffic in"
is not the only menu.
Verify next to the directory, and make the connection outbound-only. Satisfy both and you get modern login without copying password hashes and without publishing a listener inside your network.
The goal is the move to passkeys, not indefinite password use. Directory integration provides a way to make that move without interrupting users' sign-ins.
Add D1 shards without moving existing accounts.
Product notes
More users are arriving. That is welcome news, but it raises a question: how long can the current database hold them? Authrim prepares new account storage before it is needed, so growth does not have to begin with a migration project.
Cloudflare D1, the database Authrim uses, has a size limit per database: 500 MB on the Free plan and 10 GB on the Paid plan. As users and their data grow, another place to store that data will eventually be needed.
Moving every existing account whenever a database fills up would be a lot of work. Authrim can distribute accounts across multiple databases from the start. We call each storage unit a shard.
Existing accounts stay where they are; new accounts get more places to go. That is how Authrim expands account storage.
Tenant settings such as OAuth clients and policies. Accounts and personal information. Indexes that locate an account from an email address. Authrim stores these kinds of data separately.
More users do not mean every database has to grow together. Account storage and lookup indexes have different record counts and growth rates. Capacity is added where it is needed.
A new account is assigned to one of the shards available to its tenant. Healthy shards with a lower ratio of allocated accounts to their target count are preferred.
The signal here is not disk utilization. It is how many more accounts can be accepted within the configured target. With a target of 100,000 accounts, for example, a remaining margin of 20,000 helps determine when to prepare the next destination.
When the available shards have little headroom left, a prepared spare is assigned. The same approach applies to shared shards used by several tenants and exclusive shards used by just one.
Shared tenants
Exclusive tenants
Shared and exclusive tenants
Once automatic provisioning is configured, an operator need not create another database each time registrations grow. Preparing its tables and connecting a new destination no longer has to be repeated by hand. Adding capacity does not call for another plan to move existing accounts, either.
The operator watches provisioning progress, failures, usage and costs. Missing permissions or service limits still need a person to intervene. Authrim handles the preparation of the next storage destination.
With 20,000 account slots remaining, a service adding 100 accounts a day has much more time to prepare than one adding 10,000 an hour.
Authrim therefore estimates future capacity from recent registration rates as well as current allocations. Both account storage and lookup indexes are forecast. A scheduled job runs every minute, and account forecasts are also updated after allocation.
Shards already being created count toward the estimate. If several processes notice the same shortage, they should not each create another unnecessary database.
When spares are not enough, Authrim creates D1 databases through Cloudflare's management API. It creates the tables, configures Worker access and distributes the new storage locations. A database becomes an allocation target after its read and write checks pass.
Automatic provisioning must be enabled, with separate API tokens configured for D1 and Workers. When automatic execution is unavailable, an operator continues the work through the setup tool.
Progress is persisted during creation. A temporary connection failure can be retried from that state. Missing permissions or resource limits need an operator to resolve the cause before work can resume.
If preparation falls behind and account slots run out, new registrations may need to retry. Preparing ahead is intended to reduce that wait.
Adding capacity and moving existing data are separate operations. Moving a tenant from a shared shard to an exclusive shard, for example, requires copying existing data as well as providing a new destination.
The operator decides whether to start that migration. After approval, Authrim handles synchronization, verification and cutover.
The supported placement change is currently from shared to exclusive. Moving back to shared storage and automatically redistributing existing accounts evenly are not implemented.
Deleting a retired shard also requires operator approval. Growth does not automatically trigger the movement or deletion of existing data.
In a July 2026 test with 200,000 accounts, Core used about 208 MB, PII about 238 MB and Lookup about 426 MB. Each was below 5% of the Paid plan's 10 GB per-database limit. Actual usage depends on the attributes and indexes stored.
The default target is 100,000 accounts per shard, leaving room to prepare the next one instead of filling a database to its physical limit.
Authrim is pre-1.0, and long-running production experience at large scale is still to come. Measuring storage for 200,000 test accounts is distinct from operating a service used daily by millions of people.
A small service does not need a large deployment on day one. It can start with a few shards and add destinations as registrations grow. Authrim includes the preparation and procedures needed to do that.
When users start arriving, planning a database move should not become the first job on the list. We want to reduce that work so more time can go into the service itself.
Storage measured on July 30, 2026 with 200,000 test accounts. MB uses decimal units. For D1 capacity limits, see the Cloudflare documentation.
K6 Cloud tests cover representative OIDC workloads; capacity depends on workload shape, Cloudflare plan limits, storage, and sharding.
Test reports →Authrim has no per-user vendor fee — infrastructure cost depends on requests, CPU time, storage, and logging. A rough Cloudflare-cost reference, not a production quote.
Based on Cloudflare Workers pricing with a multiplier for KV, Durable Objects, and D1 from observed Authrim usage patterns.
Note — Infrastructure only. Excludes compliance, monitoring, support, operations, security review, external databases, and large R2/archive usage. Actual cost varies by deployment profile.
TypeScript-first APIs, JavaScript SDKs, and a setup workflow for evaluating and developing edge identity deployments.
Self-hosted control with SAML, SCIM, audit logging, tenant boundaries, and storage / logging controls under active hardening.
Start on Cloudflare with no per-user Authrim fee, then scale based on measured request, CPU, storage, and logging behavior.
OpenID Certification
Basic OP · Implicit OP · Hybrid OP · Config OP · Dynamic OP · Form Post OP · 3rd Party-Init OP
RP-Initiated OP · Session OP · Front-Channel OP · Back-Channel OP
Basic RP · Config RP · Dynamic RP · Form Post RP
RP-Initiated RP · Back-Channel RP
Security Profile: private key + DPoP · OpenID Connect · Message Signing: JAR · Message Signing: JARM · Client Credentials: private key + DPoP
Security Profile: private key + DPoP · OpenID Connect · Message Signing: JAR · Message Signing: JARM
Poll: Private Key · Ping: Private Key
Evaluate an open-source identity platform for Cloudflare Workers. Core protocol capabilities are implemented; production hardening is still active.