UNPKG

@sphereon/ssi-sdk.siopv2-oid4vp-rp-auth

Version:

1,057 lines (1,052 loc) • 38.5 kB
var __defProp = Object.defineProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); // plugin.schema.json var plugin_schema_default = { 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/agent/SIOPv2RP.ts import { AuthorizationResponseStateStatus, decodeUriAsJson } from "@sphereon/did-auth-siop"; import { getAgentResolver as getAgentResolver2 } from "@sphereon/ssi-sdk-ext.did-utils"; import { shaHasher as defaultHasher2 } from "@sphereon/ssi-sdk.core"; import { validate as isValidUUID2 } from "uuid"; import { CredentialMapper as CredentialMapper2 } from "@sphereon/ssi-types"; import { DcqlQuery } from "dcql"; // src/functions.ts import { ClientIdentifierPrefix, InMemoryRPSessionManager, PassBy, PropertyTarget, ResponseMode, ResponseType, RevocationVerification, RP, Scope, SubjectType, SupportedVersion } from "@sphereon/did-auth-siop"; import { SigningAlgo } from "@sphereon/oid4vc-common"; import { getAgentDIDMethods, getAgentResolver } from "@sphereon/ssi-sdk-ext.did-utils"; import { isExternalIdentifierOIDFEntityIdOpts, isManagedIdentifierDidOpts, isManagedIdentifierDidResult, isManagedIdentifierX5cOpts } from "@sphereon/ssi-sdk-ext.identifier-resolution"; import { CredentialMapper } from "@sphereon/ssi-types"; import { EventEmitter } from "events"; import { validate as isValidUUID } from "uuid"; import { defaultHasher } from "@sphereon/ssi-sdk.core"; function getRequestVersion(rpOptions) { if (Array.isArray(rpOptions.supportedVersions) && rpOptions.supportedVersions.length > 0) { return rpOptions.supportedVersions[0]; } return SupportedVersion.OID4VP_v1; } __name(getRequestVersion, "getRequestVersion"); function getWellKnownDIDVerifyCallback(siopIdentifierOpts, context) { return siopIdentifierOpts.wellknownDIDVerifyCallback ? siopIdentifierOpts.wellknownDIDVerifyCallback : async (args) => { const result = await context.agent.cvVerifyCredential({ credential: args.credential, fetchRemoteContexts: true }); return { verified: result.result }; }; } __name(getWellKnownDIDVerifyCallback, "getWellKnownDIDVerifyCallback"); function getDcqlQueryLookupCallback(context) { async function dcqlQueryLookup(queryId, version, tenantId) { const result = await context.agent.pdmGetDefinitions({ filter: [ { queryId, ...tenantId && { tenantId }, ...version && { version } }, ...isValidUUID(queryId) ? [ { id: queryId } ] : [] ] }); if (result && result.length > 0) { return result[0].query; } return Promise.reject(Error(`No dcql query found for queryId ${queryId}`)); } __name(dcqlQueryLookup, "dcqlQueryLookup"); return dcqlQueryLookup; } __name(getDcqlQueryLookupCallback, "getDcqlQueryLookupCallback"); function getPresentationVerificationCallback(idOpts, context) { async function presentationVerificationCallback(args, presentationSubmission) { if (CredentialMapper.isSdJwtEncoded(args)) { const result2 = await context.agent.verifySdJwtPresentation({ presentation: args }); return { verified: !!result2.payload }; } if (CredentialMapper.isMsoMdocOid4VPEncoded(args)) { if (context.agent.mdocOid4vpRPVerify === void 0) { return Promise.reject("ImDLMdoc agent plugin must be enabled to support MsoMdoc types"); } if (presentationSubmission !== void 0 && presentationSubmission !== null) { const verifyResult = await context.agent.mdocOid4vpRPVerify({ vp_token: args, presentation_submission: presentationSubmission }); return { verified: !verifyResult.error }; } throw Error(`mdocOid4vpRPVerify(...) method requires a presentation submission`); } const result = await context.agent.verifyPresentation({ presentation: args, fetchRemoteContexts: true, domain: (await context.agent.identifierManagedGet(idOpts)).kid?.split("#")[0] }); return { verified: result.verified }; } __name(presentationVerificationCallback, "presentationVerificationCallback"); return presentationVerificationCallback; } __name(getPresentationVerificationCallback, "getPresentationVerificationCallback"); async function createRPBuilder(args) { const { rpOpts, context } = args; const { identifierOpts } = rpOpts; const didMethods = identifierOpts.supportedDIDMethods ?? await getAgentDIDMethods(context); const eventEmitter = rpOpts.eventEmitter ?? new EventEmitter(); const defaultClientMetadata = { // FIXME: All of the below should be configurable. Some should come from builder, some should be determined by the agent. // For now it is either preconfigured or everything passed in as a single object idTokenSigningAlgValuesSupported: [ SigningAlgo.EDDSA, SigningAlgo.ES256, SigningAlgo.ES256K ], requestObjectSigningAlgValuesSupported: [ SigningAlgo.EDDSA, SigningAlgo.ES256, SigningAlgo.ES256K ], responseTypesSupported: [ ResponseType.ID_TOKEN ], client_name: "Sphereon", vpFormatsSupported: { jwt_vc: { alg: [ "EdDSA", "ES256K" ] }, jwt_vp: { alg: [ "ES256K", "EdDSA" ] } }, scopesSupported: [ Scope.OPENID_DIDAUTHN ], subjectTypesSupported: [ SubjectType.PAIRWISE ], subject_syntax_types_supported: didMethods.map((method) => `did:${method}`), passBy: PassBy.VALUE }; const resolver = rpOpts.identifierOpts.resolveOpts?.resolver ?? getAgentResolver(context, { resolverResolution: true, localResolution: true, uniresolverResolution: rpOpts.identifierOpts.resolveOpts?.noUniversalResolverFallback !== true }); let hasher = rpOpts.credentialOpts?.hasher; if (!rpOpts.credentialOpts?.hasher || typeof rpOpts.credentialOpts?.hasher !== "function") { hasher = defaultHasher; } const builder = RP.builder({ requestVersion: getRequestVersion(rpOpts) }).withScope("openid", PropertyTarget.REQUEST_OBJECT).withResponseMode(rpOpts.responseMode ?? ResponseMode.POST).withResponseType(ResponseType.VP_TOKEN, PropertyTarget.REQUEST_OBJECT).withSupportedVersions(rpOpts.supportedVersions ?? [ SupportedVersion.OID4VP_v1, SupportedVersion.SIOPv2_OID4VP_D28 ]).withEventEmitter(eventEmitter).withSessionManager(rpOpts.sessionManager ?? new InMemoryRPSessionManager(eventEmitter)).withClientMetadata(rpOpts.clientMetadataOpts ?? defaultClientMetadata, PropertyTarget.REQUEST_OBJECT).withVerifyJwtCallback(rpOpts.verifyJwtCallback ? rpOpts.verifyJwtCallback : getVerifyJwtCallback({ resolver, verifyOpts: { wellknownDIDVerifyCallback: getWellKnownDIDVerifyCallback(rpOpts.identifierOpts, context), checkLinkedDomain: "if_present" } }, context)).withDcqlQueryLookup(getDcqlQueryLookupCallback(context)).withRevocationVerification(RevocationVerification.NEVER).withPresentationVerification(getPresentationVerificationCallback(identifierOpts.idOpts, context)); const oidfOpts = identifierOpts.oidfOpts; if (oidfOpts && isExternalIdentifierOIDFEntityIdOpts(oidfOpts)) { builder.withEntityId(oidfOpts.identifier, PropertyTarget.REQUEST_OBJECT); } else { const resolution = await context.agent.identifierManagedGet(identifierOpts.idOpts); const clientId = rpOpts.clientMetadataOpts?.client_id ?? resolution.issuer ?? (isManagedIdentifierDidResult(resolution) ? resolution.did : resolution.jwkThumbprint); const clientIdPrefixed = prefixClientId(clientId); builder.withClientId(clientIdPrefixed, PropertyTarget.REQUEST_OBJECT); } if (hasher) { builder.withHasher(hasher); } if (rpOpts.responseRedirectUri) { builder.withResponseRedirectUri(rpOpts.responseRedirectUri); } if (rpOpts.transactionData) { builder.withTransactionData(rpOpts.transactionData); } if (rpOpts.verifierInfo) { builder.withVerifierInfo(rpOpts.verifierInfo); } if (rpOpts.verifierAttestations) { builder.withVerifierAttestations(rpOpts.verifierAttestations); } if (rpOpts.requestUriMethod) { builder.withRequestUriMethod(rpOpts.requestUriMethod); } if (rpOpts.expectedOrigins) { builder.withExpectedOrigins(rpOpts.expectedOrigins); } if (rpOpts.walletNonce) { builder.withWalletNonce(rpOpts.walletNonce); } const createJwtCallback = signCallback(rpOpts.identifierOpts.idOpts, context); builder.withCreateJwtCallback(createJwtCallback); return builder; } __name(createRPBuilder, "createRPBuilder"); function signCallback(idOpts, context) { return async (jwtIssuer, jwt, kid) => { if (!(isManagedIdentifierDidOpts(idOpts) || isManagedIdentifierX5cOpts(idOpts))) { return Promise.reject(Error(`JWT issuer method ${jwtIssuer.method} not yet supported`)); } const result = await context.agent.jwtCreateJwsCompactSignature({ // FIXME fix cose-key inference // @ts-ignore issuer: { identifier: idOpts.identifier, kmsKeyRef: idOpts.kmsKeyRef, noIdentifierInHeader: false }, // FIXME fix JWK key_ops // @ts-ignore protectedHeader: jwt.header, payload: jwt.payload }); return result.jwt; }; } __name(signCallback, "signCallback"); function getVerifyJwtCallback(_opts, context) { return async (_jwtVerifier, jwt) => { const result = await context.agent.jwtVerifyJwsSignature({ jws: jwt.raw }); console.log(result.message); return !result.error; }; } __name(getVerifyJwtCallback, "getVerifyJwtCallback"); function getSigningAlgo(type) { switch (type) { case "Ed25519": return SigningAlgo.EDDSA; case "Secp256k1": return SigningAlgo.ES256K; case "Secp256r1": return SigningAlgo.ES256; // @ts-ignore case "RSA": return SigningAlgo.RS256; default: throw Error("Key type not yet supported"); } } __name(getSigningAlgo, "getSigningAlgo"); function prefixClientId(clientId) { if (clientId.startsWith("did:")) { return `${ClientIdentifierPrefix.DECENTRALIZED_IDENTIFIER}:${clientId}`; } return clientId; } __name(prefixClientId, "prefixClientId"); // src/RPInstance.ts import { v4 as uuidv4 } from "uuid"; import { ensureManagedIdentifierResult, isManagedIdentifierDidResult as isManagedIdentifierDidResult2, isManagedIdentifierX5cResult } from "@sphereon/ssi-sdk-ext.identifier-resolution"; var RPInstance = class { static { __name(this, "RPInstance"); } _rp; _presentationOptions; _rpOptions; constructor({ rpOpts, pexOpts }) { this._rpOptions = rpOpts; this._presentationOptions = pexOpts; } async get(context) { if (!this._rp) { const builder = await createRPBuilder({ rpOpts: this._rpOptions, context }); this._rp = builder.build(); } return this._rp; } get rpOptions() { return this._rpOptions; } get presentationOptions() { return this._presentationOptions; } async createAuthorizationRequestURI(createArgs, context) { const { correlationId, queryId, claims, requestByReferenceURI, responseURI, responseURIType, callback, responseRedirectURI } = createArgs; const nonce = createArgs.nonce ?? uuidv4(); const state = createArgs.state ?? correlationId; let jwtIssuer; const idOpts = this.rpOptions.identifierOpts.idOpts; const resolution = await ensureManagedIdentifierResult(idOpts, context); if (isManagedIdentifierDidResult2(resolution)) { jwtIssuer = { didUrl: resolution.kid, method: "did", alg: getSigningAlgo(resolution.key.type) }; } else if (isManagedIdentifierX5cResult(resolution)) { if (!resolution.issuer) { return Promise.reject("missing issuer in idOpts"); } jwtIssuer = { issuer: resolution.issuer, x5c: resolution.x5c, method: "x5c", alg: getSigningAlgo(resolution.key.type) }; } else { return Promise.reject(Error(`JWT issuer method ${resolution.method} not yet supported`)); } return await this.get(context).then((rp) => rp.createAuthorizationRequestURI({ version: getRequestVersion(this.rpOptions), correlationId, queryId, nonce, state, claims, requestByReferenceURI, responseURI, responseURIType, jwtIssuer, callback, responseRedirectURI })); } async createAuthorizationRequest(createArgs, context) { const { correlationId, claims, requestByReferenceURI, responseURI, responseURIType, responseRedirectURI } = createArgs; const nonce = createArgs.nonce ?? uuidv4(); const state = createArgs.state ?? correlationId; const idOpts = this.rpOptions.identifierOpts.idOpts; const resolution = await ensureManagedIdentifierResult(idOpts, context); let jwtIssuer; if (isManagedIdentifierX5cResult(resolution) && resolution.issuer) { jwtIssuer = { method: resolution.method, alg: getSigningAlgo(resolution.key.type), x5c: resolution.x5c, issuer: resolution.issuer }; } else if (isManagedIdentifierDidResult2(resolution)) { jwtIssuer = { method: resolution.method, alg: getSigningAlgo(resolution.key.type), didUrl: resolution.did }; } else { return Promise.reject(Error("Only did & x5c supported at present")); } return await this.get(context).then((rp) => rp.createAuthorizationRequest({ version: getRequestVersion(this.rpOptions), correlationId, nonce, state, claims, requestByReferenceURI, responseURIType, responseURI, jwtIssuer, responseRedirectURI })); } }; // src/agent/SIOPv2RP.ts var SIOPv2RP = class _SIOPv2RP { static { __name(this, "SIOPv2RP"); } opts; static _DEFAULT_OPTS_KEY = "_default"; instances = /* @__PURE__ */ new Map(); schema = plugin_schema_default.IDidAuthSiopOpAuthenticator; methods = { siopCreateAuthRequestURI: this.createAuthorizationRequestURI.bind(this), siopCreateAuthRequestPayloads: this.createAuthorizationRequestPayloads.bind(this), siopGetAuthRequestState: this.siopGetRequestState.bind(this), siopGetAuthResponseState: this.siopGetResponseState.bind(this), siopUpdateAuthRequestState: this.siopUpdateRequestState.bind(this), siopDeleteAuthState: this.siopDeleteState.bind(this), siopVerifyAuthResponse: this.siopVerifyAuthResponse.bind(this), siopImportDefinitions: this.siopImportDefinitions.bind(this), siopGetRedirectURI: this.siopGetRedirectURI.bind(this) }; constructor(opts) { this.opts = opts; } setDefaultOpts(rpDefaultOpts, context) { this.opts.defaultOpts = rpDefaultOpts; if (!this.opts.defaultOpts.identifierOpts.resolveOpts?.resolver || typeof this.opts.defaultOpts.identifierOpts.resolveOpts.resolver.resolve !== "function") { this.opts.defaultOpts.identifierOpts.resolveOpts = { ...this.opts.defaultOpts.identifierOpts.resolveOpts, resolver: getAgentResolver2(context, { uniresolverResolution: true, resolverResolution: true, localResolution: true }) }; } } async createAuthorizationRequestURI(createArgs, context) { return await this.getRPInstance({ createWhenNotPresent: true, responseRedirectURI: createArgs.responseRedirectURI, ...createArgs.useQueryIdInstance === true && { queryId: createArgs.queryId } }, context).then((rp) => rp.createAuthorizationRequestURI(createArgs, context)).then((URI) => URI.encodedUri); } async createAuthorizationRequestPayloads(createArgs, context) { return await this.getRPInstance({ createWhenNotPresent: true, queryId: createArgs.queryId }, context).then((rp) => rp.createAuthorizationRequest(createArgs, context)).then(async (request) => { const authRequest = { authorizationRequest: request.payload, requestObject: await request.requestObjectJwt(), requestObjectDecoded: request.requestObject?.getPayload() }; return authRequest; }); } async siopGetRequestState(args, context) { return await this.getRPInstance({ createWhenNotPresent: false, queryId: args.queryId }, context).then((rp) => rp.get(context).then((rp2) => rp2.sessionManager.getRequestStateByCorrelationId(args.correlationId, args.errorOnNotFound))); } async siopGetResponseState(args, context) { const rpInstance = await this.getRPInstance({ createWhenNotPresent: false, queryId: args.queryId }, context); const authorizationResponseState = await rpInstance.get(context).then((rp) => rp.sessionManager.getResponseStateByCorrelationId(args.correlationId, args.errorOnNotFound)); if (authorizationResponseState === void 0) { return void 0; } const responseState = authorizationResponseState; if (responseState.status === AuthorizationResponseStateStatus.VERIFIED) { let hasher; if (CredentialMapper2.isSdJwtEncoded(responseState.response.payload.vp_token) && (!rpInstance.rpOptions.credentialOpts?.hasher || typeof rpInstance.rpOptions.credentialOpts?.hasher !== "function")) { hasher = defaultHasher2; } const rawVpToken = responseState.response.payload.vp_token; const vpToken = rawVpToken && (typeof rawVpToken === "string" ? JSON.parse(rawVpToken) : rawVpToken); const claims = []; for (const [credentialQueryId, presentationValue] of Object.entries(vpToken)) { let singleVP; if (Array.isArray(presentationValue)) { if (presentationValue.length === 0) { throw Error(`DCQL query '${credentialQueryId}' has empty array of presentations`); } if (presentationValue.length > 1) { throw Error(`DCQL query '${credentialQueryId}' has multiple presentations (${presentationValue.length}), but only one is supported atm`); } singleVP = presentationValue[0]; } else { singleVP = presentationValue; } const presentationDecoded = CredentialMapper2.decodeVerifiablePresentation( singleVP, //todo: later we want to conditionally pass in options for mdl-mdoc here hasher ); console.log(`presentationDecoded: ${JSON.stringify(presentationDecoded)}`); const allClaims = {}; const presentationOrClaims = this.presentationOrClaimsFrom(presentationDecoded); if ("verifiableCredential" in presentationOrClaims) { for (const credential of presentationOrClaims.verifiableCredential) { const vc = credential; const schemaValidationResult = await context.agent.cvVerifySchema({ credential, hasher, validationPolicy: rpInstance.rpOptions.verificationPolicies?.schemaValidation }); if (!schemaValidationResult.result) { responseState.status = AuthorizationResponseStateStatus.ERROR; responseState.error = new Error(schemaValidationResult.error); return responseState; } const credentialSubject = vc.credentialSubject; if (!("id" in allClaims)) { allClaims["id"] = credentialSubject.id; } Object.entries(credentialSubject).forEach(([key, value]) => { if (!(key in allClaims)) { allClaims[key] = value; } }); claims.push({ id: credentialQueryId, type: vc.type[0], claims: allClaims }); } } else { claims.push({ id: credentialQueryId, type: presentationDecoded.decodedPayload.vct, claims: presentationOrClaims }); } } responseState.verifiedData = { ...responseState.response.payload.vp_token && { authorization_response: { vp_token: typeof responseState.response.payload.vp_token === "string" ? JSON.parse(responseState.response.payload.vp_token) : responseState.response.payload.vp_token } }, ...claims.length > 0 && { credential_claims: claims } }; } return responseState; } presentationOrClaimsFrom = /* @__PURE__ */ __name((presentationDecoded) => { return CredentialMapper2.isSdJwtDecodedCredential(presentationDecoded) ? presentationDecoded.decodedPayload : CredentialMapper2.toUniformPresentation(presentationDecoded); }, "presentationOrClaimsFrom"); async siopUpdateRequestState(args, context) { if (args.state !== "authorization_request_created") { throw Error(`Only 'authorization_request_created' status is supported for this method at this point`); } return await this.getRPInstance({ createWhenNotPresent: false, queryId: args.queryId }, context).then((rp) => rp.get(context).then(async (rp2) => { await rp2.signalAuthRequestRetrieved({ correlationId: args.correlationId, error: args.error ? new Error(args.error) : void 0 }); return await rp2.sessionManager.getRequestStateByCorrelationId(args.correlationId, true); })); } async siopDeleteState(args, context) { return await this.getRPInstance({ createWhenNotPresent: false, queryId: args.queryId }, context).then((rp) => rp.get(context).then((rp2) => rp2.sessionManager.deleteStateForCorrelationId(args.correlationId))).then(() => true); } async siopVerifyAuthResponse(args, context) { if (!args.authorizationResponse) { throw Error("No SIOPv2 Authorization Response received"); } const authResponse = typeof args.authorizationResponse === "string" ? decodeUriAsJson(args.authorizationResponse) : args.authorizationResponse; return await this.getRPInstance({ createWhenNotPresent: false, queryId: args.queryId }, context).then((rp) => rp.get(context).then((rp2) => rp2.verifyAuthorizationResponse(authResponse, { correlationId: args.correlationId, ...args.dcqlQuery && { dcqlQuery: args.dcqlQuery }, audience: args.audience }))); } async siopImportDefinitions(args, context) { const { importItems, tenantId, version, versionControlMode } = args; await Promise.all(importItems.map(async (importItem) => { DcqlQuery.validate(importItem.query); console.log(`persisting DCQL definition ${importItem.queryId} with versionControlMode ${versionControlMode}`); return context.agent.pdmPersistDefinition({ definitionItem: { queryId: importItem.queryId, tenantId, version, query: importItem.query }, opts: { versionControlMode } }); })); } async siopGetRedirectURI(args, context) { const instanceId = args.queryId ?? _SIOPv2RP._DEFAULT_OPTS_KEY; if (this.instances.has(instanceId)) { const rpInstance = this.instances.get(instanceId); if (rpInstance !== void 0) { const rp = await rpInstance.get(context); return await rp.getResponseRedirectUri({ correlation_id: args.correlationId, correlationId: args.correlationId, ...args.state && { state: args.state } }); } } return void 0; } async getRPInstance({ createWhenNotPresent, queryId, responseRedirectURI }, context) { let rpInstanceId = _SIOPv2RP._DEFAULT_OPTS_KEY; let rpInstance; if (queryId) { if (this.instances.has(queryId)) { rpInstanceId = queryId; rpInstance = this.instances.get(rpInstanceId); } else if (isValidUUID2(queryId)) { try { const pd = await context.agent.pdmGetDefinition({ itemId: queryId }); if (this.instances.has(pd.queryId)) { rpInstanceId = pd.queryId; rpInstance = this.instances.get(rpInstanceId); } } catch (ignore) { } } if (createWhenNotPresent) { rpInstanceId = queryId; } else { rpInstance = this.instances.get(rpInstanceId); } } else { rpInstance = this.instances.get(rpInstanceId); } if (!rpInstance) { if (!createWhenNotPresent) { return Promise.reject(`No RP instance found for key ${rpInstanceId}`); } const instanceOpts = this.getInstanceOpts(queryId); const rpOpts = await this.getRPOptions(context, { queryId, responseRedirectURI }); if (!rpOpts.identifierOpts.resolveOpts?.resolver || typeof rpOpts.identifierOpts.resolveOpts.resolver.resolve !== "function") { if (!rpOpts.identifierOpts?.resolveOpts) { rpOpts.identifierOpts = { ...rpOpts.identifierOpts }; rpOpts.identifierOpts.resolveOpts = { ...rpOpts.identifierOpts.resolveOpts }; } console.log("Using agent DID resolver for RP instance with definition id " + queryId); rpOpts.identifierOpts.resolveOpts.resolver = getAgentResolver2(context, { uniresolverResolution: true, localResolution: true, resolverResolution: true }); } rpInstance = new RPInstance({ rpOpts, pexOpts: instanceOpts }); this.instances.set(rpInstanceId, rpInstance); } if (responseRedirectURI) { rpInstance.rpOptions.responseRedirectUri = responseRedirectURI; } return rpInstance; } async getRPOptions(context, opts) { const { queryId, responseRedirectURI } = opts; const options = this.getInstanceOpts(queryId)?.rpOpts ?? this.opts.defaultOpts; if (!options) { throw Error(`Could not get specific nor default options for definition ${queryId}`); } if (this.opts.defaultOpts) { if (!options.identifierOpts) { options.identifierOpts = this.opts.defaultOpts?.identifierOpts; } else { if (!options.identifierOpts.idOpts) { options.identifierOpts.idOpts = this.opts.defaultOpts.identifierOpts.idOpts; } if (!options.identifierOpts.supportedDIDMethods) { options.identifierOpts.supportedDIDMethods = this.opts.defaultOpts.identifierOpts.supportedDIDMethods; } if (!options.supportedVersions) { options.supportedVersions = this.opts.defaultOpts.supportedVersions; } } if (!options.identifierOpts.resolveOpts || typeof options.identifierOpts.resolveOpts.resolver?.resolve !== "function") { options.identifierOpts.resolveOpts = { ...this.opts.defaultOpts.identifierOpts.resolveOpts, resolver: this.opts.defaultOpts.identifierOpts?.resolveOpts?.resolver ?? getAgentResolver2(context, { localResolution: true, resolverResolution: true, uniresolverResolution: true }) }; } } if (responseRedirectURI !== void 0 && responseRedirectURI !== options.responseRedirectUri) { options.responseRedirectUri = responseRedirectURI; } return options; } getInstanceOpts(queryId) { if (!this.opts.instanceOpts) return void 0; const instanceOpt = queryId ? this.opts.instanceOpts.find((i) => i.queryId === queryId) : void 0; return instanceOpt ?? this.getDefaultOptions(queryId); } getDefaultOptions(queryId) { if (!this.opts.instanceOpts) return void 0; const defaultOptions = this.opts.instanceOpts.find((i) => i.queryId === "default"); if (defaultOptions) { const clonedOptions = { ...defaultOptions }; if (queryId !== void 0) { clonedOptions.queryId = queryId; } return clonedOptions; } return void 0; } }; export { SIOPv2RP, plugin_schema_default as schema }; //# sourceMappingURL=index.js.map