Incognito Actions

Cloud Incognito Actions

IDKit is required in your app's frontend for Incognito Actions, and the zero-knowledge proof received from the user will be verified via the Developer Portal API in your backend.

Creating actions

Create an action for your app in the Developer Portal. You must provide the following values:

  • Action Name: The stringified action to be taken by the user.
  • Description: This is shown to your user in the World app as they sign with their World ID. Make sure to fully describe the exact action the user is taking.
  • Max Verifications: The number of times a user can take this action. A value of 0 indicates that unlimited verifications can take place.

An action scopes uniqueness for users, which means users will always generate the same ID (nullifier hash) when performing the same action. Cloud actions natively handle sybil-resistance with a limit set in the Developer Portal.

Installing IDKit

The JS package can be included in your project either as a module (which supports tree shaking to reduce bundle size) or you can add the script directly to your website.

Install IDKit

npm install @worldcoin/idkit

Usage

Import and render IDKit. You'll want to do this on the screen where the user executes the protected action (e.g. before they click "Claim airdrop" or "Vote on proposal").

import { IDKitWidget, VerificationLevel } from '@worldcoin/idkit'

<IDKitWidget
	app_id="app_GBkZ1KlVUdFTjeMXKlVUdFT" // obtained from the Developer Portal
	action="vote_1" // this is your action id from the Developer Portal
	onSuccess={onSuccess} // callback when the modal is closed
	handleVerify={handleVerify} // optional callback when the proof is received
	verification_level={VerificationLevel.Device}
>
	{({ open }) => <button onClick={open}>Verify with World ID</button>}
</IDKitWidget>

More configuration options can be found in the IDKit reference.

When a user clicks the button, the IDKit modal will open and prompt them to scan a QR code and verify with World ID. Once this proof is received, the optional handleVerify callback is called immediately and the onSuccess callback will be called when the modal is closed. One of these callbacks should begin the process of verifying the proof.

Response

Upon successful completion of the World ID flow, you will receive a response object. This response object of type ISuccessResult has the following attributes. Normally, you will forward these parameters to your backend for verification.

ISuccessResult

{
	"merkle_root": "0x1f38b57f3bdf96f05ea62fa68814871bf0ca8ce4dbe073d8497d5a6b0a53e5e0",
	"nullifier_hash": "0x0339861e70a9bdb6b01a88c7534a3332db915d3d06511b79a5724221a6958fbe",
	"proof": "0x063942fd7ea1616f17787d2e3374c1826ebcd2d41d2394...",
	"verification_level": "orb"
}
  • Name
    merkle_root
    Type
    string
    Description

    This is the hash pointer to the root of the Merkle tree that proves membership of the user's identity in the list of identities verified by the Orb.

  • Name
    nullifier_hash
    Type
    string
    Description

    The unique identifier for this combination of user, app, and action.

  • Name
    proof
    Type
    string
    Description

    The Zero-knowledge proof of the verification.

  • Name
    verification_level
    Type
    "orb" | "device"
    Description

    Either orb or device. Returns the verification_level used to generate the proof.

Verifying Proofs

This section describes how to verify proofs via the Developer Portal API.

You should pass the proof to your backend when verifying proofs via the API. Users can manipulate information in the frontend, so the proof must be verified in a trusted environment.

Your backend should receive the ISuccessResult object returned by IDKit, as well as the signal that was input into IDKit, and send it to the Developer Portal API for verification using the verifyCloudProof helper. The action ID should be accessible in your backend as an environment variable. After performing your own backend actions based on the result, you then pass the success or error messages back to your frontend.

pages/api/verify.ts

import { type IVerifyResponse, verifyCloudProof } from '@worldcoin/idkit'

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
	const { proof, signal } = req.body
    const app_id = process.env.APP_ID
    const action = process.env.ACTION_ID
	const verifyRes = (await verifyCloudProof(proof, app_id, action, signal)) as IVerifyResponse

    if (verifyRes.success) {
        // This is where you should perform backend actions if the verification succeeds
        // Such as, setting a user as "verified" in a database
        res.status(200).send(verifyRes);
    } else {
        // This is where you should handle errors from the World ID /verify endpoint. 
        // Usually these errors are due to a user having already verified.
        res.status(400).send(verifyRes);
    }
};

Post-Verification

If handleVerify does not throw an error, the user will see a success state and the onSuccess callback will be called when the modal is closed. The onSuccess callback should redirect a user to a success page, or perform any other actions you want to take after a user has been verified.

pages/index.tsx

const onSuccess = (result: ISuccessResult) => {
	// This is where you should perform frontend actions once a user has been verified
	window.alert(
		`Successfully verified with World ID!
    Your nullifier hash is: ` + result.nullifier_hash
	)
}

For more information on configuration, see the IDKit and Cloud API reference pages.