Skip to content

Commit 3502496

Browse files
authored
Merge pull request #216 from Sphereon-Opensource/feature/SSISDK-94
feature/SSISDK-94
2 parents 20aec3b + e51804f commit 3502496

1 file changed

Lines changed: 63 additions & 8 deletions

File tree

packages/issuer/lib/VcIssuer.ts

Lines changed: 63 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -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,70 @@ 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 | undefined = 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 of ProofOfPossession objects
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+
// Map to ProofOfPossession objects, handling both string and object formats
702+
for (const jwtProof of credReq.proofs.jwt) {
703+
if (typeof jwtProof === 'string') {
704+
// Handle case where jwt array contains strings instead of ProofOfPossession objects
705+
proofCandidates.push({
706+
proof_type: 'jwt',
707+
jwt: jwtProof,
708+
})
709+
} else if (jwtProof && typeof jwtProof === 'object' && 'jwt' in jwtProof) {
710+
// Handle proper ProofOfPossession object
711+
proofCandidates.push(jwtProof)
712+
}
713+
}
714+
}
715+
716+
// Check if there are no supported proofs found
717+
if (proofCandidates.length === 0) {
718+
const availableTypes = Object.keys(credReq.proofs).join(', ')
719+
throw Error(`No supported proof types found in request. Available: [${availableTypes}]`)
720+
}
721+
} else {
722+
throw Error('Proof of possession is required. No proof or proofs value present in credential request')
723+
}
724+
725+
// Execute verification
726+
let jwtVerifyResult: JwtVerifyResult | undefined
727+
const validationErrors: string[] = []
728+
729+
for (const proof of proofCandidates) {
730+
try {
731+
jwtVerifyResult = await verifyFn({ jwt: proof.jwt })
732+
break
733+
} catch (error) {
734+
const msg = error instanceof Error ? error.message : String(error)
735+
validationErrors.push(msg)
736+
}
737+
}
738+
739+
// Check success
740+
if (!jwtVerifyResult) {
741+
throw Error(`Unable to verify any provided proofs. Errors: ${validationErrors.join('; ')}`)
742+
}
688743

689744
const { didDocument, did, jwt } = jwtVerifyResult
690745
const { header, payload } = jwt

0 commit comments

Comments
 (0)