diff --git a/demos/web2-auth/index.html b/demos/web2-auth/index.html
new file mode 100644
index 0000000000..fb7029e457
--- /dev/null
+++ b/demos/web2-auth/index.html
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+ Internet Identity
+
+
+
+
+
+
+
+
+
diff --git a/demos/web2-auth/package.json b/demos/web2-auth/package.json
new file mode 100644
index 0000000000..8a33daeb97
--- /dev/null
+++ b/demos/web2-auth/package.json
@@ -0,0 +1,18 @@
+{
+ "name": "web2-auth",
+ "version": "1.0.0",
+ "description": "",
+ "type": "module",
+ "dependencies": {
+ "@dfinity/sig-verifier-js": "*"
+ },
+ "devDependencies": {
+ "vite": "*"
+ },
+ "scripts": {
+ "check": "tsc --noEmit",
+ "vite": "NODE_OPTIONS='--experimental-wasm-modules' vite --config ./vite.config.ts"
+ },
+ "author": "",
+ "license": "ISC"
+}
diff --git a/demos/web2-auth/src/auth.ts b/demos/web2-auth/src/auth.ts
new file mode 100644
index 0000000000..68d056822f
--- /dev/null
+++ b/demos/web2-auth/src/auth.ts
@@ -0,0 +1,127 @@
+// TODO: deduplicate
+
+import type { SignIdentity, Signature } from "@dfinity/agent";
+import {
+ Delegation,
+ DelegationChain,
+ DelegationIdentity,
+ SignedDelegation,
+} from "@dfinity/identity";
+import { Principal } from "@dfinity/principal";
+
+// The type of response from II as per the spec
+interface AuthResponseSuccess {
+ kind: "authorize-client-success";
+ delegations: {
+ delegation: {
+ pubkey: Uint8Array;
+ expiration: bigint;
+ targets?: Principal[];
+ };
+ signature: Uint8Array;
+ }[];
+ userPublicKey: Uint8Array;
+}
+
+// Perform a sign in to II using parameters set in this app
+export const authWithII = async ({
+ url: url_,
+ maxTimeToLive,
+ derivationOrigin,
+ sessionPublicKey,
+}: {
+ url: string;
+ maxTimeToLive?: bigint;
+ derivationOrigin?: string;
+ sessionPublicKey: Uint8Array;
+}): Promise => {
+ // Figure out the II URL to use
+ const iiUrl = new URL(url_);
+ iiUrl.hash = "#authorize";
+
+ // Open an II window and kickstart the flow
+ const win = window.open(iiUrl, "ii-window");
+ if (win === null) {
+ throw new Error(`Could not open window for '${iiUrl}'`);
+ }
+
+ // Wait for II to say it's ready
+ const evnt = await new Promise((resolve) => {
+ const readyHandler = (e: MessageEvent) => {
+ window.removeEventListener("message", readyHandler);
+ resolve(e);
+ };
+ window.addEventListener("message", readyHandler);
+ });
+
+ if (evnt.data.kind !== "authorize-ready") {
+ throw new Error("Bad message from II window: " + JSON.stringify(evnt));
+ }
+
+ // Send the request to II
+ const request = {
+ kind: "authorize-client",
+ sessionPublicKey,
+ maxTimeToLive,
+ derivationOrigin,
+ };
+
+ win.postMessage(request, iiUrl.origin);
+
+ // Wait for the II response and update the local state
+ const response = await new Promise((resolve) => {
+ const responseHandler = (e: MessageEvent) => {
+ window.removeEventListener("message", responseHandler);
+ win.close();
+ resolve(e);
+ };
+ window.addEventListener("message", responseHandler);
+ });
+
+ const message = response.data;
+ if (message.kind !== "authorize-client-success") {
+ throw new Error("Bad reply: " + JSON.stringify(message));
+ }
+
+ return message;
+};
+
+// Read delegations the delegations from the response
+const identityFromResponse = ({
+ sessionIdentity,
+ response,
+}: {
+ sessionIdentity: SignIdentity;
+ response: AuthResponseSuccess;
+}): DelegationIdentity => {
+ const delegations = response.delegations.map(extractDelegation);
+
+ const delegationChain = DelegationChain.fromDelegations(
+ delegations,
+ response.userPublicKey.buffer
+ );
+
+ const identity = DelegationIdentity.fromDelegation(
+ sessionIdentity,
+ delegationChain
+ );
+
+ return identity;
+};
+
+// Infer the type of an array's elements
+type ElementOf = Arr extends readonly (infer ElementOf)[]
+ ? ElementOf
+ : "argument is not an array";
+
+export const extractDelegation = (
+ signedDelegation: ElementOf
+): SignedDelegation => ({
+ delegation: new Delegation(
+ signedDelegation.delegation.pubkey,
+ signedDelegation.delegation.expiration,
+ signedDelegation.delegation.targets
+ ),
+ signature: signedDelegation.signature
+ .buffer as Signature /* brand type for agent-js */,
+});
diff --git a/demos/web2-auth/src/index.ts b/demos/web2-auth/src/index.ts
new file mode 100644
index 0000000000..75074010cc
--- /dev/null
+++ b/demos/web2-auth/src/index.ts
@@ -0,0 +1,50 @@
+import { authWithII } from "./auth";
+
+const button = document.querySelector(
+ "[data-button-id=authenticate]"
+)! as HTMLButtonElement;
+const isAuthed = document.querySelector(
+ "[data-output-id=is-authed]"
+)! as HTMLOutputElement;
+
+export const uint8ArrayToHexString = (bytes: Uint8Array | number[]) => {
+ if (!(bytes instanceof Uint8Array)) {
+ bytes = Uint8Array.from(bytes);
+ }
+ return bytes.reduce(
+ (str, byte) => str + byte.toString(16).padStart(2, "0"),
+ ""
+ );
+};
+
+button.addEventListener("click", async () => {
+ const resp = await fetch("/challenge");
+ const obj: { challenge: string } = await resp.json();
+ const challenge = obj.challenge;
+ const delegationIdentity = await authWithII({
+ // The url needs to be aligned with the root key in the backend
+ // url: "http://internet_identity.localhost:5173",
+ url: "https://jqajs-xiaaa-aaaad-aab5q-cai.ic0.app/",
+ sessionPublicKey: new Uint8Array(Buffer.from(challenge, "base64")),
+ });
+ const data = { challenge, delegationIdentity };
+ await fetch("/verify", {
+ method: "POST",
+ body: JSON.stringify(data, (_, v) => {
+ if (typeof v === "bigint") {
+ // We need to expiration date to be hex string.
+ return v.toString(16);
+ }
+ if (v instanceof Uint8Array) {
+ // We need the keys to be hex strings.
+ return uint8ArrayToHexString(v);
+ }
+ return v;
+ }),
+ headers: new Headers({
+ "Content-Type": "application/json",
+ }),
+ });
+});
+
+button.disabled = false;
diff --git a/demos/web2-auth/tsconfig.json b/demos/web2-auth/tsconfig.json
new file mode 100644
index 0000000000..03ea203bfc
--- /dev/null
+++ b/demos/web2-auth/tsconfig.json
@@ -0,0 +1,7 @@
+{
+ "extends": "../../tsconfig.json",
+ "include": ["vite.config.ts", "./src"],
+ "compilerOptions": {
+ "composite": true
+ }
+}
diff --git a/demos/web2-auth/vite.config.ts b/demos/web2-auth/vite.config.ts
new file mode 100644
index 0000000000..9dc5f06a28
--- /dev/null
+++ b/demos/web2-auth/vite.config.ts
@@ -0,0 +1,131 @@
+import { validateDelegationAndGetPrincipal } from "@dfinity/sig-verifier-js/sig_verifier_js";
+import { IncomingMessage, ServerResponse } from "http";
+import type { Plugin, ViteDevServer } from "vite";
+import { defineConfig } from "vite";
+
+export async function createChallenge(): Promise {
+ // TODO: generate random challenge, store & add expiry
+ return "YSBjaGFsbGVuZ2UsIGkuZS4gYSBzdHJpbmcgb2YgYXQgbGVhc3QgMzIgYnl0ZXM=";
+}
+
+type Delegation = {
+ delegation: {
+ pubkey: string;
+ expiration: string;
+ };
+ signature: string;
+};
+
+type VerifyData = {
+ challenge: string;
+ authMethod: string;
+ delegationIdentity: {
+ kind: string;
+ delegations: Delegation[];
+ userPublicKey: string;
+ };
+};
+
+const ROOT_PUBLIC_KEY_RAW = new Uint8Array([
+ 0x81, 0x4c, 0x0e, 0x6e, 0xc7, 0x1f, 0xab, 0x58, 0x3b, 0x08, 0xbd, 0x81, 0x37,
+ 0x3c, 0x25, 0x5c, 0x3c, 0x37, 0x1b, 0x2e, 0x84, 0x86, 0x3c, 0x98, 0xa4, 0xf1,
+ 0xe0, 0x8b, 0x74, 0x23, 0x5d, 0x14, 0xfb, 0x5d, 0x9c, 0x0c, 0xd5, 0x46, 0xd9,
+ 0x68, 0x5f, 0x91, 0x3a, 0x0c, 0x0b, 0x2c, 0xc5, 0x34, 0x15, 0x83, 0xbf, 0x4b,
+ 0x43, 0x92, 0xe4, 0x67, 0xdb, 0x96, 0xd6, 0x5b, 0x9b, 0xb4, 0xcb, 0x71, 0x71,
+ 0x12, 0xf8, 0x47, 0x2e, 0x0d, 0x5a, 0x4d, 0x14, 0x50, 0x5f, 0xfd, 0x74, 0x84,
+ 0xb0, 0x12, 0x91, 0x09, 0x1c, 0x5f, 0x87, 0xb9, 0x88, 0x83, 0x46, 0x3f, 0x98,
+ 0x09, 0x1a, 0x0b, 0xaa, 0xae,
+]);
+
+export function verifyChallenge(data: VerifyData): string | undefined {
+ try {
+ const delegationChain = {
+ delegations: data.delegationIdentity.delegations,
+ publicKey: data.delegationIdentity.userPublicKey,
+ };
+ const currentTimeNanoSeconds = process.hrtime.bigint();
+ const res = validateDelegationAndGetPrincipal(
+ Uint8Array.from(Buffer.from(data.challenge, "base64")),
+ JSON.stringify(delegationChain),
+ currentTimeNanoSeconds,
+ "jqajs-xiaaa-aaaad-aab5q-cai",
+ ROOT_PUBLIC_KEY_RAW
+ );
+
+ return res;
+ } catch (e) {
+ console.error(e);
+ return undefined;
+ }
+}
+
+const handleChallenge = async (req: IncomingMessage, res: ServerResponse) => {
+ const challenge = await createChallenge();
+ res.statusCode = 200;
+ res.end(JSON.stringify({ challenge }));
+};
+
+const handleVerify = async (req: RequestWithBody, res: ServerResponse) => {
+ res.statusCode = 200;
+ const principal = verifyChallenge(req.body);
+ console.log("principal", principal);
+ // TODO: add cookie here on success
+ res.end(JSON.stringify({ status: "ok" }));
+};
+
+// Extend IncomingMessage to include body
+interface RequestWithBody extends IncomingMessage {
+ body?: any;
+}
+
+const bodyParserPlugin = (): Plugin => ({
+ name: "body-parser",
+ configureServer(server) {
+ server.middlewares.use(
+ async (req: RequestWithBody, res: ServerResponse, next) => {
+ // Only parse JSON bodies and only for POST requests
+ if (
+ req.method === "POST" &&
+ req.headers["content-type"] === "application/json"
+ ) {
+ let body = "";
+ req.on("data", (chunk) => {
+ body += chunk.toString(); // convert Buffer to string
+ });
+ req.on("end", () => {
+ try {
+ req.body = JSON.parse(body);
+ } catch (e: unknown) {
+ res.statusCode = 400;
+ return res.end("Error parsing JSON body");
+ }
+ next();
+ });
+ } else {
+ next();
+ }
+ }
+ );
+ },
+});
+
+const backendPlugin = (): Plugin => ({
+ name: "backend-plugin",
+ configureServer(server: ViteDevServer) {
+ server.middlewares.use(async (req, res, next) => {
+ if (req.url === "/challenge") {
+ return handleChallenge(req, res);
+ }
+ if (req.url === "/verify") {
+ return handleVerify(req, res);
+ }
+
+ return next();
+ });
+ },
+});
+
+export default defineConfig({
+ plugins: [bodyParserPlugin(), backendPlugin()],
+ server: { port: 5178 },
+});
diff --git a/package-lock.json b/package-lock.json
index dcd6872abd..fe078578d8 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -10,6 +10,7 @@
"license": "SEE LICENSE IN LICENSE.md",
"workspaces": [
"src/vc-api",
+ "demos/web2-auth",
"demos/test-app",
"demos/vc_issuer",
"src/vite-plugins",
@@ -63,6 +64,12 @@
"npm": ">=10.0.0 <11.0.0"
}
},
+ "demos/sig-verifier-js": {
+ "version": "1.0.0",
+ "extraneous": true,
+ "license": "ISC",
+ "devDependencies": {}
+ },
"demos/test-app": {
"name": "@dfinity/internet-identity-test-app",
"dependencies": {
@@ -107,6 +114,16 @@
"vite": "^4.5.3"
}
},
+ "demos/web2-auth": {
+ "version": "1.0.0",
+ "license": "ISC",
+ "dependencies": {
+ "@dfinity/sig-verifier-js": "*"
+ },
+ "devDependencies": {
+ "vite": "*"
+ }
+ },
"node_modules/@aashutoshrathi/word-wrap": {
"version": "1.2.6",
"dev": true,
@@ -1886,6 +1903,232 @@
"url": "https://github.com/sindresorhus/is?sponsor=1"
}
},
+ "node_modules/@swc/core": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.4.1.tgz",
+ "integrity": "sha512-3y+Y8js+e7BbM16iND+6Rcs3jdiL28q3iVtYsCviYSSpP2uUVKkp5sJnCY4pg8AaVvyN7CGQHO7gLEZQ5ByozQ==",
+ "dev": true,
+ "hasInstallScript": true,
+ "optional": true,
+ "peer": true,
+ "dependencies": {
+ "@swc/counter": "^0.1.2",
+ "@swc/types": "^0.1.5"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/swc"
+ },
+ "optionalDependencies": {
+ "@swc/core-darwin-arm64": "1.4.1",
+ "@swc/core-darwin-x64": "1.4.1",
+ "@swc/core-linux-arm-gnueabihf": "1.4.1",
+ "@swc/core-linux-arm64-gnu": "1.4.1",
+ "@swc/core-linux-arm64-musl": "1.4.1",
+ "@swc/core-linux-x64-gnu": "1.4.1",
+ "@swc/core-linux-x64-musl": "1.4.1",
+ "@swc/core-win32-arm64-msvc": "1.4.1",
+ "@swc/core-win32-ia32-msvc": "1.4.1",
+ "@swc/core-win32-x64-msvc": "1.4.1"
+ },
+ "peerDependencies": {
+ "@swc/helpers": "^0.5.0"
+ },
+ "peerDependenciesMeta": {
+ "@swc/helpers": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@swc/core-darwin-arm64": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.4.1.tgz",
+ "integrity": "sha512-ePyfx0348UbR4DOAW24TedeJbafnzha8liXFGuQ4bdXtEVXhLfPngprrxKrAddCuv42F9aTxydlF6+adD3FBhA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-darwin-x64": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.4.1.tgz",
+ "integrity": "sha512-eLf4JSe6VkCMdDowjM8XNC5rO+BrgfbluEzAVtKR8L2HacNYukieumN7EzpYCi0uF1BYwu1ku6tLyG2r0VcGxA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-linux-arm-gnueabihf": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.4.1.tgz",
+ "integrity": "sha512-K8VtTLWMw+rkN/jDC9o/Q9SMmzdiHwYo2CfgkwVT29NsGccwmNhCQx6XoYiPKyKGIFKt4tdQnJHKUFzxUqQVtQ==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-linux-arm64-gnu": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.4.1.tgz",
+ "integrity": "sha512-0e8p4g0Bfkt8lkiWgcdiENH3RzkcqKtpRXIVNGOmVc0OBkvc2tpm2WTx/eoCnes2HpTT4CTtR3Zljj4knQ4Fvw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-linux-arm64-musl": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.4.1.tgz",
+ "integrity": "sha512-b/vWGQo2n7lZVUnSQ7NBq3Qrj85GrAPPiRbpqaIGwOytiFSk8VULFihbEUwDe0rXgY4LDm8z8wkgADZcLnmdUA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-linux-x64-gnu": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.4.1.tgz",
+ "integrity": "sha512-AFMQlvkKEdNi1Vk2GFTxxJzbICttBsOQaXa98kFTeWTnFFIyiIj2w7Sk8XRTEJ/AjF8ia8JPKb1zddBWr9+bEQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-linux-x64-musl": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.4.1.tgz",
+ "integrity": "sha512-QX2MxIECX1gfvUVZY+jk528/oFkS9MAl76e3ZRvG2KC/aKlCQL0KSzcTSm13mOxkDKS30EaGRDRQWNukGpMeRg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-win32-arm64-msvc": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.4.1.tgz",
+ "integrity": "sha512-OklkJYXXI/tntD2zaY8i3iZldpyDw5q+NAP3k9OlQ7wXXf37djRsHLV0NW4+ZNHBjE9xp2RsXJ0jlOJhfgGoFA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-win32-ia32-msvc": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.4.1.tgz",
+ "integrity": "sha512-MBuc3/QfKX9FnLOU7iGN+6yHRTQaPQ9WskiC8s8JFiKQ+7I2p25tay2RplR9dIEEGgVAu6L7auv96LbNTh+FaA==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-win32-x64-msvc": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.4.1.tgz",
+ "integrity": "sha512-lu4h4wFBb/bOK6N2MuZwg7TrEpwYXgpQf5R7ObNSXL65BwZ9BG8XRzD+dLJmALu8l5N08rP/TrpoKRoGT4WSxw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/counter": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz",
+ "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==",
+ "dev": true,
+ "optional": true,
+ "peer": true
+ },
+ "node_modules/@swc/types": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.5.tgz",
+ "integrity": "sha512-myfUej5naTBWnqOCc/MdVOLVjXUXtIA+NpDrDBKJtLLg2shUjBu3cZmB/85RyitKc55+lUUyl7oRfLOvkr2hsw==",
+ "dev": true,
+ "optional": true,
+ "peer": true
+ },
"node_modules/@szmarczak/http-timer": {
"version": "5.0.1",
"dev": true,
@@ -13770,6 +14013,10 @@
"node": ">= 8"
}
},
+ "node_modules/web2-auth": {
+ "resolved": "demos/web2-auth",
+ "link": true
+ },
"node_modules/webcrypto-core": {
"version": "1.7.7",
"license": "MIT",
@@ -14659,7 +14906,6 @@
},
"src/sig-verifier-js": {
"name": "@dfinity/sig-verifier-js",
- "hasInstallScript": true,
"license": "SEE LICENSE IN LICENSE.md",
"devDependencies": {
"@dfinity/internet-identity-vite-plugins": "*",
@@ -14671,7 +14917,6 @@
},
"src/vc_util_js": {
"name": "@dfinity/vc_util_js",
- "hasInstallScript": true,
"license": "SEE LICENSE IN LICENSE.md",
"devDependencies": {
"@dfinity/internet-identity-vite-plugins": "*",
diff --git a/package.json b/package.json
index 137f25cb6c..0855589da7 100644
--- a/package.json
+++ b/package.json
@@ -81,6 +81,7 @@
},
"workspaces": [
"src/vc-api",
+ "demos/web2-auth",
"demos/test-app",
"demos/vc_issuer",
"src/vite-plugins",
diff --git a/tsconfig.all.json b/tsconfig.all.json
index d39d7af8e7..17a9bf0bc2 100644
--- a/tsconfig.all.json
+++ b/tsconfig.all.json
@@ -5,6 +5,7 @@
"references": [
{ "path": "./src/vc-api" },
{ "path": "./src/sig-verifier-js" },
+ { "path": "./demos/web2-auth" },
{ "path": "./demos/test-app" },
{ "path": "./demos/vc_issuer" },
{ "path": "./src/vite-plugins" }