From 78b3759008ce3fc1111d779ee74e448b70f9ab23 Mon Sep 17 00:00:00 2001 From: Takis Kakalis <80459599+Takaros999@users.noreply.github.com> Date: Thu, 2 Apr 2026 18:08:54 +0300 Subject: [PATCH 1/2] feat: Expose session api --- .../nextjs/app/api/rp-signature/route.ts | 4 +- js/examples/nextjs/app/ui.tsx | 134 +++++++++++++++--- js/packages/core/src/index.ts | 6 + js/packages/core/src/request.ts | 9 +- js/packages/react/src/index.ts | 3 + 5 files changed, 132 insertions(+), 24 deletions(-) diff --git a/js/examples/nextjs/app/api/rp-signature/route.ts b/js/examples/nextjs/app/api/rp-signature/route.ts index c2ec810..25df8b7 100644 --- a/js/examples/nextjs/app/api/rp-signature/route.ts +++ b/js/examples/nextjs/app/api/rp-signature/route.ts @@ -6,13 +6,13 @@ import { signRequest } from "@worldcoin/idkit/signing"; export async function POST(request: Request): Promise { try { const body = (await request.json()) as { - action: string; + action?: string; ttl?: number; }; const signingKey = process.env.RP_SIGNING_KEY; const { sig, nonce, createdAt, expiresAt } = signRequest({ - action: body.action, + ...(body.action ? { action: body.action } : {}), signingKeyHex: signingKey!, ttl: body.ttl, }); diff --git a/js/examples/nextjs/app/ui.tsx b/js/examples/nextjs/app/ui.tsx index a8ca40a..aeeda30 100644 --- a/js/examples/nextjs/app/ui.tsx +++ b/js/examples/nextjs/app/ui.tsx @@ -7,11 +7,13 @@ import { deviceLegacy, selfieCheckLegacy, IDKitRequestWidget, + IDKitSessionWidget, orbLegacy, secureDocumentLegacy, setDebug, type ConstraintNode, type IDKitResult, + type IDKitResultSession, type RpContext, Preset, } from "@worldcoin/idkit"; @@ -71,11 +73,11 @@ function createPreset(kind: PresetKind, signal: string) { } } -async function fetchRpContext(action: string): Promise { +async function fetchRpContext(action?: string): Promise { const response = await fetch("/api/rp-signature", { method: "POST", headers: { "content-type": "application/json" }, - body: JSON.stringify({ action }), + body: JSON.stringify(action ? { action } : {}), }); if (!response.ok) { @@ -149,6 +151,12 @@ export function DemoClient(): ReactElement { const [genesisEnabled, setGenesisEnabled] = useState(false); const [genesisDate, setGenesisDate] = useState(""); const [isGenesisTooltipOpen, setIsGenesisTooltipOpen] = useState(false); + const [flowType, setFlowType] = useState<"uniqueness" | "session">( + "uniqueness", + ); + const [sessionId, setSessionId] = useState(""); + const [widgetSessionResult, setWidgetSessionResult] = + useState(null); const [useReturnTo, setUseReturnTo] = useState(false); const [returnTo, setReturnTo] = useState(""); const [isReturnToTooltipOpen, setIsReturnToTooltipOpen] = useState(false); @@ -208,6 +216,8 @@ export function DemoClient(): ReactElement { if (worldIdVersion !== "4.0") { setGenesisEnabled(false); setGenesisDate(""); + setFlowType("uniqueness"); + setSessionId(""); } }, [worldIdVersion]); @@ -223,13 +233,18 @@ export function DemoClient(): ReactElement { ); }, []); + const isSessionFlow = worldIdVersion === "4.0" && flowType === "session"; + const startWidgetFlow = async () => { setWidgetError(null); setWidgetVerifyResult(null); setWidgetIdkitResult(null); + setWidgetSessionResult(null); try { - const rpContext = await fetchRpContext(action || "test-action"); + const rpContext = isSessionFlow + ? await fetchRpContext() + : await fetchRpContext(action || "test-action"); setWidgetSignal(`demo-signal-${Date.now()}`); setWidgetRpContext(rpContext); setWidgetOpen(true); @@ -275,15 +290,17 @@ export function DemoClient(): ReactElement { -
- - setAction(e.target.value)} - /> -
+ {!isSessionFlow && ( +
+ + setAction(e.target.value)} + /> +
+ )}
+ setFlowType(e.target.value as "uniqueness" | "session") + } + > + + + +
+ {flowType === "session" && ( +
+ + setSessionId(e.target.value)} + placeholder="session_... (optional, for returning users)" + /> +
+ )}