Skip to main content
Use session proofs when the same user needs to verify again, such as when returning to your app or confirming a sensitive action. This is the recommended flow for Selfie Check integrations that need repeated verification. A uniqueness request allows each user to complete a particular action once. A session lets the user prove continuity across multiple checks: create it once, then prove the saved session on subsequent checks. Session IDs alone do not prevent the same person from enrolling more than once. To enforce uniqueness at enrollment and verify returning users afterward, create a session with a uniqueness proof. A World ID session is not your application’s login cookie or access token. Your backend decides what a successful verification authorizes.

Before you start

Complete the installation and Portal setup and use the same backend verification endpoint as other IDKit flows. This guide covers the session-specific changes. Generate fresh RP signatures for session creation and each subsequent check. For session-only requests, call signRequest({ signingKeyHex }) without an action. A uniqueness request that also creates a session includes an action, as shown below. Neither flow supports legacy proofs.
In IDKit 4.4.0, session builders require .constraints(...); .preset(...) throws an error. React session widgets and hooks also require constraints.
The examples assume app_id comes from your Portal configuration and rp_context contains the fresh signature returned by your backend. Use a new rp_context for each example invocation.

Create a session

CredentialRequest("selfie") selects the Selfie Check credential. See Configure Credentials for credential options. Your backend must verify the complete result before saving its session_id. Associate it with the account completing enrollment. Treat linking or replacing an account’s session as an account-security operation; do not silently replace the saved value whenever the client submits a new session.

Create a session with a uniqueness proof

During enrollment, use IDKit.request with an action and session_id: "create". This produces one uniqueness proof that also binds a new session, so the user can enroll and establish continuity in the same request. Use the same enrollment action for all users, such as "signup". On your backend, generate the RP signature with signRequest({ signingKeyHex, action: "signup" }) and use its values in rp_context. The signed action must match the request below.
The World ID 4.0 result contains both action and session_id, with a uniqueness nullifier in each credential response. For this enrollment request, use that nullifier to enforce uniqueness:
  1. Verify the complete result, including action and session_id, through your backend verification endpoint. Require the expected enrollment action.
  2. Reject a nullifier already used for enrollment under this app and action.
  3. Save the verified nullifier and session ID against the account only after both checks succeed. Enforce nullifier uniqueness in your database to prevent concurrent requests from enrolling the same World ID twice.
Uniqueness assurance depends on the selected credential. Selfie Check remains a medium-assurance credential. For later checks, prove the saved session with a fresh RP signature without an action. Keep the original enrollment nullifier; subsequent session proofs return session_nullifier values for replay protection.

Verify a returning user

Load the saved session ID from your backend for the account being verified, and obtain a fresh RP signature. Prove that existing session:
savedSessionId is the opaque session_... string returned during creation. Preserve it unchanged. Creating a new session on each visit does not establish continuity with the account’s existing session. For React, use IDKitSessionWidget with constraints={CredentialRequest("selfie")}; import both from @worldcoin/idkit. Omit existing_session_id for creation and set it to the saved session ID for subsequent checks. The widget’s handleVerify callback should call your backend before onSuccess grants access.