diff --git a/docs.json b/docs.json index 712b3a5..eebbb89 100644 --- a/docs.json +++ b/docs.json @@ -93,7 +93,10 @@ }, { "group": "Migration", - "pages": ["world-id/4-0-migration"] + "pages": [ + "world-id/4-0-migration", + "world-id/from-idkit-standalone" + ] }, { "group": "Technical Reference", diff --git a/world-id/from-idkit-standalone.mdx b/world-id/from-idkit-standalone.mdx new file mode 100644 index 0000000..fc47f4b --- /dev/null +++ b/world-id/from-idkit-standalone.mdx @@ -0,0 +1,188 @@ +--- +title: "IDKit Standalone" +description: "Migrate from @worldcoin/idkit-standalone to @worldcoin/idkit-core." +"og:image": "https://raw.githubusercontent.com/worldcoin/developer-docs/main/images/docs/docs-meta.png" +"twitter:image": "https://raw.githubusercontent.com/worldcoin/developer-docs/main/images/docs/docs-meta.png" +--- + +{/* cspell:ignore idkit standalone rp_context app_id rp_id orblegacy signal_hash nullifier nullifiers verifyCloudProof pollUntilCompletion connectorURI */} + +This guide helps you migrate from `@worldcoin/idkit-standalone` to `@worldcoin/idkit-core`. The `idkit-standalone` package has been discontinued. If you used it +for a vanilla JavaScript or custom QR flow, migrate to `@worldcoin/idkit-core`. +ยก +## Migration Checklist + +1. Enable World ID 4.0 in the [Developer Portal](https://developer.world.org) and keep your `app_id`, `rp_id`, and server-only `signing_key`. +2. Install `@worldcoin/idkit-core`. +3. Add a backend endpoint that generates an RP signature. See [RP Signatures](/world-id/idkit/signatures). +4. Pick a legacy preset that matches your previous `verification_level` configuration. +5. Replace `verifyCloudProof(...)` with a backend POST to `https://developer.world.org/api/v4/verify/{rp_id}`. +6. Store the verified `nullifier` for replay protection. + +For the broader protocol migration, including proof types and timelines, see +[World ID 4.0](/world-id/4-0-migration). + +## Install + + +```bash npm +npm i @worldcoin/idkit-core +``` + +```bash pnpm +pnpm add @worldcoin/idkit-core +``` + +```bash yarn +yarn add @worldcoin/idkit-core +``` + + +## Request a Proof + +In standalone, the package mounted UI through browser globals: + +```ts title="Before" +import "@worldcoin/idkit-standalone"; + +IDKit.init({ + app_id: "app_xxxxx", + action: "my-action", + signal: "user-123", + verification_level: "orb", +}); + +await IDKit.open(); +``` + +With `idkit-core`, fetch an RP signature from your backend, build the request, +render the `connectorURI`, and poll until World App returns a proof. + +```ts title="After" +import { IDKit, orbLegacy } from "@worldcoin/idkit-core"; + +const action = "my-action"; +const signal = "user-123"; + +const rpContext = await fetch("/api/rp-signature", { + method: "POST", + headers: { "content-type": "application/json" }, + body: JSON.stringify({ action }), +}).then((r) => r.json()); + +const request = await IDKit.request({ + app_id: "app_xxxxx", + action, + rp_context: { + rp_id: "rp_xxxxx", + nonce: rpContext.nonce, + created_at: rpContext.created_at, + expires_at: rpContext.expires_at, + signature: rpContext.sig, + }, + allow_legacy_proofs: true, + environment: "production", +}).preset(orbLegacy({ signal })); + +renderQrCode(request.connectorURI); + +const completion = await request.pollUntilCompletion({ + pollInterval: 2_000, + timeout: 120_000, +}); + +if (!completion.success) { + throw new Error(`World ID verification failed: ${completion.error}`); +} + +await fetch("/api/verify-proof", { + method: "POST", + headers: { "content-type": "application/json" }, + body: JSON.stringify({ idkitResponse: completion.result }), +}); +``` + +## Credential Mapping + +Standalone used `verification_level` to choose what the user should prove. In +`idkit-core`, use a legacy preset instead. These presets are drop-in +replacements for the old verification levels. + + + The legacy presets will return the maximum credential a user has. For example, if a user has an Orb credential, but you request `documentLegacy`, they will verify with their Orb credential. + + +| Standalone | `idkit-core` preset | +| --- | --- | +| `verification_level: "orb"` | `orbLegacy({ signal })` | +| `verification_level: "secure_document"` | `secureDocumentLegacy({ signal })` | +| `verification_level: "document"` | `documentLegacy({ signal })` | +| `verification_level: "device"` | `deviceLegacy({ signal })` | + +```ts +import { + IDKit, + deviceLegacy, + documentLegacy, + orbLegacy, + secureDocumentLegacy, +} from "@worldcoin/idkit-core"; + +const request = await IDKit.request(config).preset( + orbLegacy({ signal: "user-123" }), +); +``` + + +## RP Signatures + +IDKit 4.x requests require `rp_context`, signed by your backend with the +Developer Portal `signing_key`. Do not generate signatures in client code. + +For implementation details, use the [RP Signatures](/world-id/idkit/signatures) +reference. It includes the JavaScript helper, the signing algorithm, and test +vectors for non-JavaScript backends. + +## Verify the Proof + +Standalone integrations usually verified with `verifyCloudProof(...)`: + +```ts title="Before" +import { verifyCloudProof } from "@worldcoin/idkit"; + +const response = await verifyCloudProof(proof, app_id, action, signal); +``` + +In IDKit 4.x, send the IDKit result to your backend and forward it directly to +the [v4 verify endpoint](/api-reference/developer-portal/verify). + +```ts title="After" +import type { IDKitResult } from "@worldcoin/idkit-core"; + +export async function POST(request: Request): Promise { + const { idkitResponse } = (await request.json()) as { + idkitResponse: IDKitResult; + }; + + const response = await fetch( + `https://developer.world.org/api/v4/verify/${process.env.WORLD_ID_RP_ID}`, + { + method: "POST", + headers: { "content-type": "application/json" }, + body: JSON.stringify(idkitResponse), + }, + ); + + return new Response(await response.text(), { + status: response.status, + headers: { "content-type": "application/json" }, + }); +} +``` + +## Store the Nullifier + +After `/api/v4/verify/{rp_id}` succeeds, store the verified `nullifier` for the +action and reject duplicates. During migration, keep checking any old +`nullifier_hash` records if the same user could have verified before the +upgrade.