UNPKG

@sphereon/ssi-sdk.presentation-exchange

Version:

619 lines (614 loc) • 23.5 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); var __commonJS = (cb, mod) => function __require() { return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; }; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // plugin.schema.json var require_plugin_schema = __commonJS({ "plugin.schema.json"(exports, module2) { module2.exports = { IDidAuthSiopOpAuthenticator: { components: { schemas: { IGetSiopSessionArgs: { type: "object", properties: { sessionId: { type: "string" }, additionalProperties: false }, required: ["sessionId"], description: "Arguments needed for {@link DidAuthSiopOpAuthenticator.getSessionForSiop } " }, IRegisterSiopSessionArgs: { type: "object", properties: { identifier: { type: "object", properties: { did: { type: "string" }, alias: { type: "string" }, provider: { type: "string" }, controllerKeyId: { type: "string" }, keys: { type: "array", items: { type: "object", properties: { additionalProperties: true } } }, services: { type: "array", items: { type: "object", properties: { additionalProperties: true } } } }, additionalProperties: false, required: ["did", "provider", "keys", "services"] }, sessionId: { type: "string" }, expiresIn: { type: "number" }, additionalProperties: false }, required: ["identifier"], description: "Arguments needed for {@link DidAuthSiopOpAuthenticator.registerSessionForSiop } " }, IRemoveSiopSessionArgs: { type: "object", properties: { sessionId: { type: "string" }, additionalProperties: false }, required: ["sessionId"], description: "Arguments needed for {@link DidAuthSiopOpAuthenticator.removeSessionForSiop } " }, IAuthenticateWithSiopArgs: { type: "object", properties: { sessionId: { type: "string" }, stateId: { type: "string" }, redirectUrl: { type: "string" }, additionalProperties: false }, required: ["sessionId", "stateId", "redirectUrl"], description: "Arguments needed for {@link DidAuthSiopOpAuthenticator.authenticateWithSiop } " }, IResponse: { type: "object", properties: { status: { type: "number" }, additionalProperties: true }, required: ["status"], description: "Result of {@link DidAuthSiopOpAuthenticator.authenticateWithSiop & DidAuthSiopOpAuthenticator.sendSiopAuthenticationResponse } " }, IGetSiopAuthenticationRequestFromRpArgs: { type: "object", properties: { sessionId: { type: "string" }, stateId: { type: "string" }, redirectUrl: { type: "string" }, additionalProperties: false }, required: ["sessionId", "stateId", "redirectUrl"], description: "Arguments needed for {@link DidAuthSiopOpAuthenticator.getSiopAuthenticationRequestFromRP } " }, ParsedAuthenticationRequestURI: { type: "object", properties: { jwt: { type: "string" }, requestPayload: { type: "object", properties: { additionalProperties: true } }, registration: { type: "object", properties: { additionalProperties: true } }, additionalProperties: false }, required: ["jwt", "requestPayload", "registration"], description: "Result of {@link DidAuthSiopOpAuthenticator.getSiopAuthenticationRequestFromRP } " }, IGetSiopAuthenticationRequestDetailsArgs: { type: "object", properties: { sessionId: { type: "string" }, verifiedAuthenticationRequest: { type: "object", properties: { additionalProperties: true } }, credentialFilter: { type: "object", properties: { additionalProperties: true } }, additionalProperties: false }, required: ["sessionId", "verifiedAuthenticationRequest"], description: "Arguments needed for {@link DidAuthSiopOpAuthenticator.getSiopAuthenticationRequestDetails } " }, IAuthRequestDetails: { type: "object", properties: { id: { type: "string" }, alsoKnownAs: { type: "array", items: { type: "string" } }, vpResponseOpts: { type: "object", properties: { additionalProperties: true } }, additionalProperties: false }, required: ["id", "vpResponseOpts"], description: "Result of {@link DidAuthSiopOpAuthenticator.getSiopAuthenticationRequestDetails } " }, IVerifySiopAuthenticationRequestUriArgs: { type: "object", properties: { sessionId: { type: "string" }, ParsedAuthenticationRequestURI: { type: "object", properties: { additionalProperties: true } }, additionalProperties: false }, required: ["sessionId", "ParsedAuthenticationRequestURI"], description: "Arguments needed for {@link DidAuthSiopOpAuthenticator.verifySiopAuthenticationRequestURI } " }, VerifiedAuthorizationRequest: { type: "object", properties: { payload: { type: "object", properties: { additionalProperties: true } }, presentationDefinitions: { type: "object", properties: { additionalProperties: true } }, verifyOpts: { type: "object", properties: { additionalProperties: true } }, additionalProperties: false }, required: ["payload", "verifyOpts"], description: "Result of {@link DidAuthSiopOpAuthenticator.verifySiopAuthenticationRequestURI } " }, ISendSiopAuthenticationResponseArgs: { type: "object", properties: { sessionId: { type: "string" }, verifiedAuthenticationRequest: { type: "object", properties: { additionalProperties: true } }, verifiablePresentationResponse: { type: "object", properties: { additionalProperties: true } }, additionalProperties: false }, required: ["sessionId", "verifiedAuthenticationRequest"], description: "Arguments needed for {@link DidAuthSiopOpAuthenticator.sendSiopAuthenticationResponse } " } }, methods: { getSessionForSiop: { description: "Get SIOP session", arguments: { $ref: "#/components/schemas/IGetSiopSessionArgs" }, returnType: "object" }, registerSessionForSiop: { description: "Register SIOP session", arguments: { $ref: "#/components/schemas/IRegisterSiopSessionArgs" }, returnType: "object" }, removeSessionForSiop: { description: "Remove SIOP session", arguments: { $ref: "#/components/schemas/IRemoveSiopSessionArgs" }, returnType: "boolean" }, authenticateWithSiop: { description: "Authenticate using DID Auth SIOP", arguments: { $ref: "#/components/schemas/IAuthenticateWithSiopArgs" }, returnType: { $ref: "#/components/schemas/Response" } }, getSiopAuthenticationRequestFromRP: { description: "Get authentication request from RP", arguments: { $ref: "#/components/schemas/IGetSiopAuthenticationRequestFromRpArgs" }, returnType: { $ref: "#/components/schemas/ParsedAuthenticationRequestURI" } }, getSiopAuthenticationRequestDetails: { description: "Get authentication request details", arguments: { $ref: "#/components/schemas/IGetSiopAuthenticationRequestDetailsArgs" }, returnType: { $ref: "#/components/schemas/IAuthRequestDetails" } }, verifySiopAuthenticationRequestURI: { description: "Verify authentication request URI", arguments: { $ref: "#/components/schemas/IVerifySiopAuthenticationRequestUriArgs" }, returnType: { $ref: "#/components/schemas/VerifiedAuthorizationRequest" } }, sendSiopAuthenticationResponse: { description: "Send authentication response", arguments: { $ref: "#/components/schemas/ISendSiopAuthenticationResponseArgs" }, returnType: { $ref: "#/components/schemas/IRequiredContext" } } } } } }; } }); // src/index.ts var index_exports = {}; __export(index_exports, { PresentationExchange: () => PresentationExchange, createPEXPresentationSignCallback: () => createPEXPresentationSignCallback, schema: () => schema }); module.exports = __toCommonJS(index_exports); // src/agent/PresentationExchange.ts var import_pex = require("@sphereon/pex"); var import_ssi_types = require("@sphereon/ssi-types"); var import_ssi_sdk_ext = require("@sphereon/ssi-sdk-ext.did-utils"); var import_ssi_sdk = require("@sphereon/ssi-sdk.credential-store"); var PresentationExchange = class { static { __name(this, "PresentationExchange"); } schema = schema.IDidAuthSiopOpAuthenticator; pex = new import_pex.PEX(); methods = { pexValidateDefinition: this.pexValidateDefinition.bind(this), pexDefinitionVersion: this.pexDefinitionVersion.bind(this), pexDefinitionFilterCredentials: this.pexDefinitionFilterCredentials.bind(this), pexDefinitionFilterCredentialsPerInputDescriptor: this.pexDefinitionFilterCredentialsPerInputDescriptor.bind(this) }; constructor(opts) { } async pexValidateDefinition(args) { const { definition } = args; const invalids = []; try { const result = import_pex.PEX.validateDefinition(definition); const validations = Array.isArray(result) ? result : [ result ]; invalids.push(...validations.filter((v) => v.status === "error")); } catch (error) { invalids.push({ status: "error", message: typeof error === "string" ? error : typeof error === "object" && "message" in error ? error.message : "unknown error", tag: "validation" }); } if (invalids.length > 0) { throw Error(`Invalid definition. ${invalids.map((v) => v.message).toString()}`); } return true; } async pexDefinitionVersion(presentationDefinition) { return import_pex.PEX.definitionVersionDiscovery(presentationDefinition); } async pexDefinitionFilterCredentials(args, context) { const credentials = await this.pexFilterCredentials(args.credentialFilterOpts, context); const holderDIDs = args.holderDIDs ? (0, import_ssi_sdk_ext.toDIDs)(args.holderDIDs) : (0, import_ssi_sdk_ext.toDIDs)(await context.agent.dataStoreORMGetIdentifiers()); const selectResults = this.pex.selectFrom(args.presentationDefinition, credentials ?? [], { ...args, holderDIDs, limitDisclosureSignatureSuites: args.limitDisclosureSignatureSuites ?? [ "BbsBlsSignature2020" ] }); return { id: args.presentationDefinition.id, selectResults, filteredCredentials: selectResults.verifiableCredential?.map((vc) => import_ssi_types.CredentialMapper.storedCredentialToOriginalFormat(vc)) ?? [] }; } async pexDefinitionFilterCredentialsPerInputDescriptor(args, context) { const origDefinition = args.presentationDefinition; const credentials = await this.pexFilterCredentials(args.credentialFilterOpts ?? {}, context); const holderDIDs = args.holderDIDs ? (0, import_ssi_sdk_ext.toDIDs)(args.holderDIDs) : (0, import_ssi_sdk_ext.toDIDs)(await context.agent.dataStoreORMGetIdentifiers()); const limitDisclosureSignatureSuites = args.limitDisclosureSignatureSuites; const promises = /* @__PURE__ */ new Map(); origDefinition.input_descriptors.forEach((inputDescriptor) => { const presentationDefinition = { id: inputDescriptor.id, input_descriptors: [ inputDescriptor ] }; const credentialRole = args.credentialFilterOpts.credentialRole; promises.set(inputDescriptor, this.pexDefinitionFilterCredentials({ credentialFilterOpts: { credentialRole, verifiableCredentials: credentials }, // @ts-ignore presentationDefinition, holderDIDs, limitDisclosureSignatureSuites }, context)); }); await Promise.all(promises.values()); const result = []; for (const entry of promises.entries()) { result.push({ ...await entry[1], inputDescriptor: entry[0] }); } return result; } async pexFilterCredentials(filterOpts, context) { if (filterOpts.verifiableCredentials && filterOpts.verifiableCredentials.length > 0) { return filterOpts.verifiableCredentials; } const filter = (0, import_ssi_sdk.verifiableCredentialForRoleFilter)(filterOpts.credentialRole, filterOpts.filter); const uniqueCredentials = await context.agent.crsGetUniqueCredentials({ filter }); return uniqueCredentials.map((uniqueVC) => { const vc = uniqueVC.uniformVerifiableCredential; const proof = Array.isArray(vc.proof) ? vc.proof : [ vc.proof ]; const jwtProof = proof.find((p) => p?.type === import_ssi_types.JWT_PROOF_TYPE_2020); return jwtProof ? jwtProof.jwt : vc; }); } }; // src/functions.ts var import_ssi_sdk_ext2 = require("@sphereon/ssi-sdk-ext.identifier-resolution"); var import_ssi_types2 = require("@sphereon/ssi-types"); async function createPEXPresentationSignCallback(args, context) { function determineProofFormat(determineArgs) { const { format, presentationDefinition, presentation } = determineArgs; var formatOptions = format ?? presentationDefinition.format ?? args.format; if (!formatOptions && presentationDefinition.input_descriptors.length == 1 && "format" in presentationDefinition.input_descriptors[0]) { formatOptions = presentationDefinition.input_descriptors[0].format; } if (!formatOptions) { if (import_ssi_types2.CredentialMapper.isSdJwtDecodedCredentialPayload(presentation.decodedPayload)) { return "vc+sd-jwt"; } else if (import_ssi_types2.CredentialMapper.isMsoMdocDecodedPresentation(presentation.decodedPayload)) { return "mso_mdoc"; } else if (import_ssi_types2.CredentialMapper.isW3cPresentation(presentation.decodedPayload)) { if (typeof presentation.signedPayload === "string") { return "jwt"; } return "lds"; } return "jwt"; } else if (typeof formatOptions === "string") { return formatOptions; } const formats = new Set(Object.keys(formatOptions).map((form) => form.includes("ldp") ? "lds" : form.includes("vc+sd-jwt") ? "vc+sd-jwt" : "jwt")); if (formats.size === 1) { return formats.values().next().value; } formats.keys().next(); if (formats.has("vc+sd-jwt")) { return "vc+sd-jwt"; } else if (formats.has("jwt")) { return "jwt"; } return "lds"; } __name(determineProofFormat, "determineProofFormat"); return async ({ presentation, domain, presentationDefinition, format, challenge }) => { const proofFormat = determineProofFormat({ format, presentationDefinition, presentation }); const { idOpts } = args; const CLOCK_SKEW = 120; if (args.skipDidResolution && (0, import_ssi_sdk_ext2.isManagedIdentifierDidOpts)(idOpts)) { idOpts.offlineWhenNoDIDRegistered = true; } if ("compactSdJwtVc" in presentation) { if (proofFormat !== "vc+sd-jwt") { return Promise.reject(Error(`presentation payload does not match proof format ${proofFormat}`)); } const presentationResult = await context.agent.createSdJwtPresentation({ ...idOpts?.method === "oid4vci-issuer" && { holder: idOpts?.issuer }, presentation: presentation.compactSdJwtVc, kb: { payload: { ...presentation.kbJwt?.payload, iat: presentation.kbJwt?.payload?.iat ?? Math.floor(Date.now() / 1e3 - CLOCK_SKEW), nonce: challenge ?? presentation.kbJwt?.payload?.nonce, aud: presentation.kbJwt?.payload?.aud ?? domain ?? args.domain } } }); return import_ssi_types2.CredentialMapper.storedPresentationToOriginalFormat(presentationResult.presentation); } else { const resolution = await context.agent.identifierManagedGet(idOpts); if (proofFormat === "vc+sd-jwt") { return Promise.reject(Error(`presentation payload does not match proof format ${proofFormat}`)); } let header; if (!presentation.holder) { presentation.holder = resolution.issuer; } if (proofFormat === "jwt") { header = { ...((0, import_ssi_sdk_ext2.isManagedIdentifierDidResult)(resolution) || (0, import_ssi_sdk_ext2.isManagedIdentifierX5cResult)(resolution)) && resolution.kid && { kid: resolution.kid }, ...(0, import_ssi_sdk_ext2.isManagedIdentifierX5cResult)(resolution) && { jwk: resolution.jwk } }; if (presentation.verifier || !presentation.aud) { presentation.aud = Array.isArray(presentation.verifier) ? presentation.verifier : presentation.verifier ?? domain ?? args.domain; delete presentation.verifier; } if (!presentation.nbf) { if (presentation.issuanceDate) { const converted = Date.parse(presentation.issuanceDate); if (!isNaN(converted)) { presentation.nbf = Math.floor(converted / 1e3); } } else { presentation.nbf = Math.floor(Date.now() / 1e3 - CLOCK_SKEW); } } if (!presentation.iat) { presentation.iat = presentation.nbf; } if (!presentation.exp) { if (presentation.expirationDate) { const converted = Date.parse(presentation.expirationDate); if (!isNaN(converted)) { presentation.exp = Math.floor(converted / 1e3); } } else { presentation.exp = presentation.nbf + 600 + CLOCK_SKEW; } } if (!presentation.vp) { presentation.vp = {}; } if (!presentation.vp.holder) { presentation.vp.holder = presentation.holder; } } const vp = await context.agent.createVerifiablePresentation({ presentation, removeOriginalFields: false, keyRef: resolution.kmsKeyRef, // domain: domain ?? args.domain, // handled above, and did-jwt-vc creates an array even for 1 entry challenge: challenge ?? args.challenge, fetchRemoteContexts: args.fetchRemoteContexts !== false, proofFormat, header }); return import_ssi_types2.CredentialMapper.storedPresentationToOriginalFormat(vp); } }; } __name(createPEXPresentationSignCallback, "createPEXPresentationSignCallback"); // src/index.ts var schema = require_plugin_schema(); //# sourceMappingURL=index.cjs.map