@@ -34,6 +34,7 @@ import {
3434 OID4VCICredentialFormat ,
3535 OpenId4VCIVersion ,
3636 PRE_AUTH_GRANT_LITERAL ,
37+ ProofOfPossession ,
3738 QRCodeOpts ,
3839 StatusListOpts ,
3940 TokenErrorResponse ,
@@ -675,16 +676,58 @@ export class VcIssuer {
675676 try {
676677 if ( format && ! supportedIssuanceFormats . includes ( format ) ) {
677678 throw Error ( `Format ${ format } not supported yet` )
678- } else if ( typeof this . _jwtVerifyCallback !== 'function' && typeof jwtVerifyCallback !== 'function' ) {
679- throw new Error ( JWT_VERIFY_CONFIG_ERROR )
680- } else if ( ! credentialRequest . proof ) {
681- throw Error ( 'Proof of possession is required. No proof value present in credential request' )
682679 }
683680
684- const jwtVerifyResult = jwtVerifyCallback
685- ? await jwtVerifyCallback ( credentialRequest . proof )
686- : // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
687- await this . _jwtVerifyCallback ! ( credentialRequest . proof )
681+ const verifyFn = jwtVerifyCallback ?? this . _jwtVerifyCallback
682+ if ( typeof verifyFn !== 'function' ) {
683+ throw Error ( JWT_VERIFY_CONFIG_ERROR )
684+ }
685+
686+ const credReq = credentialRequest as CredentialRequestV1_0_15
687+
688+ // Validate request structure (mutually exclusive)
689+ if ( credReq . proof && credReq . proofs ) {
690+ throw Error ( 'Credential request may not contain both proof and proofs parameters' )
691+ }
692+
693+ // Normalize candidates into a single array
694+ const proofCandidates : Array < ProofOfPossession > = [ ]
695+
696+ if ( credReq . proof ) {
697+ proofCandidates . push ( credReq . proof )
698+ } else if ( credReq . proofs ) {
699+ // Handle "proofs": prioritize 'jwt' as it's the only fully supported type
700+ if ( Array . isArray ( credReq . proofs . jwt ) ) {
701+ proofCandidates . push ( ...credReq . proofs . jwt )
702+ }
703+
704+ // Check if there are no supported proofs found
705+ if ( proofCandidates . length === 0 ) {
706+ const availableTypes = Object . keys ( credReq . proofs ) . join ( ', ' )
707+ throw Error ( `No supported proof types found in request. Available: [${ availableTypes } ]` )
708+ }
709+ } else {
710+ throw Error ( 'Proof of possession is required. No proof or proofs value present in credential request' )
711+ }
712+
713+ // Execute verification
714+ let jwtVerifyResult : JwtVerifyResult | undefined
715+ const validationErrors : string [ ] = [ ]
716+
717+ for ( const proof of proofCandidates ) {
718+ try {
719+ jwtVerifyResult = await verifyFn ( proof )
720+ break
721+ } catch ( error ) {
722+ const msg = error instanceof Error ? error . message : String ( error )
723+ validationErrors . push ( msg )
724+ }
725+ }
726+
727+ // Check success
728+ if ( ! jwtVerifyResult ) {
729+ throw Error ( `Unable to verify any provided proofs. Errors: ${ validationErrors . join ( '; ' ) } ` )
730+ }
688731
689732 const { didDocument, did, jwt } = jwtVerifyResult
690733 const { header, payload } = jwt
0 commit comments