Blind-ID sign-in

Standard OpenID Connect. Any library that supports it works: point it at the discovery document, use the authorization code flow with a proof key, and ask for the openid scope. Each person presents a government ID from their phone wallet at every sign-in; your site receives an identifier for them and nothing from the ID.

1. Register your site

In the developer console, register the site with the address your library sends people back to, the name and logo a person's wallet shows them when your site asks for their ID, and your privacy policy. You get a client ID and a client secret. A new site is in testing, for a limited number of people; verify your domain and take it live when you're ready. On WordPress, the plugin does all of this with one button.

2. Configure your library

Discovery
https://sandbox.irlproof.me/.well-known/openid-configuration
Issuer
https://sandbox.irlproof.me/
Authorization
https://sandbox.irlproof.me/connect/authorize
Token
https://sandbox.irlproof.me/connect/token
User info
https://sandbox.irlproof.me/connect/userinfo
Sign-out
https://sandbox.irlproof.me/connect/logout
Flow
Authorization code with a proof key (S256). Required for apps without a secret, and on by default for the rest.
Scopes
openid, and offline_access for a refresh token.

Working examples for ASP.NET Core, Next.js, Python and PHP are on Code samples.

3. What your site receives

In the ID token and from user info:

ClaimWhat it is
subThe person's identifier at your site. The same every time they present that ID at your site, unique to your site, and meaningless anywhere else: two sites comparing their users find nothing in common. Use it as the account key. It is computed from the ID at every sign-in and we do not store it.
preferred_usernameA readable username made from sub, such as irlproof_me_k7q2m9x2vq. Exactly as unique and private as sub.
auth_timeWhen the person presented their ID for this sign-in.
site_dataWhat your site asked the person for during sign-in, set under "What you ask for" in the console, as an object of field and answer. Present only in the token of the sign-in that collected it: IRLProof keeps none of it, so store what you need on your side. A person is asked each needed field once.
consent_receiptA signed receipt naming the fields the person agreed to give you, and when. Sent on every sign-in once it exists. Keep it with the account.
age_verificationWith the age verification add-on: {"id", "result", "verified_at", "receipt"}, where result is over_18, under_18 or unknown (the ID doesn't carry the answer). {"result": "not_checked"} if the check wasn't made. Let someone in only on over_18.
age_over_18The same result as a boolean, present only when the ID answered.

There is no name, email, date of birth or document number, ever. If you need an email, ask for it in your data contract; the person types it.

A new document number is a new person. If someone's ID is replaced with a different number, their next sign-in produces a different sub, and nothing on our side can connect the two: we keep no record of people. If your site needs account recovery across that, keep your own way of doing it, as you would for any sign-in. The same person with a passport and a license is two sub values unless your site lets them link two sign-ins to one account.

4. The button

Put the Blind-ID button on your sign-in page, the way you would Google's or Apple's. The kit is one stylesheet and one block of markup, with a light and a dark version:

Download the button kit blind-id-button.css The sign, on its own

<link rel="stylesheet" href="https://sandbox.irlproof.me/brand/blind-id-button.css">

<button class="blindid-btn blindid-btn--sub blindid-btn--right" style="--bh:44px">…</button>
<button class="blindid-btn blindid-btn--sub blindid-btn--right blindid-btn--dark" style="--bh:44px">…</button>

5. How often the ID is asked for

6. Sign-out

Send the browser to https://sandbox.irlproof.me/connect/logout with id_token_hint and a post_logout_redirect_uri you registered. The next sign-in asks for the ID again.

7. Webhooks

Set a webhook address on your site's Webhooks tab to hear about things only IRLProof.me knows:

POST /your/webhook
IRLProof-Signature: t=1789000000,v1=5f2a...
Content-Type: application/json

{"event":"subject.deleted","sent_at":"2026-09-16T12:00:00Z","sub":"..."}

The signature is HMAC-SHA256, keyed with your webhook secret, over the timestamp, a full stop and the exact body. Refuse anything older than five minutes. Checking code is on Code samples. A delivery that fails is retried five more times, over about eight and a half hours.

8. Receipts

Consent receipts and age verification receipts are ES256 JWTs signed with the keys at /.well-known/irlproof/jwks.json. Check one with any JWT library, or paste it into /receipts.

9. What can interrupt sign-in at your site

Blind-ID presents IDs from Google Wallet under Google's digital identity program. Under it we tell Google which sites use the sign-in and what for, and if Google tells us to stop a site, we have to stop it promptly. What that means for your site, in plain words:

10. Limits and errors