Enroll & link devices
ReadyLinking a device is a one-time ceremony: your server mints a single-use invite, the user scans it in the authenticator, the app pins the connection to your deployment’s own root, and the phone generates a hardware-bound key it will use to sign every future approval. No personal data changes hands.
Who this is for: the integrator wiring enrollment into a signup or account-settings flow. Your side is a single call; the app and device SDK do the rest. This is the prerequisite for step-up and every ceremony.
To see enrolment from the person’s side, view Adding an account in the authenticator manual.
The flow#
Five steps, once per device. Your server does step 1; the authenticator and the device’s secure hardware do the rest.
Issue an invite
Call IssueEnrollmentInvite for the user’s opaque identity. You get back a single-use, short-lived invite; render it as a QR (or a deep link).
Scan it in the app
The user opens the Ydentifi authenticator and scans the QR. Nothing is bound yet — the app first has to check who issued it.
Check who issued it, then consent
The invite is bound to your deployment’s own trust chain: it carries your root CA’s fingerprint, which the app pins its TLS connection to (the phone presents a certificate it signs itself, over a key it makes for this account; nothing issues it one). So the device pins to the deployment that issued the invite and cannot be silently redirected or intercepted. The app shows your named service and asks the user to approve the link before any key is bound — so a user cannot be trivially phished into linking to an impostor.
Generate a key & attest the hardware
The phone creates a hardware-bound key in its secure element (the private half never leaves it), and enrolls the key it presented on the connection. Your server signs nothing: the phone keeps the certificate it signed itself. The server does not check a platform attestation (App Attest on iOS, key attestation on Android).
Bound
The device is now linked to that opaque identity and can receive and sign challenges. No name, email, or number was exchanged — only the opaque token and cryptographic material.
Issue the invite#
This one call is your entire server-side involvement in enrollment:
// install: go get github.com/ydentifi/go
inv, err := client.IssueEnrollmentInvite(ctx, &identity.IssueEnrollmentInviteRequest{
OpaqueId: opaqueID, // the user you onboarded earlier
TtlSeconds: 300, // single-use, and short-lived
})
if err != nil { /* handle */ }
// inv.QrPayload is what the user scans in the authenticator app.
// Render it as a QR (Ydentifi does not draw the image), or hand it to
// the app via a deep link. It is void after one use or inv.ExpiresAt.
renderQR(inv.QrPayload)The invite is single-use and expires quickly, so a leaked QR is worthless after it is scanned or its short TTL elapses. Issue it from a place where you have already authenticated the user in your own product — a signup step, or an “add a device” button in account settings.
One user per phone#
At your service a phone holds one user’s account at a time. If another user’s invite is scanned on a phone that is already enrolled for someone else, enrollment is refused (CompleteEnrollment answers device_duplicate; the app shows “device already registered”), and that invite is spent. To move the phone to the other user, revoke the first user’s device with RevokeDevice, then invite again. The same user scanning a new invite on their own phone replaces their device.
When the user is at the device limit#
Each user may have up to 3 active devices. For a user already at the limit, IssueEnrollmentInvite mints nothing and returns FAILED_PRECONDITION with reason MAX_DEVICES_REACHED. Free a slot, then invite again:
- Show the user their devices with ListDevicesForUser: the model, when each was added, when it last signed in. A phone the app was deleted from has not signed in since.
- Let the user choose one to remove. Only after you have authenticated them: removing a device is the user’s decision, not anyone’s who asks.
- Revoke it with RevokeDevice, then call
IssueEnrollmentInviteagain. The new invite is issued at once.
If the user is setting up a phone they already use, removing that phone’s entry is fine: the new enrollment takes its place. Deleting and reinstalling the app makes the phone a new device, so its old entry is the one to remove.
inv, err := client.IssueEnrollmentInvite(ctx, req)
if errors.Is(err, ydentifi.ErrDeviceLimitReached) {
devices, _ := client.ListDevicesForUser(ctx, opaqueID)
chosen := askTheUser(devices) // after authenticating them
_ = client.RevokeDevice(ctx, opaqueID, chosen)
inv, err = client.IssueEnrollmentInvite(ctx, req)
}What happens on the device#
Steps 2–4 are handled by the authenticator app — or, if you are building the ceremony into your own app, by the Swift / Kotlin device SDKs. Under the hood the app claims the invite (BeginEnrollment) and finishes the binding (CompleteEnrollment), sending its keys and a proof that it holds them; no certificate comes back. You do not write any of this; it is the same flow whether the user has the stock authenticator or your own embedded one.
The QR is your deployment’s address plus a single-use invite token — nothing else, so it stays small and scans reliably. The app accepts a connection only from a certificate that chains to the root the code pins, which is what keeps it talking to your deployment rather than a look-alike. See The ceremony.
Losing a device#
If a user loses their phone, you re-establish trust on a new one — you never move a key between devices:
- Verify the user out-of-band first (your KYC, security questions, whatever you already trust), then call
IssueRecoveryInvite. Recovery is deliberately separate from a normal invite because the stakes are higher — you, not Ydentifi, vouch that this is really them. - They enroll the new device with the same five steps above. The lost device’s key is revoked and can no longer sign.
- Replace the TOTP secret: call
IssueUserTotpEnrollmentwithreuse_existingfalse. Recovery leaves it as it is, so the lost phone’s codes stay valid until you do.
Device-to-device transfer is not part of v1 — re-enrolling a new device is the supported path.