Your site knows a person only by their sub. This page explains what it is, where it's the same and where it's different, and the few cases where it changes.
The sub
- The same every time the same person signs in to your project.
- Different for every project: two sites can't match their users up.
- Looks like
1.Ab3x…: a key version, a dot, then the ID. Treat it as an opaque string and store up to 255 characters. - It reveals nothing about the person, and Human Pass never gives a site any way to turn it into an identity.
Projects
A project is the privacy boundary. Every client in a project (your web app, your iOS app, your Android app) gets the same sub for a person, so they share accounts. Different projects never do, even in the same organization. Create one project per product whose accounts should be shared.
When an ID changes status
After someone has signed in, their Human Pass can change. The status API tells you about IDs you hold:
| Status | Meaning | What to do |
|---|---|---|
active | Normal (also what an unknown ID returns). | Nothing. |
suspended | Human Pass has stopped the person signing in, for now (for example during an investigation). | Treat like a suspended account; it may become active again. |
revoked | Stopped for good (for example a stolen ID, after a dispute). | Close or restrict the account. |
deleted | The person deleted their Human Pass. | Treat as a deleted account. If they come back, they may get the same ID. |
merged | One person had two Human Passes; they're now one. Comes with replaced_by. | Combine the two accounts (below). |
rotated | The ID was replaced by a new one for the same person. Comes with replaced_by. | Move the account to the new ID (below). |
A suspended, revoked or deleted person can't sign in: your callback gets access_denied.
Merges
Rarely, one person ends up with two Human Passes (for example they created one with a passport and another with a licence before Human Pass knew both were theirs). When they're combined, the ID that goes away is reported merged, with replaced_by set to the one that stays. If you have accounts under both, combine them as you would any duplicate; if only under the old one, move it to replaced_by.
Rotations
IDs are computed with a key. If Human Pass ever has to change that key (for example after a security incident), every ID changes, for every site, and we'll tell you in advance. For a while afterwards, a person's ID token carries both:
| You have an account under… | Do this |
|---|---|
sub | Use it (it was already moved, for example by your status check). |
only previous_sub | Move that account to sub, in the same database transaction as the lookup. |
| neither | Create a new account. |
| both | A duplicate: combine them as for merged. |
People who don't sign in during that time are reported by the status API as rotated, with replaced_by. Rehearse it with the rotation drill.