Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion js/examples/nextjs/app/api/verify-proof/route.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { NextResponse } from "next/server";
import type { IDKitResult } from "@worldcoin/idkit";

// export const runtime = "nodejs";

export async function POST(request: Request): Promise<Response> {
try {
const body = (await request.json()) as {
rp_id?: string;
devPortalPayload?: unknown;
devPortalPayload?: IDKitResult;
};

const baseUrl =
Expand Down
2 changes: 2 additions & 0 deletions js/packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ export type {
export type {
// Uniqueness proof response types
IDKitResult,
IntegrityBundle,
IntegritySignatureFormat,
ResponseItemV4,
ResponseItemV3,
// Session proof response types
Expand Down
2 changes: 2 additions & 0 deletions js/packages/core/src/lib/wasm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ export type {
IDKitResult,
IDKitResultV3,
IDKitResultV4,
IntegrityBundle,
IntegritySignatureFormat,
// Session proof response types
IDKitResultSession,
ResponseItemSession,
Expand Down
70 changes: 70 additions & 0 deletions js/packages/core/src/transports/native.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,76 @@ describe("native transport request lifecycle", () => {
});
});

it("preserves integrity_bundle from v2.1 native responses", async () => {
const integrityBundle = {
version: 1,
signature_format: "android_keystore",
timestamp: 1709901234,
signature: "304502210",
jwt: "eyJhbGciOiJFUzI1NiIs",
} as const;

const req = createNativeRequest({}, baseConfig, {}, "");
activeRequest = req;

const completionPromise = req.pollUntilCompletion({ timeout: 1000 });

miniKitHandlers["miniapp-verify-action"]?.({
status: "success",
proof_response: {
id: "req_abc123",
version: 1,
responses: [
{
identifier: "face",
proof: proofResponseProof,
nullifier: proofResponseNullifier("a"),
issuer_schema_id: 11,
expires_at_min: 0,
},
],
},
integrity_bundle: integrityBundle,
});

const completion = await completionPromise;
expect(completion.success).toBe(true);
if (completion.success) {
expect(completion.result.integrity_bundle).toEqual(integrityBundle);
}
});

it("preserves integrity_bundle from legacy native responses", async () => {
const integrityBundle = {
version: 1,
signature_format: "apple_app_attest",
timestamp: 1709901234,
signature: "304502210",
jwt: "eyJhbGciOiJFUzI1NiIs",
} as const;

const req = createNativeRequest({}, baseConfig, {}, "");
activeRequest = req;

const completionPromise = req.pollUntilCompletion({ timeout: 1000 });

miniKitHandlers["miniapp-verify-action"]?.({
status: "success",
protocol_version: "3.0",
verification_level: "orb",
proof: "0x01",
merkle_root: "0x02",
nullifier_hash: "0x03",
integrity_bundle: integrityBundle,
});

const completion = await completionPromise;
expect(completion.success).toBe(true);
if (completion.success) {
expect(completion.result.integrity_bundle).toEqual(integrityBundle);
}
});

it("prefers response signal_hash over signal hashes map", async () => {
const signalHashes = { proof_of_human: hashSignal("from-constraints") };

Expand Down
21 changes: 19 additions & 2 deletions js/packages/core/src/transports/native.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import type {
} from "../request";
import type { IDKitResult } from "../types/result";
import { IDKitErrorCodes } from "../types/result";
import type { IDKitResultV3 } from "../lib/wasm";
import type { IDKitResultV3, IntegrityBundle } from "../lib/wasm";
import { WasmModule } from "../lib/wasm";
import { isDebug } from "../lib/debug";

Expand Down Expand Up @@ -374,6 +374,7 @@ function nativeResultToIDKitResult(
): IDKitResult {
const p = payload as Record<string, any>;
const rpNonce = config.rp_context?.nonce ?? "";
const integrity_bundle = normalizeIntegrityBundle(p);

// V4 response wrapped in `proof_response` envelope.
if ("proof_response" in p && p.proof_response != null) {
Expand All @@ -386,14 +387,17 @@ function nativeResultToIDKitResult(
),
});

return WasmModule.proofResponseToIDKitResult(proof_response, {
const result = WasmModule.proofResponseToIDKitResult(proof_response, {
nonce: rpNonce,
action: config.action,
action_description: config.action_description,
environment: config.environment ?? "production",
signal_hashes: signalHashes,
identity_attested: p.identity_attested,
}) as IDKitResult;

result.integrity_bundle = integrity_bundle;
return result;
}

// Protocol ProofResponse must be nested under `proof_response`.
Expand Down Expand Up @@ -426,6 +430,7 @@ function nativeResultToIDKitResult(
nullifier: v.nullifier_hash,
})),
environment: config.environment ?? "production",
integrity_bundle,
} satisfies IDKitResultV3;
}

Expand All @@ -447,5 +452,17 @@ function nativeResultToIDKitResult(
},
],
environment: config.environment ?? "production",
integrity_bundle,
} satisfies IDKitResultV3;
}

function normalizeIntegrityBundle(
payload: Record<string, any>,
): IntegrityBundle | undefined {
const integrityBundle = payload.integrity_bundle;
if (integrityBundle == null || typeof integrityBundle !== "object") {
return undefined;
}

return integrityBundle as IntegrityBundle;
}
2 changes: 2 additions & 0 deletions js/packages/core/src/types/result.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ export type {
IDKitResult,
ResponseItemV4,
ResponseItemV3,
IntegrityBundle,
IntegritySignatureFormat,
// Session proof response types
ResponseItemSession,
IDKitResultSession,
Expand Down
2 changes: 2 additions & 0 deletions js/packages/react/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ export type {
Preset,
ConstraintNode,
IDKitResult,
IntegrityBundle,
IntegritySignatureFormat,
IDKitResultSession,
IDKitRequestConfig,
IDKitSessionConfig,
Expand Down
Loading
Loading