Skip to content
Menu

Accountless identity · Open core · Standard OIDC

Identity without the account.

Your phone holds your identity. Your biometric unlocks it. Your app receives a standard OpenID Connect token. No password, no email, and no identity-provider account to create, reset, or breach.

iPhone app on the App Store · Android coming soon See a full integration at jtmerlin.com , our demo bank.

npm install @identizen/react

A browser on acme.com/login shows a Continue with Identizen button, a QR code and the match code 47. The challenge travels to the index, the index pushes it to the phone, and the phone shows Acme, the same match code, and Approve with Face ID. The signed assertion returns to the browser.

challenge lifetime
60 s
match code
2-digit
secrets stored
0
to integrate
5 lines

Accountless identity

Passwordless still has an account.

Replacing the password does not remove the identity-provider account behind it. Identizen does. There is no master account holding your identity. Your phone holds a cryptographic identity and derives a different one for every application you use. Your biometric lets the phone prove it, once, for one request.

Accountless does not mean an application cannot keep user data. It means the identity does not depend on a credential account at a provider. Your app still stores whatever it needs under the per-site identifier it receives; nothing at Identizen can sign in as the user.

What accountless means, in full

Traditional identity

  1. You

  2. Identity-provider account

    a record someone else owns

  3. Password, passkey, or MFA

    credentials that protect that record

  4. Identity provider

    holds the credential database

  5. Application

Identizen

  1. You

  2. Your phone

    holds the cryptographic identity

  3. Your biometric

    unlocks it for one request

  4. Index

    routes and verifies; stores no secrets

  5. Application

    receives standard OIDC

The phone is not another factor in front of an account. It holds the identity. The index is in the picture because it exists: it routes requests and verifies signatures, and it never holds anything that could sign in as you.

One identity, three questions

Authenticate. Verify. Authorize.

The same phone-held key answers all three. Start with login, add the other two when an action deserves them.

  • Authenticate

    “I am this identity.”

    Sign people into your app without a password or a provider account. Your app receives a standard OIDC id_token with a per-site identifier.

    Learn more
  • Verify

    “It is really me, right now.”

    Ask the phone for a fresh biometric approval when a session needs more assurance: a new country, a sensitive page, an admin console.

    Learn more
  • Authorize

    “I approve this specific action.”

    Send the exact action to the phone. The person reads it, approves it, and the signature is bound to that text, so it cannot be reused for anything else.

    Learn more

How it works

Three hops, one tap.

Challenge in, signed assertion out. Every step is specified, signed, and verifiable by anyone running the open-source index.

  1. 01

    Your site asks for a login

    The SDK requests a challenge from the index: a signed, single-use request that expires in 60 seconds and carries a two-digit match code.

  2. 02

    The phone gets it

    A paired browser pushes straight to the phone. Otherwise the user scans a QR, or on Chromium clicks to find the phone over Bluetooth. The match code stops relay tricks.

  3. 03

    Face ID signs, you get OIDC

    The phone derives a key for your site and signs the assertion. The index verifies it and hands your app a standard id_token. No email, no password.

Developer experience

Built for the afternoon you have.

A typed SDK, a React component with accessible states, and a CLI that registers your site and scaffolds the callback route. If a quickstart step needs explaining, we treat it as a bug.

  • Works with any OIDC library; the SDK is optional.
  • Fake phone for local development and CI, no device needed.
  • Framework guides for Next.js, Express, ASP.NET Core, Django, React, and plain HTML.
app/login.tsx
import { IdentizenProvider, IdentizenButton } from '@identizen/react';

export function Login() {
  // login = { redirectUri, state, nonce, codeChallenge } from prepareLogin()
  return (
    <IdentizenProvider indexUrl="https://index.identizen.com" clientId={clientId}>
      <IdentizenButton login={login} />
    </IdentizenProvider>
  );
}
terminal
npx identizen init      # registers the site, writes .env.local, scaffolds /api/auth/*
npx identizen dev       # runs a fake phone that approves logins while you build

Why it holds up

The index is a phonebook, not a vault.

Everything we host must be safe to leak. That single constraint shapes the protocol.

  • The phone is the identity

    A seed on the device derives one key per site. Two sites cannot match a user by identifier, and there is no account with us to take over. Lose the phone: restore from 24 words and revoke the old one.

  • Nothing to leak

    The index stores public keys, push tokens, audit events and, for paired browsers, a public key plus the browser’s user-agent and last IP. Never a private key, seed, password, or plaintext token.

  • Standard on the outside

    Your app sees OpenID Connect with PKCE, back-channel logout, and a JWKS. Any OIDC library works; ours is just shorter.

  • Pair once, then no QR

    After the first approval the browser holds a pairing key. Later logins push to the phone directly. Revoke from the app at any time.

  • Proximity when you want it

    The phone advertises a rotating Bluetooth id. Chromium browsers can find it without a camera; the id changes every 15 minutes.

  • Self-host in one command

    The same Worker runs index.identizen.com. Deploy it to Cloudflare or run the container; indexes federate over WebFinger.

server/approve-wire.ts
import { createIdentizenServer } from '@identizen/sdk/server';

const idz = createIdentizenServer({ indexUrl, clientId, clientSecret });

// Any backend, any time after enrollment: the phone shows the reason and signs it.
const v = await idz.verify({ sub, reason: 'Approve wire of $12,000 to Acme?' });
const done = await idz.waitForVerification(v.verification_id);
if (done.status === 'approved') release(wire); // assertion binds the reason hash

Authorize

Don't just authenticate the user. Prove they approved the action.

Keep your existing login if you like. Bind a person's phone once, then send it the exact action: a wire transfer, a production deploy, an admin grant. The text is shown on the phone and bound into the signature, so an approval cannot be replayed for something else.

Where it runs

One protocol, every surface.

Surface Integration Ships with
Web (any framework) OIDC + @identizen/sdk @identizen/react
Next.js, Express Guides + CLI scaffolds npx identizen init
iPhone Identizen app · on the App Store Face ID
Android Identizen app · Google Play soon Fingerprint
Your own index Cloudflare Worker or Docker WebFinger federation

Add accountless identity this afternoon.

Register a site, drop in the button, and approve your first login with the phone in your pocket. Free for personal identities, forever.