@credo-ts/openid4vc 0.6.1-pr-2091-20241119140918 → 0.6.2-alpha-20251210145840
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/OpenId4VcApi.d.mts +24 -0
- package/build/OpenId4VcApi.d.mts.map +1 -0
- package/build/OpenId4VcApi.mjs +35 -0
- package/build/OpenId4VcApi.mjs.map +1 -0
- package/build/OpenId4VcModule.d.mts +30 -0
- package/build/OpenId4VcModule.d.mts.map +1 -0
- package/build/OpenId4VcModule.mjs +42 -0
- package/build/OpenId4VcModule.mjs.map +1 -0
- package/build/OpenId4VcModuleConfig.d.mts +44 -0
- package/build/OpenId4VcModuleConfig.d.mts.map +1 -0
- package/build/OpenId4VcModuleConfig.mjs +24 -0
- package/build/OpenId4VcModuleConfig.mjs.map +1 -0
- package/build/_virtual/_@oxc-project_runtime@0.99.0/helpers/decorate.mjs +10 -0
- package/build/_virtual/_@oxc-project_runtime@0.99.0/helpers/decorateMetadata.mjs +7 -0
- package/build/_virtual/_@oxc-project_runtime@0.99.0/helpers/decorateParam.mjs +9 -0
- package/build/index.d.mts +42 -0
- package/build/index.mjs +37 -0
- package/build/openid4vc-holder/OpenId4VcHolderApi.d.mts +238 -0
- package/build/openid4vc-holder/OpenId4VcHolderApi.d.mts.map +1 -0
- package/build/openid4vc-holder/OpenId4VcHolderApi.mjs +174 -0
- package/build/openid4vc-holder/OpenId4VcHolderApi.mjs.map +1 -0
- package/build/openid4vc-holder/OpenId4VcHolderModule.d.mts +17 -0
- package/build/openid4vc-holder/OpenId4VcHolderModule.d.mts.map +1 -0
- package/build/openid4vc-holder/OpenId4VcHolderModule.mjs +23 -0
- package/build/openid4vc-holder/OpenId4VcHolderModule.mjs.map +1 -0
- package/build/openid4vc-holder/OpenId4VciHolderService.d.mts +69 -0
- package/build/openid4vc-holder/OpenId4VciHolderService.d.mts.map +1 -0
- package/build/openid4vc-holder/OpenId4VciHolderService.mjs +751 -0
- package/build/openid4vc-holder/OpenId4VciHolderService.mjs.map +1 -0
- package/build/openid4vc-holder/OpenId4VciHolderServiceOptions.d.mts +398 -0
- package/build/openid4vc-holder/OpenId4VciHolderServiceOptions.d.mts.map +1 -0
- package/build/openid4vc-holder/OpenId4VciHolderServiceOptions.mjs +16 -0
- package/build/openid4vc-holder/OpenId4VciHolderServiceOptions.mjs.map +1 -0
- package/build/openid4vc-holder/OpenId4vpHolderService.d.mts +130 -0
- package/build/openid4vc-holder/OpenId4vpHolderService.d.mts.map +1 -0
- package/build/openid4vc-holder/OpenId4vpHolderService.mjs +278 -0
- package/build/openid4vc-holder/OpenId4vpHolderService.mjs.map +1 -0
- package/build/openid4vc-holder/OpenId4vpHolderServiceOptions.d.mts +112 -0
- package/build/openid4vc-holder/OpenId4vpHolderServiceOptions.d.mts.map +1 -0
- package/build/openid4vc-holder/index.d.mts +6 -0
- package/build/openid4vc-holder/index.mjs +5 -0
- package/build/openid4vc-issuer/OpenId4VcIssuanceSessionState.d.mts +16 -0
- package/build/openid4vc-issuer/OpenId4VcIssuanceSessionState.d.mts.map +1 -0
- package/build/openid4vc-issuer/OpenId4VcIssuanceSessionState.mjs +18 -0
- package/build/openid4vc-issuer/OpenId4VcIssuanceSessionState.mjs.map +1 -0
- package/build/openid4vc-issuer/OpenId4VcIssuerApi.d.mts +137 -0
- package/build/openid4vc-issuer/OpenId4VcIssuerApi.d.mts.map +1 -0
- package/build/openid4vc-issuer/OpenId4VcIssuerApi.mjs +108 -0
- package/build/openid4vc-issuer/OpenId4VcIssuerApi.mjs.map +1 -0
- package/build/openid4vc-issuer/OpenId4VcIssuerEvents.d.mts +19 -0
- package/build/openid4vc-issuer/OpenId4VcIssuerEvents.d.mts.map +1 -0
- package/build/openid4vc-issuer/OpenId4VcIssuerEvents.mjs +9 -0
- package/build/openid4vc-issuer/OpenId4VcIssuerEvents.mjs.map +1 -0
- package/build/openid4vc-issuer/OpenId4VcIssuerModule.d.mts +27 -0
- package/build/openid4vc-issuer/OpenId4VcIssuerModule.d.mts.map +1 -0
- package/build/openid4vc-issuer/OpenId4VcIssuerModule.mjs +150 -0
- package/build/openid4vc-issuer/OpenId4VcIssuerModule.mjs.map +1 -0
- package/build/openid4vc-issuer/OpenId4VcIssuerModuleConfig.d.mts +279 -0
- package/build/openid4vc-issuer/OpenId4VcIssuerModuleConfig.d.mts.map +1 -0
- package/build/openid4vc-issuer/OpenId4VcIssuerModuleConfig.mjs +179 -0
- package/build/openid4vc-issuer/OpenId4VcIssuerModuleConfig.mjs.map +1 -0
- package/build/openid4vc-issuer/OpenId4VcIssuerService.d.mts +182 -0
- package/build/openid4vc-issuer/OpenId4VcIssuerService.d.mts.map +1 -0
- package/build/openid4vc-issuer/OpenId4VcIssuerService.mjs +881 -0
- package/build/openid4vc-issuer/OpenId4VcIssuerService.mjs.map +1 -0
- package/build/openid4vc-issuer/OpenId4VcIssuerServiceOptions.d.mts +340 -0
- package/build/openid4vc-issuer/OpenId4VcIssuerServiceOptions.d.mts.map +1 -0
- package/build/openid4vc-issuer/OpenId4VcIssuerServiceOptions.mjs +1 -0
- package/build/openid4vc-issuer/index.d.mts +11 -0
- package/build/openid4vc-issuer/index.mjs +11 -0
- package/build/openid4vc-issuer/repository/OpenId4VcIssuanceSessionRecord.d.mts +300 -0
- package/build/openid4vc-issuer/repository/OpenId4VcIssuanceSessionRecord.d.mts.map +1 -0
- package/build/openid4vc-issuer/repository/OpenId4VcIssuanceSessionRecord.mjs +102 -0
- package/build/openid4vc-issuer/repository/OpenId4VcIssuanceSessionRecord.mjs.map +1 -0
- package/build/openid4vc-issuer/repository/OpenId4VcIssuanceSessionRepository.d.mts +10 -0
- package/build/openid4vc-issuer/repository/OpenId4VcIssuanceSessionRepository.d.mts.map +1 -0
- package/build/openid4vc-issuer/repository/OpenId4VcIssuanceSessionRepository.mjs +22 -0
- package/build/openid4vc-issuer/repository/OpenId4VcIssuanceSessionRepository.mjs.map +1 -0
- package/build/openid4vc-issuer/repository/OpenId4VcIssuerRecord.d.mts +84 -0
- package/build/openid4vc-issuer/repository/OpenId4VcIssuerRecord.d.mts.map +1 -0
- package/build/openid4vc-issuer/repository/OpenId4VcIssuerRecord.mjs +89 -0
- package/build/openid4vc-issuer/repository/OpenId4VcIssuerRecord.mjs.map +1 -0
- package/build/openid4vc-issuer/repository/OpenId4VcIssuerRepository.d.mts +12 -0
- package/build/openid4vc-issuer/repository/OpenId4VcIssuerRepository.d.mts.map +1 -0
- package/build/openid4vc-issuer/repository/OpenId4VcIssuerRepository.mjs +28 -0
- package/build/openid4vc-issuer/repository/OpenId4VcIssuerRepository.mjs.map +1 -0
- package/build/openid4vc-issuer/repository/index.d.mts +4 -0
- package/build/openid4vc-issuer/repository/index.mjs +4 -0
- package/build/openid4vc-issuer/router/accessTokenEndpoint.mjs +199 -0
- package/build/openid4vc-issuer/router/accessTokenEndpoint.mjs.map +1 -0
- package/build/openid4vc-issuer/router/authorizationChallengeEndpoint.mjs +241 -0
- package/build/openid4vc-issuer/router/authorizationChallengeEndpoint.mjs.map +1 -0
- package/build/openid4vc-issuer/router/authorizationEndpoint.mjs +51 -0
- package/build/openid4vc-issuer/router/authorizationEndpoint.mjs.map +1 -0
- package/build/openid4vc-issuer/router/authorizationServerMetadataEndpoint.mjs +25 -0
- package/build/openid4vc-issuer/router/authorizationServerMetadataEndpoint.mjs.map +1 -0
- package/build/openid4vc-issuer/router/credentialEndpoint.mjs +142 -0
- package/build/openid4vc-issuer/router/credentialEndpoint.mjs.map +1 -0
- package/build/openid4vc-issuer/router/credentialOfferEndpoint.mjs +38 -0
- package/build/openid4vc-issuer/router/credentialOfferEndpoint.mjs.map +1 -0
- package/build/openid4vc-issuer/router/deferredCredentialEndpoint.mjs +84 -0
- package/build/openid4vc-issuer/router/deferredCredentialEndpoint.mjs.map +1 -0
- package/build/openid4vc-issuer/router/index.mjs +12 -0
- package/build/openid4vc-issuer/router/issuerMetadataEndpoint.mjs +43 -0
- package/build/openid4vc-issuer/router/issuerMetadataEndpoint.mjs.map +1 -0
- package/build/openid4vc-issuer/router/jwksEndpoint.mjs +18 -0
- package/build/openid4vc-issuer/router/jwksEndpoint.mjs.map +1 -0
- package/build/openid4vc-issuer/router/nonceEndpoint.mjs +29 -0
- package/build/openid4vc-issuer/router/nonceEndpoint.mjs.map +1 -0
- package/build/openid4vc-issuer/router/pushedAuthorizationRequestEndpoint.mjs +164 -0
- package/build/openid4vc-issuer/router/pushedAuthorizationRequestEndpoint.mjs.map +1 -0
- package/build/openid4vc-issuer/router/redirectEndpoint.mjs +124 -0
- package/build/openid4vc-issuer/router/redirectEndpoint.mjs.map +1 -0
- package/build/openid4vc-issuer/util/txCode.mjs +18 -0
- package/build/openid4vc-issuer/util/txCode.mjs.map +1 -0
- package/build/openid4vc-verifier/OpenId4VcVerificationSessionState.d.mts +10 -0
- package/build/openid4vc-verifier/OpenId4VcVerificationSessionState.d.mts.map +1 -0
- package/build/openid4vc-verifier/OpenId4VcVerificationSessionState.mjs +12 -0
- package/build/openid4vc-verifier/OpenId4VcVerificationSessionState.mjs.map +1 -0
- package/build/openid4vc-verifier/OpenId4VcVerifierApi.d.mts +60 -0
- package/build/openid4vc-verifier/OpenId4VcVerifierApi.d.mts.map +1 -0
- package/build/openid4vc-verifier/OpenId4VcVerifierApi.mjs +83 -0
- package/build/openid4vc-verifier/OpenId4VcVerifierApi.mjs.map +1 -0
- package/build/openid4vc-verifier/OpenId4VcVerifierEvents.d.mts +19 -0
- package/build/openid4vc-verifier/OpenId4VcVerifierEvents.d.mts.map +1 -0
- package/build/openid4vc-verifier/OpenId4VcVerifierEvents.mjs +9 -0
- package/build/openid4vc-verifier/OpenId4VcVerifierEvents.mjs.map +1 -0
- package/build/openid4vc-verifier/OpenId4VcVerifierModule.d.mts +25 -0
- package/build/openid4vc-verifier/OpenId4VcVerifierModule.d.mts.map +1 -0
- package/build/openid4vc-verifier/OpenId4VcVerifierModule.mjs +91 -0
- package/build/openid4vc-verifier/OpenId4VcVerifierModule.mjs.map +1 -0
- package/build/openid4vc-verifier/OpenId4VcVerifierModuleConfig.d.mts +55 -0
- package/build/openid4vc-verifier/OpenId4VcVerifierModuleConfig.d.mts.map +1 -0
- package/build/openid4vc-verifier/OpenId4VcVerifierModuleConfig.mjs +36 -0
- package/build/openid4vc-verifier/OpenId4VcVerifierModuleConfig.mjs.map +1 -0
- package/build/openid4vc-verifier/OpenId4VpVerifierService.d.mts +60 -0
- package/build/openid4vc-verifier/OpenId4VpVerifierService.d.mts.map +1 -0
- package/build/openid4vc-verifier/OpenId4VpVerifierService.mjs +714 -0
- package/build/openid4vc-verifier/OpenId4VpVerifierService.mjs.map +1 -0
- package/build/openid4vc-verifier/OpenId4VpVerifierServiceOptions.d.mts +194 -0
- package/build/openid4vc-verifier/OpenId4VpVerifierServiceOptions.d.mts.map +1 -0
- package/build/openid4vc-verifier/index.d.mts +12 -0
- package/build/openid4vc-verifier/index.mjs +11 -0
- package/build/openid4vc-verifier/repository/OpenId4VcVerificationSessionRecord.d.mts +129 -0
- package/build/openid4vc-verifier/repository/OpenId4VcVerificationSessionRecord.d.mts.map +1 -0
- package/build/openid4vc-verifier/repository/OpenId4VcVerificationSessionRecord.mjs +64 -0
- package/build/openid4vc-verifier/repository/OpenId4VcVerificationSessionRecord.mjs.map +1 -0
- package/build/openid4vc-verifier/repository/OpenId4VcVerificationSessionRepository.d.mts +10 -0
- package/build/openid4vc-verifier/repository/OpenId4VcVerificationSessionRepository.d.mts.map +1 -0
- package/build/openid4vc-verifier/repository/OpenId4VcVerificationSessionRepository.mjs +22 -0
- package/build/openid4vc-verifier/repository/OpenId4VcVerificationSessionRepository.mjs.map +1 -0
- package/build/openid4vc-verifier/repository/OpenId4VcVerifierRecord.d.mts +33 -0
- package/build/openid4vc-verifier/repository/OpenId4VcVerifierRecord.d.mts.map +1 -0
- package/build/openid4vc-verifier/repository/OpenId4VcVerifierRecord.mjs +32 -0
- package/build/openid4vc-verifier/repository/OpenId4VcVerifierRecord.mjs.map +1 -0
- package/build/openid4vc-verifier/repository/OpenId4VcVerifierRepository.d.mts +12 -0
- package/build/openid4vc-verifier/repository/OpenId4VcVerifierRepository.d.mts.map +1 -0
- package/build/openid4vc-verifier/repository/OpenId4VcVerifierRepository.mjs +28 -0
- package/build/openid4vc-verifier/repository/OpenId4VcVerifierRepository.mjs.map +1 -0
- package/build/openid4vc-verifier/repository/index.d.mts +4 -0
- package/build/openid4vc-verifier/repository/index.mjs +4 -0
- package/build/openid4vc-verifier/router/authorizationEndpoint.mjs +117 -0
- package/build/openid4vc-verifier/router/authorizationEndpoint.mjs.map +1 -0
- package/build/openid4vc-verifier/router/authorizationRequestEndpoint.mjs +39 -0
- package/build/openid4vc-verifier/router/authorizationRequestEndpoint.mjs.map +1 -0
- package/build/openid4vc-verifier/router/index.mjs +1 -0
- package/build/shared/callbacks.d.mts +47 -0
- package/build/shared/callbacks.d.mts.map +1 -0
- package/build/shared/callbacks.mjs +279 -0
- package/build/shared/callbacks.mjs.map +1 -0
- package/build/shared/index.d.mts +7 -0
- package/build/shared/index.mjs +4 -0
- package/build/shared/issuerMetadataUtils.d.mts +22 -0
- package/build/shared/issuerMetadataUtils.d.mts.map +1 -0
- package/build/shared/issuerMetadataUtils.mjs +30 -0
- package/build/shared/issuerMetadataUtils.mjs.map +1 -0
- package/build/shared/models/CredentialHolderBinding.d.mts +71 -0
- package/build/shared/models/CredentialHolderBinding.d.mts.map +1 -0
- package/build/shared/models/CredentialHolderBinding.mjs +1 -0
- package/build/shared/models/OpenId4VcJwtIssuer.d.mts +46 -0
- package/build/shared/models/OpenId4VcJwtIssuer.d.mts.map +1 -0
- package/build/shared/models/OpenId4VcJwtIssuer.mjs +1 -0
- package/build/shared/models/OpenId4VciAuthorizationServerConfig.d.mts +71 -0
- package/build/shared/models/OpenId4VciAuthorizationServerConfig.d.mts.map +1 -0
- package/build/shared/models/OpenId4VciCredentialFormatProfile.d.mts +12 -0
- package/build/shared/models/OpenId4VciCredentialFormatProfile.d.mts.map +1 -0
- package/build/shared/models/OpenId4VciCredentialFormatProfile.mjs +14 -0
- package/build/shared/models/OpenId4VciCredentialFormatProfile.mjs.map +1 -0
- package/build/shared/models/index.d.mts +30 -0
- package/build/shared/models/index.d.mts.map +1 -0
- package/build/shared/models/index.mjs +6 -0
- package/build/shared/router/context.mjs +52 -0
- package/build/shared/router/context.mjs.map +1 -0
- package/build/shared/router/express.browser.d.mts +5 -0
- package/build/shared/router/express.browser.d.mts.map +1 -0
- package/build/shared/router/express.browser.mjs +8 -0
- package/build/shared/router/express.browser.mjs.map +1 -0
- package/build/shared/router/express.mjs +10 -0
- package/build/shared/router/express.mjs.map +1 -0
- package/build/shared/router/express.native.d.mts +5 -0
- package/build/shared/router/express.native.d.mts.map +1 -0
- package/build/shared/router/express.native.mjs +8 -0
- package/build/shared/router/express.native.mjs.map +1 -0
- package/build/shared/router/index.mjs +3 -0
- package/build/shared/router/tenants.mjs +36 -0
- package/build/shared/router/tenants.mjs.map +1 -0
- package/build/shared/transactionData.mjs +19 -0
- package/build/shared/transactionData.mjs.map +1 -0
- package/build/shared/utils.mjs +90 -0
- package/build/shared/utils.mjs.map +1 -0
- package/package.json +30 -23
- package/build/index.d.ts +0 -4
- package/build/index.js +0 -21
- package/build/index.js.map +0 -1
- package/build/openid4vc-holder/OpenId4VcHolderApi.d.ts +0 -124
- package/build/openid4vc-holder/OpenId4VcHolderApi.js +0 -155
- package/build/openid4vc-holder/OpenId4VcHolderApi.js.map +0 -1
- package/build/openid4vc-holder/OpenId4VcHolderModule.d.ts +0 -13
- package/build/openid4vc-holder/OpenId4VcHolderModule.js +0 -35
- package/build/openid4vc-holder/OpenId4VcHolderModule.js.map +0 -1
- package/build/openid4vc-holder/OpenId4VciHolderService.d.ts +0 -72
- package/build/openid4vc-holder/OpenId4VciHolderService.js +0 -569
- package/build/openid4vc-holder/OpenId4VciHolderService.js.map +0 -1
- package/build/openid4vc-holder/OpenId4VciHolderServiceOptions.d.ts +0 -238
- package/build/openid4vc-holder/OpenId4VciHolderServiceOptions.js +0 -14
- package/build/openid4vc-holder/OpenId4VciHolderServiceOptions.js.map +0 -1
- package/build/openid4vc-holder/OpenId4vcSiopHolderService.d.ts +0 -32
- package/build/openid4vc-holder/OpenId4vcSiopHolderService.js +0 -302
- package/build/openid4vc-holder/OpenId4vcSiopHolderService.js.map +0 -1
- package/build/openid4vc-holder/OpenId4vcSiopHolderServiceOptions.d.ts +0 -38
- package/build/openid4vc-holder/OpenId4vcSiopHolderServiceOptions.js +0 -3
- package/build/openid4vc-holder/OpenId4vcSiopHolderServiceOptions.js.map +0 -1
- package/build/openid4vc-holder/index.d.ts +0 -6
- package/build/openid4vc-holder/index.js +0 -23
- package/build/openid4vc-holder/index.js.map +0 -1
- package/build/openid4vc-issuer/OpenId4VcIssuanceSessionState.d.ts +0 -12
- package/build/openid4vc-issuer/OpenId4VcIssuanceSessionState.js +0 -19
- package/build/openid4vc-issuer/OpenId4VcIssuanceSessionState.js.map +0 -1
- package/build/openid4vc-issuer/OpenId4VcIssuerApi.d.ts +0 -101
- package/build/openid4vc-issuer/OpenId4VcIssuerApi.js +0 -110
- package/build/openid4vc-issuer/OpenId4VcIssuerApi.js.map +0 -1
- package/build/openid4vc-issuer/OpenId4VcIssuerEvents.d.ts +0 -13
- package/build/openid4vc-issuer/OpenId4VcIssuerEvents.js +0 -8
- package/build/openid4vc-issuer/OpenId4VcIssuerEvents.js.map +0 -1
- package/build/openid4vc-issuer/OpenId4VcIssuerModule.d.ts +0 -21
- package/build/openid4vc-issuer/OpenId4VcIssuerModule.js +0 -121
- package/build/openid4vc-issuer/OpenId4VcIssuerModule.js.map +0 -1
- package/build/openid4vc-issuer/OpenId4VcIssuerModuleConfig.d.ts +0 -190
- package/build/openid4vc-issuer/OpenId4VcIssuerModuleConfig.js +0 -141
- package/build/openid4vc-issuer/OpenId4VcIssuerModuleConfig.js.map +0 -1
- package/build/openid4vc-issuer/OpenId4VcIssuerService.d.ts +0 -116
- package/build/openid4vc-issuer/OpenId4VcIssuerService.js +0 -698
- package/build/openid4vc-issuer/OpenId4VcIssuerService.js.map +0 -1
- package/build/openid4vc-issuer/OpenId4VcIssuerServiceOptions.d.ts +0 -229
- package/build/openid4vc-issuer/OpenId4VcIssuerServiceOptions.js +0 -3
- package/build/openid4vc-issuer/OpenId4VcIssuerServiceOptions.js.map +0 -1
- package/build/openid4vc-issuer/index.d.ts +0 -8
- package/build/openid4vc-issuer/index.js +0 -27
- package/build/openid4vc-issuer/index.js.map +0 -1
- package/build/openid4vc-issuer/repository/OpenId4VcIssuanceSessionRecord.d.ts +0 -160
- package/build/openid4vc-issuer/repository/OpenId4VcIssuanceSessionRecord.js +0 -88
- package/build/openid4vc-issuer/repository/OpenId4VcIssuanceSessionRecord.js.map +0 -1
- package/build/openid4vc-issuer/repository/OpenId4VcIssuanceSessionRepository.d.ts +0 -5
- package/build/openid4vc-issuer/repository/OpenId4VcIssuanceSessionRepository.js +0 -29
- package/build/openid4vc-issuer/repository/OpenId4VcIssuanceSessionRepository.js.map +0 -1
- package/build/openid4vc-issuer/repository/OpenId4VcIssuerRecord.d.ts +0 -56
- package/build/openid4vc-issuer/repository/OpenId4VcIssuerRecord.js +0 -83
- package/build/openid4vc-issuer/repository/OpenId4VcIssuerRecord.js.map +0 -1
- package/build/openid4vc-issuer/repository/OpenId4VcIssuerRepository.d.ts +0 -8
- package/build/openid4vc-issuer/repository/OpenId4VcIssuerRepository.js +0 -35
- package/build/openid4vc-issuer/repository/OpenId4VcIssuerRepository.js.map +0 -1
- package/build/openid4vc-issuer/repository/index.d.ts +0 -4
- package/build/openid4vc-issuer/repository/index.js +0 -21
- package/build/openid4vc-issuer/repository/index.js.map +0 -1
- package/build/openid4vc-issuer/router/accessTokenEndpoint.d.ts +0 -5
- package/build/openid4vc-issuer/router/accessTokenEndpoint.js +0 -164
- package/build/openid4vc-issuer/router/accessTokenEndpoint.js.map +0 -1
- package/build/openid4vc-issuer/router/authorizationChallengeEndpoint.d.ts +0 -3
- package/build/openid4vc-issuer/router/authorizationChallengeEndpoint.js +0 -213
- package/build/openid4vc-issuer/router/authorizationChallengeEndpoint.js.map +0 -1
- package/build/openid4vc-issuer/router/authorizationServerMetadataEndpoint.d.ts +0 -6
- package/build/openid4vc-issuer/router/authorizationServerMetadataEndpoint.js +0 -25
- package/build/openid4vc-issuer/router/authorizationServerMetadataEndpoint.js.map +0 -1
- package/build/openid4vc-issuer/router/credentialEndpoint.d.ts +0 -3
- package/build/openid4vc-issuer/router/credentialEndpoint.js +0 -176
- package/build/openid4vc-issuer/router/credentialEndpoint.js.map +0 -1
- package/build/openid4vc-issuer/router/credentialOfferEndpoint.d.ts +0 -3
- package/build/openid4vc-issuer/router/credentialOfferEndpoint.js +0 -45
- package/build/openid4vc-issuer/router/credentialOfferEndpoint.js.map +0 -1
- package/build/openid4vc-issuer/router/index.d.ts +0 -9
- package/build/openid4vc-issuer/router/index.js +0 -20
- package/build/openid4vc-issuer/router/index.js.map +0 -1
- package/build/openid4vc-issuer/router/issuerMetadataEndpoint.d.ts +0 -2
- package/build/openid4vc-issuer/router/issuerMetadataEndpoint.js +0 -26
- package/build/openid4vc-issuer/router/issuerMetadataEndpoint.js.map +0 -1
- package/build/openid4vc-issuer/router/jwksEndpoint.d.ts +0 -3
- package/build/openid4vc-issuer/router/jwksEndpoint.js +0 -20
- package/build/openid4vc-issuer/router/jwksEndpoint.js.map +0 -1
- package/build/openid4vc-issuer/router/nonceEndpoint.d.ts +0 -3
- package/build/openid4vc-issuer/router/nonceEndpoint.js +0 -26
- package/build/openid4vc-issuer/router/nonceEndpoint.js.map +0 -1
- package/build/openid4vc-issuer/router/requestContext.d.ts +0 -5
- package/build/openid4vc-issuer/router/requestContext.js +0 -3
- package/build/openid4vc-issuer/router/requestContext.js.map +0 -1
- package/build/openid4vc-issuer/util/txCode.d.ts +0 -3
- package/build/openid4vc-issuer/util/txCode.js +0 -18
- package/build/openid4vc-issuer/util/txCode.js.map +0 -1
- package/build/openid4vc-verifier/OpenId4VcSiopVerifierService.d.ts +0 -55
- package/build/openid4vc-verifier/OpenId4VcSiopVerifierService.js +0 -498
- package/build/openid4vc-verifier/OpenId4VcSiopVerifierService.js.map +0 -1
- package/build/openid4vc-verifier/OpenId4VcSiopVerifierServiceOptions.d.ts +0 -77
- package/build/openid4vc-verifier/OpenId4VcSiopVerifierServiceOptions.js +0 -3
- package/build/openid4vc-verifier/OpenId4VcSiopVerifierServiceOptions.js.map +0 -1
- package/build/openid4vc-verifier/OpenId4VcVerificationSessionState.d.ts +0 -6
- package/build/openid4vc-verifier/OpenId4VcVerificationSessionState.js +0 -11
- package/build/openid4vc-verifier/OpenId4VcVerificationSessionState.js.map +0 -1
- package/build/openid4vc-verifier/OpenId4VcVerifierApi.d.ts +0 -61
- package/build/openid4vc-verifier/OpenId4VcVerifierApi.js +0 -108
- package/build/openid4vc-verifier/OpenId4VcVerifierApi.js.map +0 -1
- package/build/openid4vc-verifier/OpenId4VcVerifierEvents.d.ts +0 -13
- package/build/openid4vc-verifier/OpenId4VcVerifierEvents.js +0 -8
- package/build/openid4vc-verifier/OpenId4VcVerifierEvents.js.map +0 -1
- package/build/openid4vc-verifier/OpenId4VcVerifierModule.d.ts +0 -21
- package/build/openid4vc-verifier/OpenId4VcVerifierModule.js +0 -109
- package/build/openid4vc-verifier/OpenId4VcVerifierModule.js.map +0 -1
- package/build/openid4vc-verifier/OpenId4VcVerifierModuleConfig.d.ts +0 -31
- package/build/openid4vc-verifier/OpenId4VcVerifierModuleConfig.js +0 -28
- package/build/openid4vc-verifier/OpenId4VcVerifierModuleConfig.js.map +0 -1
- package/build/openid4vc-verifier/index.d.ts +0 -8
- package/build/openid4vc-verifier/index.js +0 -25
- package/build/openid4vc-verifier/index.js.map +0 -1
- package/build/openid4vc-verifier/repository/OpenId4VcRelyingPartyEventEmitter.d.ts +0 -49
- package/build/openid4vc-verifier/repository/OpenId4VcRelyingPartyEventEmitter.js +0 -234
- package/build/openid4vc-verifier/repository/OpenId4VcRelyingPartyEventEmitter.js.map +0 -1
- package/build/openid4vc-verifier/repository/OpenId4VcRelyingPartySessionManager.d.ts +0 -19
- package/build/openid4vc-verifier/repository/OpenId4VcRelyingPartySessionManager.js +0 -146
- package/build/openid4vc-verifier/repository/OpenId4VcRelyingPartySessionManager.js.map +0 -1
- package/build/openid4vc-verifier/repository/OpenId4VcVerificationSessionRecord.d.ts +0 -71
- package/build/openid4vc-verifier/repository/OpenId4VcVerificationSessionRecord.js +0 -46
- package/build/openid4vc-verifier/repository/OpenId4VcVerificationSessionRecord.js.map +0 -1
- package/build/openid4vc-verifier/repository/OpenId4VcVerificationSessionRepository.d.ts +0 -5
- package/build/openid4vc-verifier/repository/OpenId4VcVerificationSessionRepository.js +0 -29
- package/build/openid4vc-verifier/repository/OpenId4VcVerificationSessionRepository.js.map +0 -1
- package/build/openid4vc-verifier/repository/OpenId4VcVerifierRecord.d.ts +0 -29
- package/build/openid4vc-verifier/repository/OpenId4VcVerifierRecord.js +0 -29
- package/build/openid4vc-verifier/repository/OpenId4VcVerifierRecord.js.map +0 -1
- package/build/openid4vc-verifier/repository/OpenId4VcVerifierRepository.d.ts +0 -8
- package/build/openid4vc-verifier/repository/OpenId4VcVerifierRepository.js +0 -35
- package/build/openid4vc-verifier/repository/OpenId4VcVerifierRepository.js.map +0 -1
- package/build/openid4vc-verifier/repository/index.d.ts +0 -4
- package/build/openid4vc-verifier/repository/index.js +0 -21
- package/build/openid4vc-verifier/repository/index.js.map +0 -1
- package/build/openid4vc-verifier/router/authorizationEndpoint.d.ts +0 -11
- package/build/openid4vc-verifier/router/authorizationEndpoint.js +0 -102
- package/build/openid4vc-verifier/router/authorizationEndpoint.js.map +0 -1
- package/build/openid4vc-verifier/router/authorizationRequestEndpoint.d.ts +0 -11
- package/build/openid4vc-verifier/router/authorizationRequestEndpoint.js +0 -63
- package/build/openid4vc-verifier/router/authorizationRequestEndpoint.js.map +0 -1
- package/build/openid4vc-verifier/router/index.d.ts +0 -2
- package/build/openid4vc-verifier/router/index.js +0 -6
- package/build/openid4vc-verifier/router/index.js.map +0 -1
- package/build/openid4vc-verifier/router/requestContext.d.ts +0 -5
- package/build/openid4vc-verifier/router/requestContext.js +0 -3
- package/build/openid4vc-verifier/router/requestContext.js.map +0 -1
- package/build/shared/callbacks.d.ts +0 -18
- package/build/shared/callbacks.js +0 -81
- package/build/shared/callbacks.js.map +0 -1
- package/build/shared/index.d.ts +0 -2
- package/build/shared/index.js +0 -19
- package/build/shared/index.js.map +0 -1
- package/build/shared/issuerMetadataUtils.d.ts +0 -158
- package/build/shared/issuerMetadataUtils.js +0 -38
- package/build/shared/issuerMetadataUtils.js.map +0 -1
- package/build/shared/models/CredentialHolderBinding.d.ts +0 -13
- package/build/shared/models/CredentialHolderBinding.js +0 -3
- package/build/shared/models/CredentialHolderBinding.js.map +0 -1
- package/build/shared/models/OpenId4VcJwtIssuer.d.ts +0 -28
- package/build/shared/models/OpenId4VcJwtIssuer.js +0 -3
- package/build/shared/models/OpenId4VcJwtIssuer.js.map +0 -1
- package/build/shared/models/OpenId4VciAuthorizationServerConfig.d.ts +0 -10
- package/build/shared/models/OpenId4VciAuthorizationServerConfig.js +0 -3
- package/build/shared/models/OpenId4VciAuthorizationServerConfig.js.map +0 -1
- package/build/shared/models/OpenId4VciCredentialFormatProfile.d.ts +0 -7
- package/build/shared/models/OpenId4VciCredentialFormatProfile.js +0 -12
- package/build/shared/models/OpenId4VciCredentialFormatProfile.js.map +0 -1
- package/build/shared/models/index.d.ts +0 -24
- package/build/shared/models/index.js +0 -25
- package/build/shared/models/index.js.map +0 -1
- package/build/shared/router/context.d.ts +0 -17
- package/build/shared/router/context.js +0 -76
- package/build/shared/router/context.js.map +0 -1
- package/build/shared/router/express.d.ts +0 -2
- package/build/shared/router/express.js +0 -15
- package/build/shared/router/express.js.map +0 -1
- package/build/shared/router/express.native.d.ts +0 -1
- package/build/shared/router/express.native.js +0 -7
- package/build/shared/router/express.native.js.map +0 -1
- package/build/shared/router/index.d.ts +0 -3
- package/build/shared/router/index.js +0 -20
- package/build/shared/router/index.js.map +0 -1
- package/build/shared/router/tenants.d.ts +0 -13
- package/build/shared/router/tenants.js +0 -49
- package/build/shared/router/tenants.js.map +0 -1
- package/build/shared/transform.d.ts +0 -5
- package/build/shared/transform.js +0 -73
- package/build/shared/transform.js.map +0 -1
- package/build/shared/utils.d.ts +0 -22
- package/build/shared/utils.js +0 -154
- package/build/shared/utils.js.map +0 -1
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import { OpenId4VcIssuerModuleConfig } from "../OpenId4VcIssuerModuleConfig.mjs";
|
|
2
|
+
import { getRequestContext, sendJsonResponse, sendOauth2ErrorResponse, sendUnknownServerErrorResponse } from "../../shared/router/context.mjs";
|
|
3
|
+
import "../../shared/router/index.mjs";
|
|
4
|
+
import { getAllowedAndRequestedScopeValues, getCredentialConfigurationsSupportedForScopes, getOfferedCredentials, getScopesFromCredentialConfigurationsSupported } from "../../shared/issuerMetadataUtils.mjs";
|
|
5
|
+
import "../../shared/index.mjs";
|
|
6
|
+
import { OpenId4VcIssuanceSessionState } from "../OpenId4VcIssuanceSessionState.mjs";
|
|
7
|
+
import { OpenId4VcVerificationSessionState } from "../../openid4vc-verifier/OpenId4VcVerificationSessionState.mjs";
|
|
8
|
+
import { OpenId4VcVerificationSessionRepository } from "../../openid4vc-verifier/repository/OpenId4VcVerificationSessionRepository.mjs";
|
|
9
|
+
import { OpenId4VcVerifierApi } from "../../openid4vc-verifier/OpenId4VcVerifierApi.mjs";
|
|
10
|
+
import "../../openid4vc-verifier/index.mjs";
|
|
11
|
+
import { OpenId4VcIssuerService } from "../OpenId4VcIssuerService.mjs";
|
|
12
|
+
import { handlePushedAuthorizationRequest } from "./pushedAuthorizationRequestEndpoint.mjs";
|
|
13
|
+
import { Kms, TypedArrayEncoder, joinUriParts, utils } from "@credo-ts/core";
|
|
14
|
+
import { Oauth2ErrorCodes, Oauth2ServerErrorResponseError, decodeJwt } from "@openid4vc/oauth2";
|
|
15
|
+
|
|
16
|
+
//#region src/openid4vc-issuer/router/authorizationChallengeEndpoint.ts
|
|
17
|
+
function configureAuthorizationChallengeEndpoint(router, config) {
|
|
18
|
+
router.post(config.authorizationChallengeEndpointPath, async (request, response, next) => {
|
|
19
|
+
const { agentContext, issuer } = getRequestContext(request);
|
|
20
|
+
try {
|
|
21
|
+
const openId4VcIssuerService = agentContext.dependencyManager.resolve(OpenId4VcIssuerService);
|
|
22
|
+
const issuerMetadata = await openId4VcIssuerService.getIssuerMetadata(agentContext, issuer);
|
|
23
|
+
const authorizationServer = openId4VcIssuerService.getOauth2AuthorizationServer(agentContext);
|
|
24
|
+
const fullRequestUrl = joinUriParts(issuerMetadata.credentialIssuer.credential_issuer, [config.authorizationChallengeEndpointPath]);
|
|
25
|
+
const requestLike = {
|
|
26
|
+
headers: new Headers(request.headers),
|
|
27
|
+
method: request.method,
|
|
28
|
+
url: fullRequestUrl
|
|
29
|
+
};
|
|
30
|
+
const parseResult = authorizationServer.parseAuthorizationChallengeRequest({
|
|
31
|
+
authorizationChallengeRequest: request.body,
|
|
32
|
+
request: requestLike
|
|
33
|
+
});
|
|
34
|
+
const { authorizationChallengeRequest } = parseResult;
|
|
35
|
+
if (authorizationChallengeRequest.auth_session) await handleAuthorizationChallengeWithAuthSession({
|
|
36
|
+
response,
|
|
37
|
+
next,
|
|
38
|
+
parseResult,
|
|
39
|
+
request: requestLike,
|
|
40
|
+
agentContext,
|
|
41
|
+
issuer
|
|
42
|
+
});
|
|
43
|
+
else await handleAuthorizationChallengeNoAuthSession({
|
|
44
|
+
agentContext,
|
|
45
|
+
issuer,
|
|
46
|
+
parseResult,
|
|
47
|
+
request: requestLike
|
|
48
|
+
});
|
|
49
|
+
} catch (error) {
|
|
50
|
+
if (error instanceof Oauth2ServerErrorResponseError) return sendOauth2ErrorResponse(response, next, agentContext.config.logger, error);
|
|
51
|
+
return sendUnknownServerErrorResponse(response, next, agentContext.config.logger, error);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Handle authorization challenge request without auth session. This endpoint
|
|
57
|
+
* may fall back to a Pushed Authorization Request if no presentation during issuance
|
|
58
|
+
* is required.
|
|
59
|
+
*/
|
|
60
|
+
async function handleAuthorizationChallengeNoAuthSession(options) {
|
|
61
|
+
const { agentContext, issuer, parseResult, request } = options;
|
|
62
|
+
const { authorizationChallengeRequest } = parseResult;
|
|
63
|
+
const openId4VcIssuerService = agentContext.dependencyManager.resolve(OpenId4VcIssuerService);
|
|
64
|
+
const config = agentContext.dependencyManager.resolve(OpenId4VcIssuerModuleConfig);
|
|
65
|
+
const issuerMetadata = await openId4VcIssuerService.getIssuerMetadata(agentContext, issuer);
|
|
66
|
+
if (!authorizationChallengeRequest.issuer_state) throw new Oauth2ServerErrorResponseError({
|
|
67
|
+
error: Oauth2ErrorCodes.InvalidRequest,
|
|
68
|
+
error_description: `Missing required 'issuer_state' parameter. Only requests initiated by a credential offer are supported for authorization challenge.`
|
|
69
|
+
});
|
|
70
|
+
if (!authorizationChallengeRequest.scope) throw new Oauth2ServerErrorResponseError({
|
|
71
|
+
error: Oauth2ErrorCodes.InvalidScope,
|
|
72
|
+
error_description: `Missing required 'scope' parameter`
|
|
73
|
+
});
|
|
74
|
+
const issuanceSession = await openId4VcIssuerService.findSingleIssuanceSessionByQuery(agentContext, {
|
|
75
|
+
issuerId: issuer.issuerId,
|
|
76
|
+
issuerState: authorizationChallengeRequest.issuer_state
|
|
77
|
+
});
|
|
78
|
+
const allowedStates = [OpenId4VcIssuanceSessionState.OfferCreated, OpenId4VcIssuanceSessionState.OfferUriRetrieved];
|
|
79
|
+
if (!issuanceSession || !allowedStates.includes(issuanceSession.state)) throw new Oauth2ServerErrorResponseError({
|
|
80
|
+
error: Oauth2ErrorCodes.InvalidRequest,
|
|
81
|
+
error_description: `Invalid 'issuer_state' parameter`
|
|
82
|
+
}, { internalMessage: !issuanceSession ? `Issuance session not found for 'issuer_state' parameter '${authorizationChallengeRequest.issuer_state}'` : `Issuance session '${issuanceSession.id}' has state '${issuanceSession.state}' but expected one of ${allowedStates.join(", ")}` });
|
|
83
|
+
if (issuanceSession?.chainedIdentity?.externalAuthorizationServerUrl) {
|
|
84
|
+
const clientId = parseResult.authorizationChallengeRequest.client_id ?? (parseResult.clientAttestation?.clientAttestationJwt ? decodeJwt({ jwt: parseResult.clientAttestation.clientAttestationJwt }).payload.sub : void 0);
|
|
85
|
+
if (!clientId || typeof clientId !== "string") throw new Oauth2ServerErrorResponseError({
|
|
86
|
+
error: Oauth2ErrorCodes.InvalidClient,
|
|
87
|
+
error_description: `Missing required 'client_id' parameter in authorization request.`
|
|
88
|
+
});
|
|
89
|
+
const { pushedAuthorizationResponse } = await handlePushedAuthorizationRequest(agentContext, {
|
|
90
|
+
issuer,
|
|
91
|
+
issuanceSession,
|
|
92
|
+
parsedAuthorizationRequest: {
|
|
93
|
+
clientAttestation: parseResult.clientAttestation,
|
|
94
|
+
dpop: parseResult.dpop,
|
|
95
|
+
authorizationRequest: {
|
|
96
|
+
...parseResult.authorizationChallengeRequest,
|
|
97
|
+
response_type: "code",
|
|
98
|
+
client_id: clientId
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
request
|
|
102
|
+
});
|
|
103
|
+
throw new Oauth2ServerErrorResponseError({
|
|
104
|
+
error: Oauth2ErrorCodes.RedirectToWeb,
|
|
105
|
+
error_description: "Authorization required before issuance",
|
|
106
|
+
...pushedAuthorizationResponse
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
if (!issuanceSession.presentation?.required) throw new Oauth2ServerErrorResponseError({
|
|
110
|
+
error: Oauth2ErrorCodes.InvalidRequest,
|
|
111
|
+
error_description: `Invalid 'issuer_state' parameter`
|
|
112
|
+
}, { internalMessage: `Neither presentation during issuance or identity chaining was configured on issuance session '${issuanceSession.id}'` });
|
|
113
|
+
if (!config.getVerificationSessionForIssuanceSessionAuthorization) throw new Oauth2ServerErrorResponseError({ error: Oauth2ErrorCodes.ServerError }, { internalMessage: `Missing required 'getVerificationSessionForIssuanceSessionAuthorization' callback in openid4vc issuer module config. This callback is required for presentation during issuance flows.` });
|
|
114
|
+
const authorizationServer = openId4VcIssuerService.getOauth2AuthorizationServer(agentContext, { issuanceSessionId: issuanceSession.id });
|
|
115
|
+
const { clientAttestation, dpop } = await authorizationServer.verifyAuthorizationChallengeRequest({
|
|
116
|
+
authorizationChallengeRequest,
|
|
117
|
+
authorizationServerMetadata: issuerMetadata.authorizationServers[0],
|
|
118
|
+
request,
|
|
119
|
+
clientAttestation: {
|
|
120
|
+
...parseResult.clientAttestation,
|
|
121
|
+
required: issuanceSession.walletAttestation?.required ?? config.walletAttestationsRequired
|
|
122
|
+
},
|
|
123
|
+
dpop: {
|
|
124
|
+
...parseResult.dpop,
|
|
125
|
+
required: issuanceSession.dpop?.required ?? config.dpopRequired
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
if (dpop) issuanceSession.dpop = {
|
|
129
|
+
required: true,
|
|
130
|
+
dpopJkt: dpop.jwkThumbprint
|
|
131
|
+
};
|
|
132
|
+
if (clientAttestation) issuanceSession.walletAttestation = { required: true };
|
|
133
|
+
const offeredCredentialConfigurations = getOfferedCredentials(issuanceSession.credentialOfferPayload.credential_configuration_ids, issuerMetadata.credentialIssuer.credential_configurations_supported);
|
|
134
|
+
const requestedScopes = getAllowedAndRequestedScopeValues({
|
|
135
|
+
allowedScopes: getScopesFromCredentialConfigurationsSupported(offeredCredentialConfigurations),
|
|
136
|
+
requestedScope: authorizationChallengeRequest.scope
|
|
137
|
+
});
|
|
138
|
+
const requestedCredentialConfigurations = getCredentialConfigurationsSupportedForScopes(offeredCredentialConfigurations, requestedScopes);
|
|
139
|
+
if (requestedScopes.length === 0 || Object.keys(requestedCredentialConfigurations).length === 0) throw new Oauth2ServerErrorResponseError({
|
|
140
|
+
error: Oauth2ErrorCodes.InvalidScope,
|
|
141
|
+
error_description: `No requested 'scope' values match with offered credential configurations.`
|
|
142
|
+
});
|
|
143
|
+
const { authorizationRequest, verificationSession, scopes: presentationScopes } = await config.getVerificationSessionForIssuanceSessionAuthorization({
|
|
144
|
+
agentContext,
|
|
145
|
+
issuanceSession,
|
|
146
|
+
requestedCredentialConfigurations,
|
|
147
|
+
scopes: requestedScopes
|
|
148
|
+
});
|
|
149
|
+
const kms = agentContext.resolve(Kms.KeyManagementApi);
|
|
150
|
+
verificationSession.presentationDuringIssuanceSession = TypedArrayEncoder.toBase64URL(kms.randomBytes({ length: 32 }));
|
|
151
|
+
await agentContext.dependencyManager.resolve(OpenId4VcVerificationSessionRepository).update(agentContext, verificationSession);
|
|
152
|
+
const authSession = TypedArrayEncoder.toBase64URL(kms.randomBytes({ length: 32 }));
|
|
153
|
+
issuanceSession.authorization = {
|
|
154
|
+
...issuanceSession.authorization,
|
|
155
|
+
scopes: presentationScopes
|
|
156
|
+
};
|
|
157
|
+
issuanceSession.presentation = {
|
|
158
|
+
required: true,
|
|
159
|
+
authSession,
|
|
160
|
+
openId4VcVerificationSessionId: verificationSession.id
|
|
161
|
+
};
|
|
162
|
+
issuanceSession.clientId = clientAttestation?.clientAttestation.payload.sub ?? authorizationChallengeRequest.client_id;
|
|
163
|
+
await openId4VcIssuerService.updateState(agentContext, issuanceSession, OpenId4VcIssuanceSessionState.AuthorizationInitiated);
|
|
164
|
+
throw new Oauth2ServerErrorResponseError(authorizationServer.createAuthorizationChallengePresentationErrorResponse({
|
|
165
|
+
authSession,
|
|
166
|
+
presentation: authorizationRequest,
|
|
167
|
+
errorDescription: "Presentation required before issuance"
|
|
168
|
+
}));
|
|
169
|
+
}
|
|
170
|
+
async function handleAuthorizationChallengeWithAuthSession(options) {
|
|
171
|
+
const { agentContext, issuer, parseResult, request, response, next } = options;
|
|
172
|
+
const { authorizationChallengeRequest } = parseResult;
|
|
173
|
+
const openId4VcIssuerService = agentContext.dependencyManager.resolve(OpenId4VcIssuerService);
|
|
174
|
+
const config = agentContext.dependencyManager.resolve(OpenId4VcIssuerModuleConfig);
|
|
175
|
+
const issuerMetadata = await openId4VcIssuerService.getIssuerMetadata(agentContext, issuer);
|
|
176
|
+
const verifierApi = agentContext.dependencyManager.resolve(OpenId4VcVerifierApi);
|
|
177
|
+
const issuanceSession = await openId4VcIssuerService.findSingleIssuanceSessionByQuery(agentContext, {
|
|
178
|
+
issuerId: issuer.issuerId,
|
|
179
|
+
presentationAuthSession: authorizationChallengeRequest.auth_session
|
|
180
|
+
});
|
|
181
|
+
const allowedStates = [OpenId4VcIssuanceSessionState.AuthorizationInitiated];
|
|
182
|
+
if (!issuanceSession?.presentation || !issuanceSession.presentation.openId4VcVerificationSessionId || !issuanceSession.presentation.authSession || !allowedStates.includes(issuanceSession.state)) throw new Oauth2ServerErrorResponseError({
|
|
183
|
+
error: Oauth2ErrorCodes.InvalidSession,
|
|
184
|
+
error_description: `Invalid 'auth_session'`
|
|
185
|
+
}, { internalMessage: !issuanceSession ? `Issuance session not found for 'auth_session' parameter '${authorizationChallengeRequest.auth_session}'` : !issuanceSession?.presentation ? `Issuance session '${issuanceSession.id}' has no 'presentation'. This should not happen and means state is corrupted` : `Issuance session '${issuanceSession.id}' has state '${issuanceSession.state}' but expected one of ${allowedStates.join(", ")}` });
|
|
186
|
+
const authorizationServer = openId4VcIssuerService.getOauth2AuthorizationServer(agentContext, { issuanceSessionId: issuanceSession.id });
|
|
187
|
+
const { clientAttestation, dpop } = await authorizationServer.verifyAuthorizationChallengeRequest({
|
|
188
|
+
authorizationChallengeRequest,
|
|
189
|
+
authorizationServerMetadata: issuerMetadata.authorizationServers[0],
|
|
190
|
+
request,
|
|
191
|
+
clientAttestation: {
|
|
192
|
+
...parseResult.clientAttestation,
|
|
193
|
+
required: issuanceSession.walletAttestation?.required
|
|
194
|
+
},
|
|
195
|
+
dpop: {
|
|
196
|
+
...parseResult.dpop,
|
|
197
|
+
required: issuanceSession.dpop?.required
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
if (dpop && dpop.jwkThumbprint !== issuanceSession.dpop?.dpopJkt) throw new Oauth2ServerErrorResponseError({
|
|
201
|
+
error: Oauth2ErrorCodes.InvalidDpopProof,
|
|
202
|
+
error_description: "Invalid jwk thumbprint"
|
|
203
|
+
}, { internalMessage: `DPoP JWK thumbprint '${dpop.jwkThumbprint}' does not match expected value '${issuanceSession.dpop?.dpopJkt}'` });
|
|
204
|
+
if (clientAttestation && clientAttestation.clientAttestation.payload.sub !== issuanceSession.clientId) throw new Oauth2ServerErrorResponseError({
|
|
205
|
+
error: Oauth2ErrorCodes.InvalidClient,
|
|
206
|
+
error_description: "Invalid client"
|
|
207
|
+
}, { internalMessage: `Client id '${authorizationChallengeRequest.client_id}' from authorization challenge request does not match client id '${issuanceSession.clientId}' on issuance session` });
|
|
208
|
+
const { openId4VcVerificationSessionId } = issuanceSession.presentation;
|
|
209
|
+
await verifierApi.getVerificationSessionById(openId4VcVerificationSessionId).catch(async () => {
|
|
210
|
+
issuanceSession.errorMessage = `Associated openId4VcVerificationSessionRecord with id '${openId4VcVerificationSessionId}' does not exist`;
|
|
211
|
+
await openId4VcIssuerService.updateState(agentContext, issuanceSession, OpenId4VcIssuanceSessionState.Error);
|
|
212
|
+
throw new Oauth2ServerErrorResponseError({
|
|
213
|
+
error: Oauth2ErrorCodes.InvalidSession,
|
|
214
|
+
error_description: `Invalid 'auth_session'`
|
|
215
|
+
}, { internalMessage: `Openid4vc verification session with id '${openId4VcVerificationSessionId}' not found during issuance session with id '${issuanceSession.id}'` });
|
|
216
|
+
}).then(async (verificationSession) => {
|
|
217
|
+
if (verificationSession.state === OpenId4VcVerificationSessionState.Error) {
|
|
218
|
+
issuanceSession.errorMessage = `Associated openId4VcVerificationSessionRecord with id '${openId4VcVerificationSessionId}' has error state`;
|
|
219
|
+
await openId4VcIssuerService.updateState(agentContext, issuanceSession, OpenId4VcIssuanceSessionState.Error);
|
|
220
|
+
}
|
|
221
|
+
if (verificationSession.state !== OpenId4VcVerificationSessionState.ResponseVerified || authorizationChallengeRequest.presentation_during_issuance_session !== verificationSession.presentationDuringIssuanceSession) throw new Oauth2ServerErrorResponseError({
|
|
222
|
+
error: Oauth2ErrorCodes.InvalidSession,
|
|
223
|
+
error_description: `Invalid presentation for 'auth_session'`
|
|
224
|
+
}, { internalMessage: verificationSession.state !== OpenId4VcVerificationSessionState.ResponseVerified ? `Openid4vc verification session with id '${openId4VcVerificationSessionId}' has state '${verificationSession.state}', while '${OpenId4VcVerificationSessionState.ResponseVerified}' was expected.` : `Openid4vc verification session with id '${openId4VcVerificationSessionId}' has 'presentation_during_issuance_session' '${verificationSession.presentationDuringIssuanceSession}', but authorization challenge request provided value '${authorizationChallengeRequest.presentation_during_issuance_session}'.` });
|
|
225
|
+
});
|
|
226
|
+
const kms = agentContext.resolve(Kms.KeyManagementApi);
|
|
227
|
+
const authorizationCode = TypedArrayEncoder.toBase64URL(kms.randomBytes({ length: 32 }));
|
|
228
|
+
const authorizationCodeExpiresAt = utils.addSecondsToDate(/* @__PURE__ */ new Date(), config.authorizationCodeExpiresInSeconds);
|
|
229
|
+
issuanceSession.authorization = {
|
|
230
|
+
...issuanceSession.authorization,
|
|
231
|
+
code: authorizationCode,
|
|
232
|
+
codeExpiresAt: authorizationCodeExpiresAt
|
|
233
|
+
};
|
|
234
|
+
await openId4VcIssuerService.updateState(agentContext, issuanceSession, OpenId4VcIssuanceSessionState.AuthorizationGranted);
|
|
235
|
+
const { authorizationChallengeResponse } = authorizationServer.createAuthorizationChallengeResponse({ authorizationCode });
|
|
236
|
+
return sendJsonResponse(response, next, authorizationChallengeResponse);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
//#endregion
|
|
240
|
+
export { configureAuthorizationChallengeEndpoint };
|
|
241
|
+
//# sourceMappingURL=authorizationChallengeEndpoint.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authorizationChallengeEndpoint.mjs","names":[],"sources":["../../../src/openid4vc-issuer/router/authorizationChallengeEndpoint.ts"],"sourcesContent":["import type { AgentContext } from '@credo-ts/core'\nimport { joinUriParts, Kms, TypedArrayEncoder, utils } from '@credo-ts/core'\nimport type { HttpMethod, ParseAuthorizationChallengeRequestResult, RequestLike } from '@openid4vc/oauth2'\nimport { decodeJwt, Oauth2ErrorCodes, Oauth2ServerErrorResponseError } from '@openid4vc/oauth2'\nimport type { NextFunction, Response, Router } from 'express'\nimport {\n OpenId4VcVerificationSessionRepository,\n OpenId4VcVerificationSessionState,\n OpenId4VcVerifierApi,\n} from '../../openid4vc-verifier'\nimport type { OpenId4VciCredentialConfigurationsSupportedWithFormats } from '../../shared'\nimport {\n getAllowedAndRequestedScopeValues,\n getCredentialConfigurationsSupportedForScopes,\n getOfferedCredentials,\n getScopesFromCredentialConfigurationsSupported,\n} from '../../shared'\nimport {\n getRequestContext,\n sendJsonResponse,\n sendOauth2ErrorResponse,\n sendUnknownServerErrorResponse,\n} from '../../shared/router'\nimport { OpenId4VcIssuanceSessionState } from '../OpenId4VcIssuanceSessionState'\nimport { OpenId4VcIssuerModuleConfig } from '../OpenId4VcIssuerModuleConfig'\nimport { OpenId4VcIssuerService } from '../OpenId4VcIssuerService'\nimport type { OpenId4VcIssuerRecord } from '../repository'\nimport { handlePushedAuthorizationRequest } from './pushedAuthorizationRequestEndpoint'\nimport type { OpenId4VcIssuanceRequest } from './requestContext'\n\nexport function configureAuthorizationChallengeEndpoint(router: Router, config: OpenId4VcIssuerModuleConfig) {\n router.post(\n config.authorizationChallengeEndpointPath,\n async (request: OpenId4VcIssuanceRequest, response: Response, next: NextFunction) => {\n const requestContext = getRequestContext(request)\n const { agentContext, issuer } = requestContext\n\n try {\n const openId4VcIssuerService = agentContext.dependencyManager.resolve(OpenId4VcIssuerService)\n const issuerMetadata = await openId4VcIssuerService.getIssuerMetadata(agentContext, issuer)\n const authorizationServer = openId4VcIssuerService.getOauth2AuthorizationServer(agentContext)\n const fullRequestUrl = joinUriParts(issuerMetadata.credentialIssuer.credential_issuer, [\n config.authorizationChallengeEndpointPath,\n ])\n const requestLike = {\n headers: new Headers(request.headers as Record<string, string>),\n method: request.method as HttpMethod,\n url: fullRequestUrl,\n } as const\n\n const parseResult = authorizationServer.parseAuthorizationChallengeRequest({\n authorizationChallengeRequest: request.body,\n request: requestLike,\n })\n\n const { authorizationChallengeRequest } = parseResult\n\n if (authorizationChallengeRequest.auth_session) {\n await handleAuthorizationChallengeWithAuthSession({\n response,\n next,\n parseResult,\n request: requestLike,\n agentContext,\n issuer,\n })\n } else {\n // First call, no auth_session yet\n await handleAuthorizationChallengeNoAuthSession({\n agentContext,\n issuer,\n parseResult,\n request: requestLike,\n })\n }\n } catch (error) {\n if (error instanceof Oauth2ServerErrorResponseError) {\n return sendOauth2ErrorResponse(response, next, agentContext.config.logger, error)\n }\n return sendUnknownServerErrorResponse(response, next, agentContext.config.logger, error)\n }\n }\n )\n}\n\n/**\n * Handle authorization challenge request without auth session. This endpoint\n * may fall back to a Pushed Authorization Request if no presentation during issuance\n * is required.\n */\nasync function handleAuthorizationChallengeNoAuthSession(options: {\n agentContext: AgentContext\n issuer: OpenId4VcIssuerRecord\n parseResult: ParseAuthorizationChallengeRequestResult\n request: RequestLike\n}) {\n const { agentContext, issuer, parseResult, request } = options\n const { authorizationChallengeRequest } = parseResult\n\n const openId4VcIssuerService = agentContext.dependencyManager.resolve(OpenId4VcIssuerService)\n const config = agentContext.dependencyManager.resolve(OpenId4VcIssuerModuleConfig)\n const issuerMetadata = await openId4VcIssuerService.getIssuerMetadata(agentContext, issuer)\n\n if (!authorizationChallengeRequest.issuer_state) {\n throw new Oauth2ServerErrorResponseError({\n error: Oauth2ErrorCodes.InvalidRequest,\n error_description: `Missing required 'issuer_state' parameter. Only requests initiated by a credential offer are supported for authorization challenge.`,\n })\n }\n\n if (!authorizationChallengeRequest.scope) {\n throw new Oauth2ServerErrorResponseError({\n error: Oauth2ErrorCodes.InvalidScope,\n error_description: `Missing required 'scope' parameter`,\n })\n }\n\n const issuanceSession = await openId4VcIssuerService.findSingleIssuanceSessionByQuery(agentContext, {\n issuerId: issuer.issuerId,\n issuerState: authorizationChallengeRequest.issuer_state,\n })\n\n const allowedStates = [OpenId4VcIssuanceSessionState.OfferCreated, OpenId4VcIssuanceSessionState.OfferUriRetrieved]\n if (!issuanceSession || !allowedStates.includes(issuanceSession.state)) {\n throw new Oauth2ServerErrorResponseError(\n {\n error: Oauth2ErrorCodes.InvalidRequest,\n error_description: `Invalid 'issuer_state' parameter`,\n },\n {\n internalMessage: !issuanceSession\n ? `Issuance session not found for 'issuer_state' parameter '${authorizationChallengeRequest.issuer_state}'`\n : `Issuance session '${issuanceSession.id}' has state '${\n issuanceSession.state\n }' but expected one of ${allowedStates.join(', ')}`,\n }\n )\n }\n\n if (issuanceSession?.chainedIdentity?.externalAuthorizationServerUrl) {\n const clientId =\n parseResult.authorizationChallengeRequest.client_id ??\n (parseResult.clientAttestation?.clientAttestationJwt\n ? // FIXME: export scheme for client attestation jwt\n // FIXME: add sub to base jwt type\n decodeJwt({\n jwt: parseResult.clientAttestation.clientAttestationJwt,\n }).payload.sub\n : undefined)\n\n if (!clientId || typeof clientId !== 'string') {\n throw new Oauth2ServerErrorResponseError({\n error: Oauth2ErrorCodes.InvalidClient,\n error_description: `Missing required 'client_id' parameter in authorization request.`,\n })\n }\n\n const { pushedAuthorizationResponse } = await handlePushedAuthorizationRequest(agentContext, {\n issuer,\n issuanceSession,\n parsedAuthorizationRequest: {\n clientAttestation: parseResult.clientAttestation,\n dpop: parseResult.dpop,\n authorizationRequest: {\n ...parseResult.authorizationChallengeRequest,\n response_type: 'code',\n client_id: clientId,\n },\n },\n request,\n })\n\n throw new Oauth2ServerErrorResponseError({\n error: Oauth2ErrorCodes.RedirectToWeb,\n error_description: 'Authorization required before issuance',\n ...pushedAuthorizationResponse,\n })\n }\n\n // From here on 'presentation' MUST be required\n if (!issuanceSession.presentation?.required) {\n throw new Oauth2ServerErrorResponseError(\n {\n error: Oauth2ErrorCodes.InvalidRequest,\n error_description: `Invalid 'issuer_state' parameter`,\n },\n {\n internalMessage: `Neither presentation during issuance or identity chaining was configured on issuance session '${issuanceSession.id}'`,\n }\n )\n }\n\n if (!config.getVerificationSessionForIssuanceSessionAuthorization) {\n throw new Oauth2ServerErrorResponseError(\n {\n error: Oauth2ErrorCodes.ServerError,\n },\n {\n internalMessage: `Missing required 'getVerificationSessionForIssuanceSessionAuthorization' callback in openid4vc issuer module config. This callback is required for presentation during issuance flows.`,\n }\n )\n }\n\n const authorizationServer = openId4VcIssuerService.getOauth2AuthorizationServer(agentContext, {\n issuanceSessionId: issuanceSession.id,\n })\n const { clientAttestation, dpop } = await authorizationServer.verifyAuthorizationChallengeRequest({\n authorizationChallengeRequest,\n authorizationServerMetadata: issuerMetadata.authorizationServers[0],\n request,\n clientAttestation: {\n ...parseResult.clientAttestation,\n // First session config, fall back to global config\n required: issuanceSession.walletAttestation?.required ?? config.walletAttestationsRequired,\n },\n dpop: {\n ...parseResult.dpop,\n // First session config, fall back to global config\n required: issuanceSession.dpop?.required ?? config.dpopRequired,\n },\n })\n\n // Bind dpop jwk thumbprint to session\n if (dpop)\n issuanceSession.dpop = {\n // If dpop is provided at the start, it's required from now on.\n required: true,\n dpopJkt: dpop.jwkThumbprint,\n }\n if (clientAttestation)\n issuanceSession.walletAttestation = {\n // If client attestation is provided at the start, it's required from now on.\n required: true,\n }\n\n const offeredCredentialConfigurations = getOfferedCredentials(\n issuanceSession.credentialOfferPayload.credential_configuration_ids,\n issuerMetadata.credentialIssuer.credential_configurations_supported\n )\n\n const allowedScopes = getScopesFromCredentialConfigurationsSupported(offeredCredentialConfigurations)\n const requestedScopes = getAllowedAndRequestedScopeValues({\n allowedScopes,\n requestedScope: authorizationChallengeRequest.scope,\n })\n const requestedCredentialConfigurations = getCredentialConfigurationsSupportedForScopes(\n offeredCredentialConfigurations,\n requestedScopes\n ) as OpenId4VciCredentialConfigurationsSupportedWithFormats\n\n if (requestedScopes.length === 0 || Object.keys(requestedCredentialConfigurations).length === 0) {\n throw new Oauth2ServerErrorResponseError({\n error: Oauth2ErrorCodes.InvalidScope,\n error_description: `No requested 'scope' values match with offered credential configurations.`,\n })\n }\n\n const {\n authorizationRequest,\n verificationSession,\n scopes: presentationScopes,\n } = await config.getVerificationSessionForIssuanceSessionAuthorization({\n agentContext,\n issuanceSession,\n requestedCredentialConfigurations,\n scopes: requestedScopes,\n })\n\n const kms = agentContext.resolve(Kms.KeyManagementApi)\n // Store presentation during issuance session on the record\n verificationSession.presentationDuringIssuanceSession = TypedArrayEncoder.toBase64URL(kms.randomBytes({ length: 32 }))\n await agentContext.dependencyManager\n .resolve(OpenId4VcVerificationSessionRepository)\n .update(agentContext, verificationSession)\n\n const authSession = TypedArrayEncoder.toBase64URL(kms.randomBytes({ length: 32 }))\n issuanceSession.authorization = {\n ...issuanceSession.authorization,\n scopes: presentationScopes,\n }\n issuanceSession.presentation = {\n required: true,\n authSession,\n openId4VcVerificationSessionId: verificationSession.id,\n }\n\n // If client attestation is used we have verified this client_id matches with the sub\n // of the wallet attestation\n issuanceSession.clientId = clientAttestation?.clientAttestation.payload.sub ?? authorizationChallengeRequest.client_id\n\n await openId4VcIssuerService.updateState(\n agentContext,\n issuanceSession,\n OpenId4VcIssuanceSessionState.AuthorizationInitiated\n )\n\n const authorizationChallengeErrorResponse = authorizationServer.createAuthorizationChallengePresentationErrorResponse(\n {\n authSession,\n presentation: authorizationRequest,\n errorDescription: 'Presentation required before issuance',\n }\n )\n throw new Oauth2ServerErrorResponseError(authorizationChallengeErrorResponse)\n}\n\nasync function handleAuthorizationChallengeWithAuthSession(options: {\n response: Response\n agentContext: AgentContext\n issuer: OpenId4VcIssuerRecord\n next: NextFunction\n parseResult: ParseAuthorizationChallengeRequestResult\n request: RequestLike\n}) {\n const { agentContext, issuer, parseResult, request, response, next } = options\n const { authorizationChallengeRequest } = parseResult\n\n const openId4VcIssuerService = agentContext.dependencyManager.resolve(OpenId4VcIssuerService)\n const config = agentContext.dependencyManager.resolve(OpenId4VcIssuerModuleConfig)\n const issuerMetadata = await openId4VcIssuerService.getIssuerMetadata(agentContext, issuer)\n\n const verifierApi = agentContext.dependencyManager.resolve(OpenId4VcVerifierApi)\n\n // NOTE: we ignore scope, issuer_state etc.. parameters if auth_session is present\n // should we validate that these are not in the request? I'm not sure what best practice would be here\n\n const issuanceSession = await openId4VcIssuerService.findSingleIssuanceSessionByQuery(agentContext, {\n issuerId: issuer.issuerId,\n presentationAuthSession: authorizationChallengeRequest.auth_session,\n })\n const allowedStates = [OpenId4VcIssuanceSessionState.AuthorizationInitiated]\n if (\n !issuanceSession?.presentation ||\n !issuanceSession.presentation.openId4VcVerificationSessionId ||\n !issuanceSession.presentation.authSession ||\n !allowedStates.includes(issuanceSession.state)\n ) {\n throw new Oauth2ServerErrorResponseError(\n {\n error: Oauth2ErrorCodes.InvalidSession,\n error_description: `Invalid 'auth_session'`,\n },\n {\n internalMessage: !issuanceSession\n ? `Issuance session not found for 'auth_session' parameter '${authorizationChallengeRequest.auth_session}'`\n : !issuanceSession?.presentation\n ? `Issuance session '${issuanceSession.id}' has no 'presentation'. This should not happen and means state is corrupted`\n : `Issuance session '${issuanceSession.id}' has state '${\n issuanceSession.state\n }' but expected one of ${allowedStates.join(', ')}`,\n }\n )\n }\n\n const authorizationServer = openId4VcIssuerService.getOauth2AuthorizationServer(agentContext, {\n issuanceSessionId: issuanceSession.id,\n })\n const { clientAttestation, dpop } = await authorizationServer.verifyAuthorizationChallengeRequest({\n authorizationChallengeRequest,\n authorizationServerMetadata: issuerMetadata.authorizationServers[0],\n request,\n clientAttestation: {\n ...parseResult.clientAttestation,\n // We only look at the issuance session here. If it is required\n // it will be defined on the issuance session now.\n required: issuanceSession.walletAttestation?.required,\n },\n dpop: {\n ...parseResult.dpop,\n // We only look at the issuance session here. If it is required\n // it will be defined on the issuance session now.\n required: issuanceSession.dpop?.required,\n },\n })\n\n if (dpop && dpop.jwkThumbprint !== issuanceSession.dpop?.dpopJkt) {\n throw new Oauth2ServerErrorResponseError(\n {\n error: Oauth2ErrorCodes.InvalidDpopProof,\n error_description: 'Invalid jwk thumbprint',\n },\n {\n internalMessage: `DPoP JWK thumbprint '${dpop.jwkThumbprint}' does not match expected value '${issuanceSession.dpop?.dpopJkt}'`,\n }\n )\n }\n\n if (clientAttestation && clientAttestation.clientAttestation.payload.sub !== issuanceSession.clientId) {\n throw new Oauth2ServerErrorResponseError(\n {\n error: Oauth2ErrorCodes.InvalidClient,\n error_description: 'Invalid client',\n },\n {\n internalMessage: `Client id '${authorizationChallengeRequest.client_id}' from authorization challenge request does not match client id '${issuanceSession.clientId}' on issuance session`,\n }\n )\n }\n\n const { openId4VcVerificationSessionId } = issuanceSession.presentation\n\n await verifierApi\n .getVerificationSessionById(openId4VcVerificationSessionId)\n .catch(async () => {\n // Issuance session is corrupted\n issuanceSession.errorMessage = `Associated openId4VcVerificationSessionRecord with id '${openId4VcVerificationSessionId}' does not exist`\n await openId4VcIssuerService.updateState(agentContext, issuanceSession, OpenId4VcIssuanceSessionState.Error)\n\n throw new Oauth2ServerErrorResponseError(\n {\n error: Oauth2ErrorCodes.InvalidSession,\n error_description: `Invalid 'auth_session'`,\n },\n {\n internalMessage: `Openid4vc verification session with id '${openId4VcVerificationSessionId}' not found during issuance session with id '${issuanceSession.id}'`,\n }\n )\n })\n .then(async (verificationSession) => {\n // Issuance session cannot be used anymore\n if (verificationSession.state === OpenId4VcVerificationSessionState.Error) {\n issuanceSession.errorMessage = `Associated openId4VcVerificationSessionRecord with id '${openId4VcVerificationSessionId}' has error state`\n await openId4VcIssuerService.updateState(agentContext, issuanceSession, OpenId4VcIssuanceSessionState.Error)\n }\n\n if (\n verificationSession.state !== OpenId4VcVerificationSessionState.ResponseVerified ||\n authorizationChallengeRequest.presentation_during_issuance_session !==\n verificationSession.presentationDuringIssuanceSession\n ) {\n throw new Oauth2ServerErrorResponseError(\n {\n error: Oauth2ErrorCodes.InvalidSession,\n error_description: `Invalid presentation for 'auth_session'`,\n },\n {\n internalMessage:\n verificationSession.state !== OpenId4VcVerificationSessionState.ResponseVerified\n ? `Openid4vc verification session with id '${openId4VcVerificationSessionId}' has state '${verificationSession.state}', while '${OpenId4VcVerificationSessionState.ResponseVerified}' was expected.`\n : `Openid4vc verification session with id '${openId4VcVerificationSessionId}' has 'presentation_during_issuance_session' '${verificationSession.presentationDuringIssuanceSession}', but authorization challenge request provided value '${authorizationChallengeRequest.presentation_during_issuance_session}'.`,\n }\n )\n }\n })\n\n // Grant authorization\n const kms = agentContext.resolve(Kms.KeyManagementApi)\n const authorizationCode = TypedArrayEncoder.toBase64URL(kms.randomBytes({ length: 32 }))\n const authorizationCodeExpiresAt = utils.addSecondsToDate(new Date(), config.authorizationCodeExpiresInSeconds)\n\n issuanceSession.authorization = {\n ...issuanceSession.authorization,\n code: authorizationCode,\n codeExpiresAt: authorizationCodeExpiresAt,\n }\n\n // TODO: we need to start using locks so we can't get corrupted state\n await openId4VcIssuerService.updateState(\n agentContext,\n issuanceSession,\n OpenId4VcIssuanceSessionState.AuthorizationGranted\n )\n\n const { authorizationChallengeResponse } = authorizationServer.createAuthorizationChallengeResponse({\n authorizationCode,\n })\n\n return sendJsonResponse(response, next, authorizationChallengeResponse)\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import "../OpenId4VcIssuerModuleConfig.mjs";
|
|
2
|
+
import { getRequestContext, sendOauth2ErrorResponse, sendUnknownServerErrorResponse } from "../../shared/router/context.mjs";
|
|
3
|
+
import "../../shared/router/index.mjs";
|
|
4
|
+
import { OpenId4VcIssuanceSessionState } from "../OpenId4VcIssuanceSessionState.mjs";
|
|
5
|
+
import { OpenId4VcIssuerService } from "../OpenId4VcIssuerService.mjs";
|
|
6
|
+
import { Oauth2ErrorCodes, Oauth2ServerErrorResponseError, parsePushedAuthorizationRequestUriReferenceValue } from "@openid4vc/oauth2";
|
|
7
|
+
|
|
8
|
+
//#region src/openid4vc-issuer/router/authorizationEndpoint.ts
|
|
9
|
+
function configureAuthorizationEndpoint(router, config) {
|
|
10
|
+
router.get(config.authorizationEndpoint, async (request, response, next) => {
|
|
11
|
+
const { agentContext, issuer } = getRequestContext(request);
|
|
12
|
+
const openId4VcIssuerService = agentContext.dependencyManager.resolve(OpenId4VcIssuerService);
|
|
13
|
+
try {
|
|
14
|
+
const requestUri = request.query.request_uri;
|
|
15
|
+
const clientId = request.query.client_id;
|
|
16
|
+
if (!requestUri || typeof requestUri !== "string") throw new Oauth2ServerErrorResponseError({
|
|
17
|
+
error: Oauth2ErrorCodes.InvalidRequest,
|
|
18
|
+
error_description: `Missing required 'request_uri' parameter. Pushed authorization requests are required`
|
|
19
|
+
});
|
|
20
|
+
const requestUriReferenceValue = parsePushedAuthorizationRequestUriReferenceValue({ uri: requestUri });
|
|
21
|
+
const issuanceSession = await openId4VcIssuerService.findSingleIssuanceSessionByQuery(agentContext, {
|
|
22
|
+
issuerId: issuer.issuerId,
|
|
23
|
+
chainedIdentityRequestUriReferenceValue: requestUriReferenceValue
|
|
24
|
+
});
|
|
25
|
+
if (!issuanceSession || issuanceSession.state !== OpenId4VcIssuanceSessionState.AuthorizationInitiated) throw new Oauth2ServerErrorResponseError({
|
|
26
|
+
error: Oauth2ErrorCodes.InvalidRequest,
|
|
27
|
+
error_description: `The 'request_uri' parameter is invalid or has expired.`
|
|
28
|
+
}, { internalMessage: !issuanceSession ? `Issuance session not found for 'request_uri' reference value '${requestUriReferenceValue}'` : `Issuance session '${issuanceSession.id}' has state '${issuanceSession.state}' but expected ${OpenId4VcIssuanceSessionState.AuthorizationInitiated}` });
|
|
29
|
+
if (clientId !== issuanceSession.clientId) throw new Oauth2ServerErrorResponseError({
|
|
30
|
+
error: Oauth2ErrorCodes.InvalidRequest,
|
|
31
|
+
error_description: `The 'client_id' parameter does not match the original value.`
|
|
32
|
+
}, { internalMessage: `The 'client_id' '${clientId}' does not match the expected value for issuance session '${issuanceSession.id}'.` });
|
|
33
|
+
if (!issuanceSession.chainedIdentity?.externalAuthorizationServerUrl || !issuanceSession.chainedIdentity.requestUriExpiresAt || !issuanceSession.chainedIdentity.externalAuthorizationRequestUrl) throw new Oauth2ServerErrorResponseError({
|
|
34
|
+
error: Oauth2ErrorCodes.InvalidRequest,
|
|
35
|
+
error_description: `The 'request_uri' parameter is invalid or has expired.`
|
|
36
|
+
}, { internalMessage: `Issuance session '${issuanceSession.id}' does not have identity chaining configured, so it's not compatible with the authorization endpoint.` });
|
|
37
|
+
if (Date.now() > issuanceSession.chainedIdentity.requestUriExpiresAt.getTime()) throw new Oauth2ServerErrorResponseError({
|
|
38
|
+
error: Oauth2ErrorCodes.InvalidRequest,
|
|
39
|
+
error_description: `The 'request_uri' parameter is invalid or has expired.`
|
|
40
|
+
}, { internalMessage: `The 'request_uri' for issuance session '${issuanceSession.id}' has expired.` });
|
|
41
|
+
return response.redirect(issuanceSession.chainedIdentity.externalAuthorizationRequestUrl);
|
|
42
|
+
} catch (error) {
|
|
43
|
+
if (error instanceof Oauth2ServerErrorResponseError) return sendOauth2ErrorResponse(response, next, agentContext.config.logger, error);
|
|
44
|
+
return sendUnknownServerErrorResponse(response, next, agentContext.config.logger, error);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
//#endregion
|
|
50
|
+
export { configureAuthorizationEndpoint };
|
|
51
|
+
//# sourceMappingURL=authorizationEndpoint.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authorizationEndpoint.mjs","names":[],"sources":["../../../src/openid4vc-issuer/router/authorizationEndpoint.ts"],"sourcesContent":["import {\n Oauth2ErrorCodes,\n Oauth2ServerErrorResponseError,\n parsePushedAuthorizationRequestUriReferenceValue,\n} from '@openid4vc/oauth2'\nimport type { NextFunction, Response, Router } from 'express'\nimport { getRequestContext, sendOauth2ErrorResponse, sendUnknownServerErrorResponse } from '../../shared/router'\nimport { OpenId4VcIssuanceSessionState } from '../OpenId4VcIssuanceSessionState'\nimport { OpenId4VcIssuerModuleConfig } from '../OpenId4VcIssuerModuleConfig'\nimport { OpenId4VcIssuerService } from '../OpenId4VcIssuerService'\nimport type { OpenId4VcIssuanceRequest } from './requestContext'\n\nexport function configureAuthorizationEndpoint(router: Router, config: OpenId4VcIssuerModuleConfig) {\n router.get(\n config.authorizationEndpoint,\n async (request: OpenId4VcIssuanceRequest, response: Response, next: NextFunction) => {\n const requestContext = getRequestContext(request)\n const { agentContext, issuer } = requestContext\n const openId4VcIssuerService = agentContext.dependencyManager.resolve(OpenId4VcIssuerService)\n\n try {\n const requestUri = request.query.request_uri\n const clientId = request.query.client_id\n\n if (!requestUri || typeof requestUri !== 'string') {\n throw new Oauth2ServerErrorResponseError({\n error: Oauth2ErrorCodes.InvalidRequest,\n error_description: `Missing required 'request_uri' parameter. Pushed authorization requests are required`,\n })\n }\n\n const requestUriReferenceValue = parsePushedAuthorizationRequestUriReferenceValue({ uri: requestUri })\n const issuanceSession = await openId4VcIssuerService.findSingleIssuanceSessionByQuery(agentContext, {\n issuerId: issuer.issuerId,\n chainedIdentityRequestUriReferenceValue: requestUriReferenceValue,\n })\n\n if (!issuanceSession || issuanceSession.state !== OpenId4VcIssuanceSessionState.AuthorizationInitiated) {\n throw new Oauth2ServerErrorResponseError(\n {\n error: Oauth2ErrorCodes.InvalidRequest,\n error_description: `The 'request_uri' parameter is invalid or has expired.`,\n },\n {\n internalMessage: !issuanceSession\n ? `Issuance session not found for 'request_uri' reference value '${requestUriReferenceValue}'`\n : `Issuance session '${issuanceSession.id}' has state '${\n issuanceSession.state\n }' but expected ${OpenId4VcIssuanceSessionState.AuthorizationInitiated}`,\n }\n )\n }\n\n if (clientId !== issuanceSession.clientId) {\n throw new Oauth2ServerErrorResponseError(\n {\n error: Oauth2ErrorCodes.InvalidRequest,\n error_description: `The 'client_id' parameter does not match the original value.`,\n },\n {\n internalMessage: `The 'client_id' '${clientId}' does not match the expected value for issuance session '${issuanceSession.id}'.`,\n }\n )\n }\n\n if (\n !issuanceSession.chainedIdentity?.externalAuthorizationServerUrl ||\n !issuanceSession.chainedIdentity.requestUriExpiresAt ||\n !issuanceSession.chainedIdentity.externalAuthorizationRequestUrl\n ) {\n throw new Oauth2ServerErrorResponseError(\n {\n error: Oauth2ErrorCodes.InvalidRequest,\n error_description: `The 'request_uri' parameter is invalid or has expired.`,\n },\n {\n internalMessage: `Issuance session '${issuanceSession.id}' does not have identity chaining configured, so it's not compatible with the authorization endpoint.`,\n }\n )\n }\n\n if (Date.now() > issuanceSession.chainedIdentity.requestUriExpiresAt.getTime()) {\n throw new Oauth2ServerErrorResponseError(\n {\n error: Oauth2ErrorCodes.InvalidRequest,\n error_description: `The 'request_uri' parameter is invalid or has expired.`,\n },\n {\n internalMessage: `The 'request_uri' for issuance session '${issuanceSession.id}' has expired.`,\n }\n )\n }\n\n return response.redirect(issuanceSession.chainedIdentity.externalAuthorizationRequestUrl)\n } catch (error) {\n if (error instanceof Oauth2ServerErrorResponseError) {\n return sendOauth2ErrorResponse(response, next, agentContext.config.logger, error)\n }\n return sendUnknownServerErrorResponse(response, next, agentContext.config.logger, error)\n }\n }\n )\n}\n"],"mappings":";;;;;;;;AAYA,SAAgB,+BAA+B,QAAgB,QAAqC;AAClG,QAAO,IACL,OAAO,uBACP,OAAO,SAAmC,UAAoB,SAAuB;EAEnF,MAAM,EAAE,cAAc,WADC,kBAAkB,QAAQ;EAEjD,MAAM,yBAAyB,aAAa,kBAAkB,QAAQ,uBAAuB;AAE7F,MAAI;GACF,MAAM,aAAa,QAAQ,MAAM;GACjC,MAAM,WAAW,QAAQ,MAAM;AAE/B,OAAI,CAAC,cAAc,OAAO,eAAe,SACvC,OAAM,IAAI,+BAA+B;IACvC,OAAO,iBAAiB;IACxB,mBAAmB;IACpB,CAAC;GAGJ,MAAM,2BAA2B,iDAAiD,EAAE,KAAK,YAAY,CAAC;GACtG,MAAM,kBAAkB,MAAM,uBAAuB,iCAAiC,cAAc;IAClG,UAAU,OAAO;IACjB,yCAAyC;IAC1C,CAAC;AAEF,OAAI,CAAC,mBAAmB,gBAAgB,UAAU,8BAA8B,uBAC9E,OAAM,IAAI,+BACR;IACE,OAAO,iBAAiB;IACxB,mBAAmB;IACpB,EACD,EACE,iBAAiB,CAAC,kBACd,iEAAiE,yBAAyB,KAC1F,qBAAqB,gBAAgB,GAAG,eACtC,gBAAgB,MACjB,iBAAiB,8BAA8B,0BACrD,CACF;AAGH,OAAI,aAAa,gBAAgB,SAC/B,OAAM,IAAI,+BACR;IACE,OAAO,iBAAiB;IACxB,mBAAmB;IACpB,EACD,EACE,iBAAiB,oBAAoB,SAAS,4DAA4D,gBAAgB,GAAG,KAC9H,CACF;AAGH,OACE,CAAC,gBAAgB,iBAAiB,kCAClC,CAAC,gBAAgB,gBAAgB,uBACjC,CAAC,gBAAgB,gBAAgB,gCAEjC,OAAM,IAAI,+BACR;IACE,OAAO,iBAAiB;IACxB,mBAAmB;IACpB,EACD,EACE,iBAAiB,qBAAqB,gBAAgB,GAAG,wGAC1D,CACF;AAGH,OAAI,KAAK,KAAK,GAAG,gBAAgB,gBAAgB,oBAAoB,SAAS,CAC5E,OAAM,IAAI,+BACR;IACE,OAAO,iBAAiB;IACxB,mBAAmB;IACpB,EACD,EACE,iBAAiB,2CAA2C,gBAAgB,GAAG,iBAChF,CACF;AAGH,UAAO,SAAS,SAAS,gBAAgB,gBAAgB,gCAAgC;WAClF,OAAO;AACd,OAAI,iBAAiB,+BACnB,QAAO,wBAAwB,UAAU,MAAM,aAAa,OAAO,QAAQ,MAAM;AAEnF,UAAO,+BAA+B,UAAU,MAAM,aAAa,OAAO,QAAQ,MAAM;;GAG7F"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { getRequestContext, sendJsonResponse, sendUnknownServerErrorResponse } from "../../shared/router/context.mjs";
|
|
2
|
+
import "../../shared/router/index.mjs";
|
|
3
|
+
import { OpenId4VcIssuerService } from "../OpenId4VcIssuerService.mjs";
|
|
4
|
+
import { getAuthorizationServerMetadataFromList } from "@openid4vc/oauth2";
|
|
5
|
+
|
|
6
|
+
//#region src/openid4vc-issuer/router/authorizationServerMetadataEndpoint.ts
|
|
7
|
+
/**
|
|
8
|
+
* This is the credo authorization server metadata. It is only used for pre-authorized
|
|
9
|
+
* code flow.
|
|
10
|
+
*/
|
|
11
|
+
function configureOAuthAuthorizationServerMetadataEndpoint(router, path) {
|
|
12
|
+
router.get(path, async (_request, response, next) => {
|
|
13
|
+
const { agentContext, issuer } = getRequestContext(_request);
|
|
14
|
+
try {
|
|
15
|
+
const issuerMetadata = await agentContext.dependencyManager.resolve(OpenId4VcIssuerService).getIssuerMetadata(agentContext, issuer);
|
|
16
|
+
return sendJsonResponse(response, next, getAuthorizationServerMetadataFromList(issuerMetadata.authorizationServers, issuerMetadata.credentialIssuer.credential_issuer));
|
|
17
|
+
} catch (e) {
|
|
18
|
+
return sendUnknownServerErrorResponse(response, next, agentContext.config.logger, e);
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
//#endregion
|
|
24
|
+
export { configureOAuthAuthorizationServerMetadataEndpoint };
|
|
25
|
+
//# sourceMappingURL=authorizationServerMetadataEndpoint.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authorizationServerMetadataEndpoint.mjs","names":[],"sources":["../../../src/openid4vc-issuer/router/authorizationServerMetadataEndpoint.ts"],"sourcesContent":["import { getAuthorizationServerMetadataFromList } from '@openid4vc/oauth2'\nimport type { Response, Router } from 'express'\nimport { getRequestContext, sendJsonResponse, sendUnknownServerErrorResponse } from '../../shared/router'\nimport { OpenId4VcIssuerService } from '../OpenId4VcIssuerService'\nimport type { OpenId4VcIssuanceRequest } from './requestContext'\n\n/**\n * This is the credo authorization server metadata. It is only used for pre-authorized\n * code flow.\n */\nexport function configureOAuthAuthorizationServerMetadataEndpoint(router: Router, path: string) {\n router.get(path, async (_request: OpenId4VcIssuanceRequest, response: Response, next) => {\n const { agentContext, issuer } = getRequestContext(_request)\n try {\n const openId4VcIssuerService = agentContext.dependencyManager.resolve(OpenId4VcIssuerService)\n const issuerMetadata = await openId4VcIssuerService.getIssuerMetadata(agentContext, issuer)\n const issuerAuthorizationServer = getAuthorizationServerMetadataFromList(\n issuerMetadata.authorizationServers,\n issuerMetadata.credentialIssuer.credential_issuer\n )\n\n return sendJsonResponse(response, next, issuerAuthorizationServer)\n } catch (e) {\n return sendUnknownServerErrorResponse(response, next, agentContext.config.logger, e)\n }\n })\n}\n"],"mappings":";;;;;;;;;;AAUA,SAAgB,kDAAkD,QAAgB,MAAc;AAC9F,QAAO,IAAI,MAAM,OAAO,UAAoC,UAAoB,SAAS;EACvF,MAAM,EAAE,cAAc,WAAW,kBAAkB,SAAS;AAC5D,MAAI;GAEF,MAAM,iBAAiB,MADQ,aAAa,kBAAkB,QAAQ,uBAAuB,CACzC,kBAAkB,cAAc,OAAO;AAM3F,UAAO,iBAAiB,UAAU,MALA,uCAChC,eAAe,sBACf,eAAe,iBAAiB,kBACjC,CAEiE;WAC3D,GAAG;AACV,UAAO,+BAA+B,UAAU,MAAM,aAAa,OAAO,QAAQ,EAAE;;GAEtF"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { getRequestContext, sendJsonResponse, sendOauth2ErrorResponse, sendUnauthorizedError, sendUnknownServerErrorResponse } from "../../shared/router/context.mjs";
|
|
2
|
+
import "../../shared/router/index.mjs";
|
|
3
|
+
import { getCredentialConfigurationsSupportedForScopes } from "../../shared/issuerMetadataUtils.mjs";
|
|
4
|
+
import "../../shared/index.mjs";
|
|
5
|
+
import { OpenId4VcIssuanceSessionState } from "../OpenId4VcIssuanceSessionState.mjs";
|
|
6
|
+
import { OpenId4VcIssuanceSessionRecord } from "../repository/OpenId4VcIssuanceSessionRecord.mjs";
|
|
7
|
+
import { OpenId4VcIssuanceSessionRepository } from "../repository/OpenId4VcIssuanceSessionRepository.mjs";
|
|
8
|
+
import "../repository/index.mjs";
|
|
9
|
+
import { OpenId4VcIssuerService } from "../OpenId4VcIssuerService.mjs";
|
|
10
|
+
import { joinUriParts, utils } from "@credo-ts/core";
|
|
11
|
+
import { Oauth2ErrorCodes, Oauth2ResourceUnauthorizedError, Oauth2ServerErrorResponseError } from "@openid4vc/oauth2";
|
|
12
|
+
import { Openid4vciDraftVersion, getCredentialConfigurationsMatchingRequestFormat } from "@openid4vc/openid4vci";
|
|
13
|
+
|
|
14
|
+
//#region src/openid4vc-issuer/router/credentialEndpoint.ts
|
|
15
|
+
function configureCredentialEndpoint(router, config) {
|
|
16
|
+
router.post(config.credentialEndpointPath, async (request, response, next) => {
|
|
17
|
+
const { agentContext, issuer } = getRequestContext(request);
|
|
18
|
+
const openId4VcIssuerService = agentContext.dependencyManager.resolve(OpenId4VcIssuerService);
|
|
19
|
+
const issuerMetadata = await openId4VcIssuerService.getIssuerMetadata(agentContext, issuer, true);
|
|
20
|
+
const vcIssuer = openId4VcIssuerService.getIssuer(agentContext);
|
|
21
|
+
const resourceServer = openId4VcIssuerService.getResourceServer(agentContext, issuer);
|
|
22
|
+
const fullRequestUrl = joinUriParts(issuerMetadata.credentialIssuer.credential_issuer, [config.credentialEndpointPath]);
|
|
23
|
+
const resourceRequestResult = await resourceServer.verifyResourceRequest({
|
|
24
|
+
authorizationServers: issuerMetadata.authorizationServers,
|
|
25
|
+
resourceServer: issuerMetadata.credentialIssuer.credential_issuer,
|
|
26
|
+
request: {
|
|
27
|
+
headers: new Headers(request.headers),
|
|
28
|
+
method: request.method,
|
|
29
|
+
url: fullRequestUrl
|
|
30
|
+
}
|
|
31
|
+
}).catch((error) => {
|
|
32
|
+
sendUnauthorizedError(response, next, agentContext.config.logger, error);
|
|
33
|
+
});
|
|
34
|
+
if (!resourceRequestResult) return;
|
|
35
|
+
const { tokenPayload, accessToken, scheme, authorizationServer } = resourceRequestResult;
|
|
36
|
+
const credentialRequest = request.body;
|
|
37
|
+
const issuanceSessionRepository = agentContext.dependencyManager.resolve(OpenId4VcIssuanceSessionRepository);
|
|
38
|
+
const parsedCredentialRequest = vcIssuer.parseCredentialRequest({
|
|
39
|
+
credentialRequest,
|
|
40
|
+
issuerMetadata
|
|
41
|
+
});
|
|
42
|
+
let issuanceSession = null;
|
|
43
|
+
const preAuthorizedCode = typeof tokenPayload["pre-authorized_code"] === "string" ? tokenPayload["pre-authorized_code"] : void 0;
|
|
44
|
+
const issuerState = typeof tokenPayload.issuer_state === "string" ? tokenPayload.issuer_state : void 0;
|
|
45
|
+
if (!tokenPayload.sub) return sendOauth2ErrorResponse(response, next, agentContext.config.logger, new Oauth2ServerErrorResponseError({ error: Oauth2ErrorCodes.ServerError }, { internalMessage: `Received token without 'sub' claim. Subject is required for binding issuance session` }));
|
|
46
|
+
if (!parsedCredentialRequest.format && !parsedCredentialRequest.credentialConfiguration) return sendOauth2ErrorResponse(response, next, agentContext.config.logger, new Oauth2ServerErrorResponseError({
|
|
47
|
+
error: parsedCredentialRequest.credentialIdentifier ? Oauth2ErrorCodes.InvalidCredentialRequest : Oauth2ErrorCodes.UnsupportedCredentialFormat,
|
|
48
|
+
error_description: parsedCredentialRequest.credentialIdentifier ? `Credential request containing 'credential_identifier' not supported` : parsedCredentialRequest.credentialConfigurationId ? `Credential configuration '${parsedCredentialRequest.credentialConfigurationId}' not supported` : `Credential format '${parsedCredentialRequest.credentialRequest.format}' not supported`
|
|
49
|
+
}));
|
|
50
|
+
if (preAuthorizedCode || issuerState) {
|
|
51
|
+
issuanceSession = await issuanceSessionRepository.findSingleByQuery(agentContext, {
|
|
52
|
+
issuerId: issuer.issuerId,
|
|
53
|
+
preAuthorizedCode,
|
|
54
|
+
issuerState
|
|
55
|
+
});
|
|
56
|
+
if (!issuanceSession) {
|
|
57
|
+
agentContext.config.logger.warn(`No issuance session found for incoming credential request for issuer ${issuer.issuerId} but access token data has ${issuerState ? "issuer_state" : "pre-authorized_code"}. Returning error response`, { tokenPayload });
|
|
58
|
+
return sendOauth2ErrorResponse(response, next, agentContext.config.logger, new Oauth2ServerErrorResponseError({ error: Oauth2ErrorCodes.CredentialRequestDenied }, { internalMessage: `No issuance session found for incoming credential request for issuer ${issuer.issuerId} and access token data` }));
|
|
59
|
+
}
|
|
60
|
+
if (issuanceSession.dpop?.required && !resourceRequestResult.dpop) return sendUnauthorizedError(response, next, agentContext.config.logger, new Oauth2ResourceUnauthorizedError("Missing required DPoP proof", {
|
|
61
|
+
scheme,
|
|
62
|
+
error: Oauth2ErrorCodes.InvalidDpopProof
|
|
63
|
+
}));
|
|
64
|
+
const expiresAt = issuanceSession.expiresAt ?? utils.addSecondsToDate(issuanceSession.createdAt, config.statefulCredentialOfferExpirationInSeconds);
|
|
65
|
+
if (issuanceSession.authorization?.subject) {
|
|
66
|
+
if (issuanceSession.authorization.subject !== tokenPayload.sub) return sendOauth2ErrorResponse(response, next, agentContext.config.logger, new Oauth2ServerErrorResponseError({ error: Oauth2ErrorCodes.CredentialRequestDenied }, { internalMessage: `Issuance session authorization subject does not match with the token payload subject for issuance session '${issuanceSession.id}'. Returning error response` }));
|
|
67
|
+
} else if (Date.now() > expiresAt.getTime()) {
|
|
68
|
+
issuanceSession.errorMessage = "Credential offer has expired";
|
|
69
|
+
await openId4VcIssuerService.updateState(agentContext, issuanceSession, OpenId4VcIssuanceSessionState.Error);
|
|
70
|
+
return sendOauth2ErrorResponse(response, next, agentContext.config.logger, new Oauth2ServerErrorResponseError({
|
|
71
|
+
error: Oauth2ErrorCodes.CredentialRequestDenied,
|
|
72
|
+
error_description: "Session expired"
|
|
73
|
+
}));
|
|
74
|
+
} else {
|
|
75
|
+
issuanceSession.authorization = {
|
|
76
|
+
...issuanceSession.authorization,
|
|
77
|
+
subject: tokenPayload.sub
|
|
78
|
+
};
|
|
79
|
+
await issuanceSessionRepository.update(agentContext, issuanceSession);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
if (!issuanceSession && config.allowDynamicIssuanceSessions) {
|
|
83
|
+
agentContext.config.logger.warn(`No issuance session found for incoming credential request for issuer ${issuer.issuerId} and access token data has no issuer_state or pre-authorized_code. Creating on-demand issuance session`, { tokenPayload });
|
|
84
|
+
if (config.dpopRequired && !resourceRequestResult.dpop) return sendUnauthorizedError(response, next, agentContext.config.logger, new Oauth2ResourceUnauthorizedError("Missing required DPoP proof", {
|
|
85
|
+
scheme,
|
|
86
|
+
error: Oauth2ErrorCodes.InvalidDpopProof
|
|
87
|
+
}));
|
|
88
|
+
const configurationsForScope = getCredentialConfigurationsSupportedForScopes(issuerMetadata.credentialIssuer.credential_configurations_supported, tokenPayload.scope?.split(" ") ?? []);
|
|
89
|
+
let configurationsForToken = {};
|
|
90
|
+
if (parsedCredentialRequest.credentialConfigurationId && parsedCredentialRequest.credentialConfiguration) {
|
|
91
|
+
if (configurationsForScope[parsedCredentialRequest.credentialConfigurationId]) configurationsForToken = { [parsedCredentialRequest.credentialConfigurationId]: parsedCredentialRequest.credentialConfiguration };
|
|
92
|
+
} else if (parsedCredentialRequest.format) configurationsForToken = getCredentialConfigurationsMatchingRequestFormat({
|
|
93
|
+
issuerMetadata,
|
|
94
|
+
requestFormat: parsedCredentialRequest.format
|
|
95
|
+
});
|
|
96
|
+
if (Object.keys(configurationsForToken).length === 0) return sendUnauthorizedError(response, next, agentContext.config.logger, new Oauth2ResourceUnauthorizedError("No credential configurations match credential request and access token scope", {
|
|
97
|
+
scheme,
|
|
98
|
+
error: Oauth2ErrorCodes.InsufficientScope
|
|
99
|
+
}), 403);
|
|
100
|
+
const createdAt = /* @__PURE__ */ new Date();
|
|
101
|
+
issuanceSession = new OpenId4VcIssuanceSessionRecord({
|
|
102
|
+
createdAt,
|
|
103
|
+
expiresAt: utils.addSecondsToDate(createdAt, config.statefulCredentialOfferExpirationInSeconds),
|
|
104
|
+
credentialOfferPayload: {
|
|
105
|
+
credential_configuration_ids: Object.keys(configurationsForToken),
|
|
106
|
+
credential_issuer: issuerMetadata.credentialIssuer.credential_issuer
|
|
107
|
+
},
|
|
108
|
+
credentialOfferId: utils.uuid(),
|
|
109
|
+
issuerId: issuer.issuerId,
|
|
110
|
+
state: OpenId4VcIssuanceSessionState.CredentialRequestReceived,
|
|
111
|
+
clientId: tokenPayload.client_id,
|
|
112
|
+
dpop: config.dpopRequired ? { required: true } : void 0,
|
|
113
|
+
authorization: { subject: tokenPayload.sub },
|
|
114
|
+
openId4VciVersion: issuerMetadata.originalDraftVersion === Openid4vciDraftVersion.V1 ? "v1" : issuerMetadata.originalDraftVersion === Openid4vciDraftVersion.Draft15 ? "v1.draft15" : "v1.draft11-14"
|
|
115
|
+
});
|
|
116
|
+
await issuanceSessionRepository.save(agentContext, issuanceSession);
|
|
117
|
+
openId4VcIssuerService.emitStateChangedEvent(agentContext, issuanceSession, null);
|
|
118
|
+
} else if (!issuanceSession) return sendOauth2ErrorResponse(response, next, agentContext.config.logger, new Oauth2ServerErrorResponseError({ error: Oauth2ErrorCodes.CredentialRequestDenied }, { internalMessage: `Access token without 'issuer_state' or 'pre-authorized_code' issued by external authorization server provided, but 'allowDynamicIssuanceSessions' is disabled. Either bind the access token to a stateful credential offer, or enable 'allowDynamicIssuanceSessions'.` }));
|
|
119
|
+
try {
|
|
120
|
+
const { credentialResponse } = await openId4VcIssuerService.createCredentialResponse(agentContext, {
|
|
121
|
+
issuanceSession,
|
|
122
|
+
credentialRequest,
|
|
123
|
+
authorization: {
|
|
124
|
+
authorizationServer,
|
|
125
|
+
accessToken: {
|
|
126
|
+
payload: tokenPayload,
|
|
127
|
+
value: accessToken
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
return sendJsonResponse(response, next, credentialResponse, void 0, credentialResponse.transaction_id ? 202 : 200);
|
|
132
|
+
} catch (error) {
|
|
133
|
+
if (error instanceof Oauth2ServerErrorResponseError) return sendOauth2ErrorResponse(response, next, agentContext.config.logger, error);
|
|
134
|
+
if (error instanceof Oauth2ResourceUnauthorizedError) return sendUnauthorizedError(response, next, agentContext.config.logger, error);
|
|
135
|
+
return sendUnknownServerErrorResponse(response, next, agentContext.config.logger, error);
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
//#endregion
|
|
141
|
+
export { configureCredentialEndpoint };
|
|
142
|
+
//# sourceMappingURL=credentialEndpoint.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credentialEndpoint.mjs","names":["issuanceSession: OpenId4VcIssuanceSessionRecord | null","configurationsForToken: CredentialConfigurationsSupportedWithFormats"],"sources":["../../../src/openid4vc-issuer/router/credentialEndpoint.ts"],"sourcesContent":["import { joinUriParts, utils } from '@credo-ts/core'\nimport type { HttpMethod } from '@openid4vc/oauth2'\nimport { Oauth2ErrorCodes, Oauth2ResourceUnauthorizedError, Oauth2ServerErrorResponseError } from '@openid4vc/oauth2'\nimport {\n type CredentialConfigurationsSupportedWithFormats,\n getCredentialConfigurationsMatchingRequestFormat,\n Openid4vciDraftVersion,\n} from '@openid4vc/openid4vci'\nimport type { Response, Router } from 'express'\nimport { getCredentialConfigurationsSupportedForScopes } from '../../shared'\nimport {\n getRequestContext,\n sendJsonResponse,\n sendOauth2ErrorResponse,\n sendUnauthorizedError,\n sendUnknownServerErrorResponse,\n} from '../../shared/router'\nimport { OpenId4VcIssuanceSessionState } from '../OpenId4VcIssuanceSessionState'\nimport type { OpenId4VcIssuerModuleConfig } from '../OpenId4VcIssuerModuleConfig'\nimport { OpenId4VcIssuerService } from '../OpenId4VcIssuerService'\nimport { OpenId4VcIssuanceSessionRecord, OpenId4VcIssuanceSessionRepository } from '../repository'\nimport type { OpenId4VcIssuanceRequest } from './requestContext'\n\nexport function configureCredentialEndpoint(router: Router, config: OpenId4VcIssuerModuleConfig) {\n router.post(config.credentialEndpointPath, async (request: OpenId4VcIssuanceRequest, response: Response, next) => {\n const { agentContext, issuer } = getRequestContext(request)\n const openId4VcIssuerService = agentContext.dependencyManager.resolve(OpenId4VcIssuerService)\n const issuerMetadata = await openId4VcIssuerService.getIssuerMetadata(agentContext, issuer, true)\n const vcIssuer = openId4VcIssuerService.getIssuer(agentContext)\n const resourceServer = openId4VcIssuerService.getResourceServer(agentContext, issuer)\n\n const fullRequestUrl = joinUriParts(issuerMetadata.credentialIssuer.credential_issuer, [\n config.credentialEndpointPath,\n ])\n const resourceRequestResult = await resourceServer\n .verifyResourceRequest({\n authorizationServers: issuerMetadata.authorizationServers,\n resourceServer: issuerMetadata.credentialIssuer.credential_issuer,\n request: {\n headers: new Headers(request.headers as Record<string, string>),\n method: request.method as HttpMethod,\n url: fullRequestUrl,\n },\n })\n .catch((error) => {\n sendUnauthorizedError(response, next, agentContext.config.logger, error)\n })\n if (!resourceRequestResult) return\n const { tokenPayload, accessToken, scheme, authorizationServer } = resourceRequestResult\n\n const credentialRequest = request.body\n const issuanceSessionRepository = agentContext.dependencyManager.resolve(OpenId4VcIssuanceSessionRepository)\n\n const parsedCredentialRequest = vcIssuer.parseCredentialRequest({\n credentialRequest,\n issuerMetadata,\n })\n\n let issuanceSession: OpenId4VcIssuanceSessionRecord | null = null\n const preAuthorizedCode =\n typeof tokenPayload['pre-authorized_code'] === 'string' ? tokenPayload['pre-authorized_code'] : undefined\n const issuerState = typeof tokenPayload.issuer_state === 'string' ? tokenPayload.issuer_state : undefined\n\n const subject = tokenPayload.sub\n if (!subject) {\n return sendOauth2ErrorResponse(\n response,\n next,\n agentContext.config.logger,\n new Oauth2ServerErrorResponseError(\n {\n error: Oauth2ErrorCodes.ServerError,\n },\n {\n internalMessage: `Received token without 'sub' claim. Subject is required for binding issuance session`,\n }\n )\n )\n }\n\n // Already handle request without format/credential_configuration_id. Simplifies next code sections\n if (!parsedCredentialRequest.format && !parsedCredentialRequest.credentialConfiguration) {\n return sendOauth2ErrorResponse(\n response,\n next,\n agentContext.config.logger,\n new Oauth2ServerErrorResponseError({\n error: parsedCredentialRequest.credentialIdentifier\n ? Oauth2ErrorCodes.InvalidCredentialRequest\n : Oauth2ErrorCodes.UnsupportedCredentialFormat,\n error_description: parsedCredentialRequest.credentialIdentifier\n ? `Credential request containing 'credential_identifier' not supported`\n : parsedCredentialRequest.credentialConfigurationId\n ? `Credential configuration '${parsedCredentialRequest.credentialConfigurationId}' not supported`\n : `Credential format '${parsedCredentialRequest.credentialRequest.format}' not supported`,\n })\n )\n }\n\n if (preAuthorizedCode || issuerState) {\n issuanceSession = await issuanceSessionRepository.findSingleByQuery(agentContext, {\n issuerId: issuer.issuerId,\n preAuthorizedCode,\n issuerState,\n })\n\n if (!issuanceSession) {\n agentContext.config.logger.warn(\n `No issuance session found for incoming credential request for issuer ${\n issuer.issuerId\n } but access token data has ${\n issuerState ? 'issuer_state' : 'pre-authorized_code'\n }. Returning error response`,\n {\n tokenPayload,\n }\n )\n\n return sendOauth2ErrorResponse(\n response,\n next,\n agentContext.config.logger,\n new Oauth2ServerErrorResponseError(\n {\n error: Oauth2ErrorCodes.CredentialRequestDenied,\n },\n {\n internalMessage: `No issuance session found for incoming credential request for issuer ${issuer.issuerId} and access token data`,\n }\n )\n )\n }\n\n // Use issuance session dpop config\n if (issuanceSession.dpop?.required && !resourceRequestResult.dpop) {\n return sendUnauthorizedError(\n response,\n next,\n agentContext.config.logger,\n new Oauth2ResourceUnauthorizedError('Missing required DPoP proof', {\n scheme,\n error: Oauth2ErrorCodes.InvalidDpopProof,\n })\n )\n }\n\n const expiresAt =\n issuanceSession.expiresAt ??\n utils.addSecondsToDate(issuanceSession.createdAt, config.statefulCredentialOfferExpirationInSeconds)\n\n // Verify the issuance session subject\n if (issuanceSession.authorization?.subject) {\n if (issuanceSession.authorization.subject !== tokenPayload.sub) {\n return sendOauth2ErrorResponse(\n response,\n next,\n agentContext.config.logger,\n new Oauth2ServerErrorResponseError(\n {\n error: Oauth2ErrorCodes.CredentialRequestDenied,\n },\n {\n internalMessage: `Issuance session authorization subject does not match with the token payload subject for issuance session '${issuanceSession.id}'. Returning error response`,\n }\n )\n )\n }\n }\n\n // Stateful session expired\n else if (Date.now() > expiresAt.getTime()) {\n issuanceSession.errorMessage = 'Credential offer has expired'\n await openId4VcIssuerService.updateState(agentContext, issuanceSession, OpenId4VcIssuanceSessionState.Error)\n return sendOauth2ErrorResponse(\n response,\n next,\n agentContext.config.logger,\n new Oauth2ServerErrorResponseError({\n // What is the best error here?\n error: Oauth2ErrorCodes.CredentialRequestDenied,\n error_description: 'Session expired',\n })\n )\n } else {\n issuanceSession.authorization = {\n ...issuanceSession.authorization,\n subject: tokenPayload.sub,\n }\n await issuanceSessionRepository.update(agentContext, issuanceSession)\n }\n }\n\n if (!issuanceSession && config.allowDynamicIssuanceSessions) {\n agentContext.config.logger.warn(\n `No issuance session found for incoming credential request for issuer ${issuer.issuerId} and access token data has no issuer_state or pre-authorized_code. Creating on-demand issuance session`,\n {\n tokenPayload,\n }\n )\n\n // Use global config when creating a dynamic session\n if (config.dpopRequired && !resourceRequestResult.dpop) {\n return sendUnauthorizedError(\n response,\n next,\n agentContext.config.logger,\n new Oauth2ResourceUnauthorizedError('Missing required DPoP proof', {\n scheme,\n error: Oauth2ErrorCodes.InvalidDpopProof,\n })\n )\n }\n\n const configurationsForScope = getCredentialConfigurationsSupportedForScopes(\n issuerMetadata.credentialIssuer.credential_configurations_supported,\n tokenPayload.scope?.split(' ') ?? []\n )\n\n // All credential configurations that match the request scope and credential request\n // This is just so we don't create an issuance session that will fail immediately after\n let configurationsForToken: CredentialConfigurationsSupportedWithFormats = {}\n\n if (parsedCredentialRequest.credentialConfigurationId && parsedCredentialRequest.credentialConfiguration) {\n if (configurationsForScope[parsedCredentialRequest.credentialConfigurationId]) {\n configurationsForToken = {\n [parsedCredentialRequest.credentialConfigurationId]: parsedCredentialRequest.credentialConfiguration,\n }\n }\n } else if (parsedCredentialRequest.format) {\n configurationsForToken = getCredentialConfigurationsMatchingRequestFormat({\n issuerMetadata,\n requestFormat: parsedCredentialRequest.format,\n })\n }\n\n if (Object.keys(configurationsForToken).length === 0) {\n return sendUnauthorizedError(\n response,\n next,\n agentContext.config.logger,\n new Oauth2ResourceUnauthorizedError(\n 'No credential configurations match credential request and access token scope',\n {\n scheme,\n error: Oauth2ErrorCodes.InsufficientScope,\n }\n ),\n // Forbidden for InsufficientScope\n 403\n )\n }\n\n const createdAt = new Date()\n const expiresAt = utils.addSecondsToDate(createdAt, config.statefulCredentialOfferExpirationInSeconds)\n\n issuanceSession = new OpenId4VcIssuanceSessionRecord({\n createdAt,\n expiresAt,\n credentialOfferPayload: {\n credential_configuration_ids: Object.keys(configurationsForToken),\n credential_issuer: issuerMetadata.credentialIssuer.credential_issuer,\n },\n credentialOfferId: utils.uuid(),\n issuerId: issuer.issuerId,\n state: OpenId4VcIssuanceSessionState.CredentialRequestReceived,\n clientId: tokenPayload.client_id,\n dpop: config.dpopRequired\n ? {\n required: true,\n }\n : undefined,\n authorization: {\n subject: tokenPayload.sub,\n },\n openId4VciVersion:\n issuerMetadata.originalDraftVersion === Openid4vciDraftVersion.V1\n ? 'v1'\n : issuerMetadata.originalDraftVersion === Openid4vciDraftVersion.Draft15\n ? 'v1.draft15'\n : 'v1.draft11-14',\n })\n\n // Save and update\n await issuanceSessionRepository.save(agentContext, issuanceSession)\n openId4VcIssuerService.emitStateChangedEvent(agentContext, issuanceSession, null)\n } else if (!issuanceSession) {\n return sendOauth2ErrorResponse(\n response,\n next,\n agentContext.config.logger,\n new Oauth2ServerErrorResponseError(\n {\n error: Oauth2ErrorCodes.CredentialRequestDenied,\n },\n {\n internalMessage: `Access token without 'issuer_state' or 'pre-authorized_code' issued by external authorization server provided, but 'allowDynamicIssuanceSessions' is disabled. Either bind the access token to a stateful credential offer, or enable 'allowDynamicIssuanceSessions'.`,\n }\n )\n )\n }\n\n try {\n const { credentialResponse } = await openId4VcIssuerService.createCredentialResponse(agentContext, {\n issuanceSession,\n credentialRequest,\n authorization: {\n authorizationServer,\n accessToken: {\n payload: tokenPayload,\n value: accessToken,\n },\n },\n })\n\n return sendJsonResponse(\n response,\n next,\n credentialResponse,\n undefined,\n credentialResponse.transaction_id ? 202 : 200\n )\n } catch (error) {\n if (error instanceof Oauth2ServerErrorResponseError) {\n return sendOauth2ErrorResponse(response, next, agentContext.config.logger, error)\n }\n if (error instanceof Oauth2ResourceUnauthorizedError) {\n return sendUnauthorizedError(response, next, agentContext.config.logger, error)\n }\n\n return sendUnknownServerErrorResponse(response, next, agentContext.config.logger, error)\n }\n })\n}\n"],"mappings":"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"}
|