@@ -2,8 +2,10 @@ import { createDPoP, CreateDPoPClientOpts, getCreateDPoPOptions } from '@sphereo
22import {
33 acquireDeferredCredential ,
44 AuthorizationDetailsV1_0_15 ,
5+ AuthorizationDetailsV1_0 ,
56 CredentialRequest ,
67 CredentialRequestV1_0_15 ,
8+ CredentialRequestV1_0 ,
79 CredentialResponse ,
810 DPoPResponseParams ,
911 ExperimentalSubjectIssuance ,
@@ -20,6 +22,7 @@ import {
2022import { CredentialFormat , Loggers } from '@sphereon/ssi-types'
2123
2224import { CredentialRequestClientBuilderV1_0_15 } from './CredentialRequestClientBuilderV1_0_15'
25+ import { CredentialRequestClientBuilderV1_0 } from './CredentialRequestClientBuilderV1_0'
2326import { ProofOfPossessionBuilder } from './ProofOfPossessionBuilder'
2427import { shouldRetryResourceRequestWithDPoPNonce } from './functions/dpopUtil'
2528
@@ -32,14 +35,15 @@ export interface CredentialRequestOpts {
3235 notificationEndpoint ?: string
3336 deferredCredentialEndpoint ?: string
3437 credentialTypes ?: string [ ]
35- credentialIdentifier ?: string
38+ credentialIdentifier ?: string // d15: singular
39+ credentialIdentifiers ?: string [ ] // 1.0 final: array
3640 credentialConfigurationId ?: string
3741 proof : ProofOfPossession
3842 token : string
3943 version : OpenId4VCIVersion
4044 subjectIssuance ?: ExperimentalSubjectIssuance
4145 issuerState ?: string
42- authorizationDetails ?: AuthorizationDetailsV1_0_15 [ ]
46+ authorizationDetails ?: ( AuthorizationDetailsV1_0_15 | AuthorizationDetailsV1_0 ) [ ]
4347}
4448
4549export type CreateCredentialRequestOpts = {
@@ -134,7 +138,7 @@ export class CredentialRequestClient {
134138 return this . credentialRequestOpts . deferredCredentialEndpoint
135139 }
136140
137- public constructor ( builder : CredentialRequestClientBuilderV1_0_15 ) {
141+ public constructor ( builder : CredentialRequestClientBuilderV1_0_15 | CredentialRequestClientBuilderV1_0 ) {
138142 this . _credentialRequestOpts = { ...builder }
139143 }
140144
@@ -304,41 +308,74 @@ export class CredentialRequestClient {
304308 } )
305309 }
306310
307- public async createCredentialRequestWithoutProof ( opts : CreateCredentialRequestOpts ) : Promise < CredentialRequestV1_0_15 > {
311+ public async createCredentialRequestWithoutProof ( opts : CreateCredentialRequestOpts ) : Promise < CredentialRequestV1_0_15 | CredentialRequestV1_0 > {
308312 return await this . createCredentialRequestImpl ( opts )
309313 }
310314
311315 public async createCredentialRequest (
312316 opts : CreateCredentialRequestOpts & {
313317 proofInput : ProofOfPossessionBuilder | ProofOfPossession
314318 } ,
315- ) : Promise < CredentialRequestV1_0_15 > {
319+ ) : Promise < CredentialRequestV1_0_15 | CredentialRequestV1_0 > {
316320 return await this . createCredentialRequestImpl ( opts )
317321 }
318322
319323 private async createCredentialRequestImpl (
320324 opts : CreateCredentialRequestOpts & {
321325 proofInput ?: ProofOfPossessionBuilder | ProofOfPossession
322326 } ,
323- ) : Promise < CredentialRequestV1_0_15 > {
327+ ) : Promise < CredentialRequestV1_0_15 | CredentialRequestV1_0 > {
324328 const { proofInput, credentialIdentifier, credentialConfigurationId } = opts
325329 let proof : ProofOfPossession | undefined = undefined
326330 if ( proofInput ) {
327331 proof = await buildProof ( proofInput , opts )
328332 }
329333
330- // For v15, handle authorization details from token response
331- if ( this . version ( ) >= OpenId4VCIVersion . VER_1_0_15 ) {
332- const authDetail = findAuthorizationDetail ( this . credentialRequestOpts . authorizationDetails , credentialConfigurationId ?? credentialIdentifier )
334+ const issuer_state = this . credentialRequestOpts . issuerState
335+ const commonBody = {
336+ ...( issuer_state && { issuer_state } ) ,
337+ ...( proof && { proof } ) ,
338+ ...opts . subjectIssuance ,
339+ }
333340
334- const issuer_state = this . credentialRequestOpts . issuerState
341+ // 1.0 final: credential_configuration_id is REQUIRED, credential_identifiers is OPTIONAL array
342+ if ( this . version ( ) >= OpenId4VCIVersion . VER_1_0 ) {
343+ const authDetail = findAuthorizationDetail (
344+ this . credentialRequestOpts . authorizationDetails as AuthorizationDetailsV1_0_15 [ ] ,
345+ credentialConfigurationId ?? credentialIdentifier ,
346+ )
347+ const authDetailObj = authDetail && typeof authDetail === 'object' ? ( authDetail as any ) : null
335348
336- const commonBody = {
337- ...( issuer_state && { issuer_state } ) ,
338- ...( proof && { proof } ) ,
339- ...opts . subjectIssuance ,
349+ const configId =
350+ credentialConfigurationId ?? authDetailObj ?. credential_configuration_id ?? this . _credentialRequestOpts . credentialConfigurationId
351+
352+ if ( ! configId ) {
353+ return Promise . reject ( Error ( 'credential_configuration_id is required for 1.0 final credential request' ) )
340354 }
341355
356+ // Build credential_identifiers array from various sources
357+ const identifiers : string [ ] | undefined =
358+ this . _credentialRequestOpts . credentialIdentifiers ??
359+ ( authDetailObj ?. credential_identifiers && authDetailObj . credential_identifiers . length > 0
360+ ? authDetailObj . credential_identifiers
361+ : credentialIdentifier
362+ ? [ credentialIdentifier ]
363+ : undefined )
364+
365+ const request : CredentialRequestV1_0 = {
366+ credential_configuration_id : configId ,
367+ ...( identifiers && identifiers . length > 0 && { credential_identifiers : identifiers } ) ,
368+ ...commonBody ,
369+ }
370+ return request
371+ }
372+
373+ // Draft 15: credential_identifier (singular) OR credential_configuration_id
374+ if ( this . version ( ) >= OpenId4VCIVersion . VER_1_0_15 ) {
375+ const authDetail = findAuthorizationDetail (
376+ this . credentialRequestOpts . authorizationDetails as AuthorizationDetailsV1_0_15 [ ] ,
377+ credentialConfigurationId ?? credentialIdentifier ,
378+ )
342379 const authDetailObj = authDetail && typeof authDetail === 'object' ? ( authDetail as any ) : null
343380
344381 if ( authDetailObj ?. credential_identifier ) {
@@ -374,7 +411,6 @@ export class CredentialRequestClient {
374411 return Promise . reject ( Error ( 'No credential_identifier or credential_configuration_id available for v1.0-15 request' ) )
375412 }
376413
377- // Since you only support V15+, this should never execute
378414 throw new Error ( `Unsupported version: ${ this . version ( ) } ` )
379415 }
380416
0 commit comments