From 131d93255c2fc0519518b6253603309742b24da9 Mon Sep 17 00:00:00 2001 From: Jeremie Charrier Date: Tue, 16 Jun 2026 11:37:01 +0200 Subject: [PATCH] [WALLET-63] Remove PAR from browser distribution Pushed Authorization Requests require sending the client_secret, so move PAR (and client_secret handling) out of the browser-reachable base client into the Node-only client. The browser distribution can no longer make PAR requests or hold a secret. Also: - Right-size init() params per export: BrowserInitParams vs NodeInitParams, with request-building fields validated at call time. - Introduce a named TrustRoot ("development" | "production") for verification; verify() requires it explicitly (no derivation from environment). - camelCase consumer-authored params (clientId, callbackUri, responseMode, loginHint, transactionData); map to snake_case at the wire boundary. - ProofCredentialV1 exposes idiomatic property accessors instead of zero-arg getter methods. - Standardize thrown errors as strings. - Update README to match the new API. Co-Authored-By: Claude Opus 4.8 (1M context) --- README.md | 64 ++++++------ src/certificates/chain_validator.ts | 12 +-- src/certificates/trust_store/index.ts | 11 +- src/index.browser.ts | 5 + src/index.node.ts | 7 ++ src/presentation/base_client.ts | 144 +++++++++++--------------- src/presentation/node_client.ts | 97 ++++++++++++++++- src/proof_credentials.ts | 50 +++------ src/types.ts | 1 + src/vc_presentation.browser.ts | 6 +- src/vc_presentation.node.ts | 10 +- 11 files changed, 227 insertions(+), 180 deletions(-) diff --git a/README.md b/README.md index 2bf0046..c6766df 100644 --- a/README.md +++ b/README.md @@ -42,9 +42,9 @@ import { init } from "@proof.com/proof-vc-common"; init({ environment: "sandbox", - client_id: "verifier-demo", - response_mode: "direct_post", - callback_uri: "http://localhost/verify_vp_token", + clientId: "verifier-demo", + responseMode: "direct_post", + callbackUri: "http://localhost/verify_vp_token", }); ``` @@ -54,7 +54,7 @@ Proof supports `fragment` and `direct_post` response modes. #### fragment -Using `fragment` the `vp_token` is returned as a fragment of the `callback_uri` when the user is 302 redirected from Proof to your website. +Using `fragment` the `vp_token` is returned as a fragment of the `callbackUri` when the user is 302 redirected from Proof to your website. ``` GET http://localhost/verify_vp_token#vp_token=eyJwcm9vZl9pZF9... @@ -62,7 +62,7 @@ GET http://localhost/verify_vp_token#vp_token=eyJwcm9vZl9pZF9... #### direct_post -Using `direct_post` the `vp_token` is returned in the JSON body of a POST request to the `callback_uri` from Proof to your website. See the [OID4VP specification](https://openid.net/specs/openid-4-verifiable-presentations-1_0.html#name-response-mode-direct_post) for more details. +Using `direct_post` the `vp_token` is returned in the JSON body of a POST request to the `callbackUri` from Proof to your website. See the [OID4VP specification](https://openid.net/specs/openid-4-verifiable-presentations-1_0.html#name-response-mode-direct_post) for more details. ``` POST http://localhost/verify_vp_token @@ -73,14 +73,16 @@ POST http://localhost/verify_vp_token Proof supports [Pushed Authorization Requests](https://datatracker.ietf.org/doc/html/rfc9126) (PAR). You may want to use this feature when using [Transaction Templates](#transaction-templates) to avoid hitting URL size limits. +Note that PAR is available **only from the Node.js distribution**. ```javascript init({ environment: "sandbox", - client_id: "caxdw5a7d", - response_mode: "direct_post", - callback_uri: "http://localhost/verify_vp_token", - use_pushed_authorization_request: true, + clientId: "caxdw5a7d", + clientSecret: "…", + responseMode: "direct_post", + callbackUri: "http://localhost/verify_vp_token", + usePushedAuthorizationRequest: true, }); ``` @@ -110,11 +112,11 @@ Request a Verifiable Credential Presentation with an [OAuth 2.0](https://datatra ```javascript import { getAuthorizationRequestURL } from "@proof.com/proof-vc-common"; -const redirect = getAuthorizationRequestURL({ +const redirect = await getAuthorizationRequestURL({ nonce: "3e8e4918-e9fb-453a-a538-81152be15c1b", scope: "urn:proof:params:scope:verifiable-credentials:basic", state: "6A2B4CD830", - login_hint: "frodo.baggins@theshire", + loginHint: "frodo.baggins@theshire", }); window.location.href = redirect; @@ -162,12 +164,12 @@ const data = transactionData.wireInstructions({ currency: "USD", memo: "Invoice #2024-089", }); -const redirect = getAuthorizationRequestURL({ +const redirect = await getAuthorizationRequestURL({ nonce: "3e8e4918-e9fb-453a-a538-81152be15c1b", scope: "urn:proof:params:scope:verifiable-credentials:basic", state: "6A2B4CD830", - login_hint: "frodo.baggins@theshire", - transaction_data: data, + loginHint: "frodo.baggins@theshire", + transactionData: data, }); ``` @@ -190,12 +192,12 @@ const data = transactionData.paymentItemized({ { quantity: 2, unit_cost: 11.4, label: "Fees" }, ], }); -const redirect = getAuthorizationRequestURL({ +const redirect = await getAuthorizationRequestURL({ nonce: "3e8e4918-e9fb-453a-a538-81152be15c1b", scope: "urn:proof:params:scope:verifiable-credentials:basic", state: "6A2B4CD830", - login_hint: "frodo.baggins@theshire", - transaction_data: data, + loginHint: "frodo.baggins@theshire", + transactionData: data, }); ``` @@ -225,12 +227,12 @@ const data = transactionData.paymentMandate({ amount: 500, currency: "USD", }); -const redirect = getAuthorizationRequestURL({ +const redirect = await getAuthorizationRequestURL({ nonce: "3e8e4918-e9fb-453a-a538-81152be15c1b", scope: "urn:proof:params:scope:verifiable-credentials:basic", state: "6A2B4CD830", - login_hint: "frodo.baggins@theshire", - transaction_data: data, + loginHint: "frodo.baggins@theshire", + transactionData: data, }); ``` @@ -241,20 +243,16 @@ Decode and verify a Verifiable Presentation's `vp_token` server-side: ```javascript import { init, verifyVPToken } from "@proof.com/proof-vc-common"; -init({ - environment: "sandbox", - client_id: "verifier-demo", - callback_uri: "https://demo.next.proof.com/", -}); +init({ trustRoot: "production" }); const vpToken = "eyJwcm9vZl9pZ..."; -const presentation = verifyVPToken({ +const presentation = await verifyVPToken({ encodedVPToken: vpToken, nonce: "3e8e4918-e9fb-453a-a538-81152be15c1b", }); const verifiableCredential = presentation["proof_id_default"][0]; -if (verifiableCredential.isOver18()) { +if (verifiableCredential.isOver18) { purchaseItem(); } else { userNotOver18(); @@ -266,19 +264,15 @@ Verify a single SD-JWT-VC: ```javascript import { init, verify } from "@proof.com/proof-vc-common"; -init({ - environment: "sandbox", - client_id: "verifier-demo", - callback_uri: "https://demo.next.proof.com/", -}); +init({ trustRoot: "production" }); const encodedSDJWT = "eyJraWQiOiI3..."; -const verifiableCredential = verify({ +const verifiableCredential = await verify({ encodedSDJWT, nonce: "3e8e4918-e9fb-453a-a538-81152be15c1b", }); -if (verifiableCredential.isOver18()) { +if (verifiableCredential.isOver18) { purchaseItem(); } else { userNotOver18(); @@ -293,7 +287,7 @@ following the CA/B Forum Baseline Requirements for the Issuance and Management o The Proof Root CA R1 Certificate is published at http://cert.proof.com/proof-root-ca-r1.crt and is also committed in this repository [proof-root-ca-r1.crt](src/certificates/trust_store/proof_root_ca_r1.ts). -The sandbox Root CA R1 Development certificate is also committed in this repository [proof-root-ca-r1-development.crt](src/certificates/trust_store/proof_root_ca_r1_development.ts) and used when `environment: "sandbox"`. +The sandbox Root CA R1 Development certificate is also committed in this repository [proof-root-ca-r1-development.crt](src/certificates/trust_store/proof_root_ca_r1_development.ts) and used when `trustRoot: "development"`. ## Documentation diff --git a/src/certificates/chain_validator.ts b/src/certificates/chain_validator.ts index 7bb4f93..448d5ef 100644 --- a/src/certificates/chain_validator.ts +++ b/src/certificates/chain_validator.ts @@ -5,7 +5,7 @@ export function verifyChain( root: X509Certificate, ): void { if (chain.length === 0) { - throw new Error("verifyChain: empty chain"); + throw "verifyChain: empty chain"; } const full = [...chain, root]; @@ -18,20 +18,20 @@ export function verifyChain( const validFrom = new Date(cert.validFromDate); const validTo = new Date(cert.validToDate); if (now < validFrom || now > validTo) { - throw new Error(`Certificate at index ${i} is expired or not yet valid`); + throw `Certificate at index ${i} is expired or not yet valid`; } if (!cert.checkIssued(issuer)) { - throw new Error(`Certificate at index ${i} not issued by next in chain`); + throw `Certificate at index ${i} not issued by next in chain`; } if (!cert.verify(issuer.publicKey)) { - throw new Error(`Certificate at index ${i} has invalid signature`); + throw `Certificate at index ${i} has invalid signature`; } } if (now > new Date(root.validToDate)) { - throw new Error("Root certificate expired"); + throw "Root certificate expired"; } if (!root.verify(root.publicKey)) { - throw new Error("Root is not self-signed"); + throw "Root is not self-signed"; } } diff --git a/src/certificates/trust_store/index.ts b/src/certificates/trust_store/index.ts index 1abd9e0..871af10 100644 --- a/src/certificates/trust_store/index.ts +++ b/src/certificates/trust_store/index.ts @@ -1,19 +1,16 @@ import { X509Certificate } from "node:crypto"; -import type { Environment } from "../../types.ts"; +import type { TrustRoot } from "../../types.ts"; import { PROOF_ROOT_CA_R1_PEM } from "./proof_root_ca_r1.ts"; import { PROOF_ROOT_CA_R1_DEVELOPMENT_PEM } from "./proof_root_ca_r1_development.ts"; const PRODUCTION_ROOT = new X509Certificate(PROOF_ROOT_CA_R1_PEM); const DEVELOPMENT_ROOT = new X509Certificate(PROOF_ROOT_CA_R1_DEVELOPMENT_PEM); -export function getTrustRoot(env: Environment): X509Certificate { - switch (env) { +export function getTrustRoot(trustRoot: TrustRoot): X509Certificate { + switch (trustRoot) { case "production": return PRODUCTION_ROOT; - case "localhost": - case "next": - case "staging": - case "sandbox": + case "development": return DEVELOPMENT_ROOT; } } diff --git a/src/index.browser.ts b/src/index.browser.ts index b3545ac..14246c5 100644 --- a/src/index.browser.ts +++ b/src/index.browser.ts @@ -14,4 +14,9 @@ export type { export { TX_DATA_TYPE, transactionData } from "./transaction_data.ts"; +export type { + BrowserInitParams, + AuthorizationRequestParams, +} from "./presentation/base_client.ts"; + export { init, getAuthorizationRequestURL } from "./vc_presentation.browser.ts"; diff --git a/src/index.node.ts b/src/index.node.ts index ce72f08..6721b74 100644 --- a/src/index.node.ts +++ b/src/index.node.ts @@ -16,6 +16,13 @@ export { TX_DATA_TYPE, transactionData } from "./transaction_data.ts"; export { ProofCredentialV1 } from "./proof_credentials.ts"; +export type { AuthorizationRequestParams } from "./presentation/base_client.ts"; +export type { + NodeInitParams, + VerifyParams, + VerifyVPTokenParams, +} from "./presentation/node_client.ts"; + export { init, getAuthorizationRequestURL, diff --git a/src/presentation/base_client.ts b/src/presentation/base_client.ts index e06d819..91dfc75 100644 --- a/src/presentation/base_client.ts +++ b/src/presentation/base_client.ts @@ -9,62 +9,66 @@ import { type TransactionData, } from "../transaction_data.ts"; -export type VCPresentationClientParams = { +export type BrowserInitParams = { environment: Environment; - client_id: string; - client_secret?: string; - use_pushed_authorization_request?: boolean; - response_mode?: ResponseMode; - callback_uri: string; + clientId: string; + callbackUri: string; + responseMode?: ResponseMode; }; export type AuthorizationRequestParams = { scope: Scope; nonce: string; state?: string; - login_hint?: string; - transaction_data?: TransactionData | string; + loginHint?: string; + transactionData?: TransactionData | string; }; export class VCPresentationClient { - protected readonly environment: Environment; - protected readonly client_id: string; - protected readonly client_secret?: string; - protected readonly use_pushed_authorization_request: boolean = false; - protected readonly response_mode: ResponseMode = "fragment"; - protected readonly response_type: ResponseType = "vp_token"; - protected readonly callback_uri: string; - protected readonly oid4vp_uri = "/verifiable-credentials/v1/presentation"; + protected readonly environment?: Environment; + protected readonly clientId?: string; + protected readonly responseMode: ResponseMode = "fragment"; + protected readonly responseType: ResponseType = "vp_token"; + protected readonly callbackUri?: string; + protected readonly oid4vpUri = "/verifiable-credentials/v1/presentation"; - constructor({ - environment, - client_id, - client_secret, - use_pushed_authorization_request, - response_mode, - callback_uri, - }: VCPresentationClientParams) { - this.environment = environment; - this.client_id = client_id; - this.callback_uri = callback_uri; - - if (client_secret !== undefined) { - this.client_secret = client_secret; + constructor(params: { + environment?: Environment; + clientId?: string; + responseMode?: ResponseMode; + callbackUri?: string; + }) { + if (params.environment !== undefined) { + this.environment = params.environment; + } + if (params.clientId !== undefined) { + this.clientId = params.clientId; } - if (use_pushed_authorization_request !== undefined) { - this.use_pushed_authorization_request = use_pushed_authorization_request; + if (params.callbackUri !== undefined) { + this.callbackUri = params.callbackUri; } - if (response_mode !== undefined) { - this.response_mode = response_mode; + if (params.responseMode !== undefined) { + this.responseMode = params.responseMode; } } public async getAuthorizationRequestURL( params: AuthorizationRequestParams, ): Promise { - return this.use_pushed_authorization_request - ? this.pushAuthorizationRequest(params) - : this.buildAuthorizeURL(params); + this.requireRequestConfig(); + return this.buildAuthorizeURL(params); + } + + protected requireRequestConfig(): void { + if (this.environment === undefined) { + throw "getAuthorizationRequestURL requires `environment` in init()"; + } + if (this.clientId === undefined) { + throw "getAuthorizationRequestURL requires `clientId` in init()"; + } + if (this.callbackUri === undefined) { + throw "getAuthorizationRequestURL requires `callbackUri` in init()"; + } } protected baseURL(): string { @@ -79,78 +83,50 @@ export class VCPresentationClient { return "https://api.fairfax.proof.com"; case "production": return "https://api.proof.com"; + default: + throw "getAuthorizationRequestURL requires `environment` in init()"; } } - private buildAuthorizeURL(params: AuthorizationRequestParams): string { - const url = new URL(`${this.oid4vp_uri}/authorize`, this.baseURL()); + protected buildAuthorizeURL(params: AuthorizationRequestParams): string { + const url = new URL(`${this.oid4vpUri}/authorize`, this.baseURL()); url.search = this.buildParameters(params).toString(); return url.toString(); } - private async pushAuthorizationRequest( - params: AuthorizationRequestParams, - ): Promise { - const parURL = new URL(`${this.oid4vp_uri}/par`, this.baseURL()).toString(); - const response = await fetch(parURL, { - method: "POST", - headers: { "Content-Type": "application/x-www-form-urlencoded" }, - body: this.buildParameters(params).toString(), - }); - const data = await response.json(); - - if (!response.ok) { - throw `${data["error"]}: ${data["error_description"]}`; - } - - const authorizeURL = new URL( - `${this.oid4vp_uri}/authorize`, - this.baseURL(), - ); - authorizeURL.search = new URLSearchParams({ - client_id: this.client_id, - request_uri: data["request_uri"], - }).toString(); - - return authorizeURL.toString(); - } - - private buildParameters({ + protected buildParameters({ scope, nonce, state, - login_hint, - transaction_data, + loginHint, + transactionData, }: AuthorizationRequestParams): URLSearchParams { const encodedTransactionData = - typeof transaction_data === "object" - ? encodeTransactionData(transaction_data) - : transaction_data; + typeof transactionData === "object" + ? encodeTransactionData(transactionData) + : transactionData; return new URLSearchParams({ ...this.defaultAuthorizationRequestParameters(), scope, nonce, ...(state !== undefined && { state }), - ...(login_hint !== undefined && { login_hint }), + ...(loginHint !== undefined && { login_hint: loginHint }), ...(encodedTransactionData !== undefined && { transaction_data: encodedTransactionData, }), }); } - private defaultAuthorizationRequestParameters() { + protected defaultAuthorizationRequestParameters(): Record { return { - client_id: this.client_id, - ...(this.client_secret !== undefined && { - client_secret: this.client_secret, - }), - response_mode: this.response_mode, - response_type: this.response_type, - ...(this.response_mode === "fragment" && { - redirect_uri: this.callback_uri, + client_id: this.clientId!, + response_mode: this.responseMode, + response_type: this.responseType, + ...(this.responseMode === "fragment" && { + redirect_uri: this.callbackUri!, }), - ...(this.response_mode === "direct_post" && { - response_uri: this.callback_uri, + ...(this.responseMode === "direct_post" && { + response_uri: this.callbackUri!, }), }; } diff --git a/src/presentation/node_client.ts b/src/presentation/node_client.ts index 85e0b57..dd81c1a 100644 --- a/src/presentation/node_client.ts +++ b/src/presentation/node_client.ts @@ -5,12 +5,31 @@ import type { JwtPayload } from "@sd-jwt/types"; import { ES256, ES384, ES512, hasher } from "@owf/crypto"; import { base64urlDecode } from "@owf/identity-common"; -import type { ProofCredential, VPToken } from "../types.ts"; +import type { + Environment, + ProofCredential, + ResponseMode, + TrustRoot, + VPToken, +} from "../types.ts"; import { credentialIdAsType } from "../utils.ts"; import { getProofCredential } from "../proof_credential_factory.ts"; import { verifyChain } from "../certificates/chain_validator.ts"; import { getTrustRoot } from "../certificates/trust_store/index.ts"; -import { VCPresentationClient } from "./base_client.ts"; +import { + VCPresentationClient, + type AuthorizationRequestParams, +} from "./base_client.ts"; + +export type NodeInitParams = { + trustRoot?: TrustRoot; + environment?: Environment; + clientId?: string; + clientSecret?: string; + callbackUri?: string; + responseMode?: ResponseMode; + usePushedAuthorizationRequest?: boolean; +}; export type VerifyParams = { encodedSDJWT: string; @@ -56,6 +75,78 @@ function kbVerifierFor(kbAlg: SupportedAlg) { } export class NodeVCPresentationClient extends VCPresentationClient { + protected readonly clientSecret?: string; + protected readonly usePushedAuthorizationRequest: boolean = false; + protected readonly trustRoot?: TrustRoot; + + constructor(params: NodeInitParams) { + super(params); + if (params.clientSecret !== undefined) { + this.clientSecret = params.clientSecret; + } + if (params.usePushedAuthorizationRequest !== undefined) { + this.usePushedAuthorizationRequest = params.usePushedAuthorizationRequest; + } + if (params.trustRoot !== undefined) { + this.trustRoot = params.trustRoot; + } + } + + public override async getAuthorizationRequestURL( + params: AuthorizationRequestParams, + ): Promise { + this.requireRequestConfig(); + return this.usePushedAuthorizationRequest + ? this.pushAuthorizationRequest(params) + : this.buildAuthorizeURL(params); + } + + protected override defaultAuthorizationRequestParameters(): Record< + string, + string + > { + return { + ...super.defaultAuthorizationRequestParameters(), + ...(this.clientSecret !== undefined && { + client_secret: this.clientSecret, + }), + }; + } + + protected async pushAuthorizationRequest( + params: AuthorizationRequestParams, + ): Promise { + if (this.clientSecret === undefined) { + throw "pushed authorization requests require `clientSecret` in init()"; + } + const parURL = new URL(`${this.oid4vpUri}/par`, this.baseURL()).toString(); + const response = await fetch(parURL, { + method: "POST", + headers: { "Content-Type": "application/x-www-form-urlencoded" }, + body: this.buildParameters(params).toString(), + }); + const data = await response.json(); + + if (!response.ok) { + throw `${data["error"]}: ${data["error_description"]}`; + } + + const authorizeURL = new URL(`${this.oid4vpUri}/authorize`, this.baseURL()); + authorizeURL.search = new URLSearchParams({ + client_id: this.clientId!, + request_uri: data["request_uri"], + }).toString(); + + return authorizeURL.toString(); + } + + protected requireTrustRoot(): TrustRoot { + if (this.trustRoot === undefined) { + throw "verify requires `trustRoot` in init()"; + } + return this.trustRoot; + } + public async verify({ encodedSDJWT, nonce, @@ -92,7 +183,7 @@ export class NodeVCPresentationClient extends VCPresentationClient { const chain = x5c.map( (b64) => new X509Certificate(Buffer.from(b64 as string, "base64")), ); - verifyChain(chain, getTrustRoot(this.environment)); + verifyChain(chain, getTrustRoot(this.requireTrustRoot())); const leafJwk = chain[0]!.publicKey.export({ format: "jwk" }); if (leafJwk.crv !== EXPECTED_CURVE[alg]) { diff --git a/src/proof_credentials.ts b/src/proof_credentials.ts index c053d00..12d0c3e 100644 --- a/src/proof_credentials.ts +++ b/src/proof_credentials.ts @@ -39,21 +39,21 @@ type ProofCredentialV1Params = { } & CredentialParams; export class ProofCredentialV1 extends Credential { - private readonly given_name: string | undefined; - private readonly family_name: string | undefined; + public readonly givenName: string | undefined; + public readonly familyName: string | undefined; + public readonly isOver18: boolean | undefined; + public readonly isOver21: boolean | undefined; + public readonly isOver65: boolean | undefined; private readonly birth_date: string | undefined; - private readonly is_over_18: boolean | undefined; - private readonly is_over_21: boolean | undefined; - private readonly is_over_65: boolean | undefined; constructor(params: ProofCredentialV1Params) { super(params); - this.given_name = params.given_name; - this.family_name = params.family_name; + this.givenName = params.given_name; + this.familyName = params.family_name; this.birth_date = params.birth_date; - this.is_over_18 = params.is_over_18; - this.is_over_21 = params.is_over_21; - this.is_over_65 = params.is_over_65; + this.isOver18 = params.is_over_18; + this.isOver21 = params.is_over_21; + this.isOver65 = params.is_over_65; } public credentialType(): CredentialType { @@ -64,31 +64,9 @@ export class ProofCredentialV1 extends Credential { return "dc+sd-jwt"; } - public givenName(): string | undefined { - return this.given_name; - } - - public familyName(): string | undefined { - return this.family_name; - } - - public dateOfBirth(): Date | undefined { - if (this.birth_date !== undefined) { - return new Date(this.birth_date); - } else { - return undefined; - } - } - - public isOver18(): boolean | undefined { - return this.is_over_18; - } - - public isOver21(): boolean | undefined { - return this.is_over_21; - } - - public isOver65(): boolean | undefined { - return this.is_over_65; + public get dateOfBirth(): Date | undefined { + return this.birth_date !== undefined + ? new Date(this.birth_date) + : undefined; } } diff --git a/src/types.ts b/src/types.ts index c23051a..65add22 100644 --- a/src/types.ts +++ b/src/types.ts @@ -6,6 +6,7 @@ export type Environment = | "staging" | "sandbox" | "production"; +export type TrustRoot = "development" | "production"; export type ResponseMode = "fragment" | "direct_post"; export type ResponseType = "vp_token"; export type Scope = "urn:proof:params:scope:verifiable-credentials:basic"; diff --git a/src/vc_presentation.browser.ts b/src/vc_presentation.browser.ts index d395616..ddb0b6f 100644 --- a/src/vc_presentation.browser.ts +++ b/src/vc_presentation.browser.ts @@ -1,14 +1,14 @@ import { VCPresentationClient, - type VCPresentationClientParams, + type BrowserInitParams, type AuthorizationRequestParams, } from "./presentation/base_client.ts"; let instance: VCPresentationClient | null = null; -export function init(params: VCPresentationClientParams): void { +export function init(params: BrowserInitParams): void { if (params.environment === "production" && instance) - throw new Error("VCPresentationClient already initialized (browser)"); + throw "VCPresentationClient already initialized (browser)"; instance = new VCPresentationClient(params); } diff --git a/src/vc_presentation.node.ts b/src/vc_presentation.node.ts index 379d202..ef451b2 100644 --- a/src/vc_presentation.node.ts +++ b/src/vc_presentation.node.ts @@ -1,9 +1,7 @@ -import type { - VCPresentationClientParams, - AuthorizationRequestParams, -} from "./presentation/base_client.ts"; +import type { AuthorizationRequestParams } from "./presentation/base_client.ts"; import { NodeVCPresentationClient, + type NodeInitParams, type VerifyParams, type VerifyVPTokenParams, } from "./presentation/node_client.ts"; @@ -11,9 +9,9 @@ import type { ProofCredential, VPToken } from "./types.ts"; let instance: NodeVCPresentationClient | null = null; -export function init(params: VCPresentationClientParams): void { +export function init(params: NodeInitParams): void { if (params.environment === "production" && instance) - throw new Error("NodeVCPresentationClient already initialized (node)"); + throw "NodeVCPresentationClient already initialized (node)"; instance = new NodeVCPresentationClient(params); }