@@ -5,14 +5,16 @@ import {
55 convertJsonToURI ,
66 CreateRequestObjectMode ,
77 CredentialConfigurationSupportedV1_0_13 ,
8+ CredentialDefinitionJwtVcJsonLdAndLdpVcV1_0_13 ,
9+ CredentialDefinitionJwtVcJsonV1_0_13 ,
810 CredentialOfferPayloadV1_0_13 ,
911 CredentialOfferRequestWithBaseUrl ,
1012 determineSpecVersionFromOffer ,
1113 EndpointMetadataResultV1_0_13 ,
1214 formPost ,
15+ isW3cCredentialSupported ,
1316 JsonURIMode ,
1417 Jwt ,
15- OID4VCICredentialFormat ,
1618 OpenId4VCIVersion ,
1719 PARMode ,
1820 PKCEOpts ,
@@ -95,14 +97,17 @@ export const createAuthorizationRequestUrl = async ({
9597 clientId ?: string ;
9698 version ?: OpenId4VCIVersion ;
9799} ) : Promise < string > => {
98- function removeDisplayAndValueTypes ( obj : any ) : void {
99- for ( const prop in obj ) {
100+ function removeDisplayAndValueTypes ( obj : any ) {
101+ const newObj = { ...obj } ;
102+ for ( const prop in newObj ) {
100103 if ( [ 'display' , 'value_type' ] . includes ( prop ) ) {
101- delete obj [ prop ] ;
102- } else if ( typeof obj [ prop ] === 'object' ) {
103- removeDisplayAndValueTypes ( obj [ prop ] ) ;
104+ delete newObj [ prop ] ;
105+ } else if ( typeof newObj [ prop ] === 'object' ) {
106+ newObj [ prop ] = removeDisplayAndValueTypes ( newObj [ prop ] ) ;
104107 }
105108 }
109+
110+ return newObj ;
106111 }
107112
108113 const { redirectUri, requestObjectOpts = { requestObjectMode : CreateRequestObjectMode . NONE } } = authorizationRequest ;
@@ -111,7 +116,7 @@ export const createAuthorizationRequestUrl = async ({
111116 let { scope, authorizationDetails } = authorizationRequest ;
112117 const parMode = endpointMetadata ?. credentialIssuerMetadata ?. require_pushed_authorization_requests
113118 ? PARMode . REQUIRE
114- : ( authorizationRequest . parMode ?? ( client_id ? PARMode . AUTO : PARMode . NEVER ) ) ;
119+ : authorizationRequest . parMode ?? ( client_id ? PARMode . AUTO : PARMode . NEVER ) ;
115120 // Scope and authorization_details can be used in the same authorization request
116121 // https://datatracker.ietf.org/doc/html/draft-ietf-oauth-rar-23#name-relationship-to-scope-param
117122 if ( ! scope && ! authorizationDetails ) {
@@ -127,42 +132,42 @@ export const createAuthorizationRequestUrl = async ({
127132 ? filterSupportedCredentials ( credentialOffer . credential_offer as CredentialOfferPayloadV1_0_13 , credentialConfigurationSupported )
128133 : [ ] ;
129134
130- // FIXME: complains about VCT for sd-jwt
131- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
132- // @ts -ignore
133135 authorizationDetails = creds . flatMap ( ( cred ) => {
134136 const locations = [ credentialOffer ?. credential_offer . credential_issuer ?? endpointMetadata . issuer ] ;
137+
138+ // TODO: credential_configuration_id seems to always be defined?
135139 const credential_configuration_id : string | undefined = cred . configuration_id ;
136- const vct : string | undefined = cred . vct ;
137- let format : OID4VCICredentialFormat | undefined ;
140+ const format = credential_configuration_id ? undefined : cred . format ;
138141
139- if ( ! credential_configuration_id ) {
140- format = cred . format ;
141- }
142142 if ( ! credential_configuration_id && ! cred . format ) {
143143 throw Error ( 'format is required in authorization details' ) ;
144144 }
145145
146- const meta : any = { } ;
147- const credential_definition = cred . credential_definition ;
148- if ( credential_definition ?. type && ! format ) {
149- // ype: OPTIONAL. Array as defined in Appendix A.1.1.2. This claim contains the type values the Wallet requests authorization for at the Credential Issuer. It MUST be present if the claim format is present in the root of the authorization details object. It MUST not be present otherwise.
150- // It meens we have a config_id, already mapping it to an explicit format and types
151- delete credential_definition . type ;
152- }
153- if ( credential_definition . credentialSubject ) {
154- removeDisplayAndValueTypes ( credential_definition . credentialSubject ) ;
146+ // SD-JWT VC
147+ const vct = cred . format === 'vc+sd-jwt' ? cred . vct : undefined ;
148+
149+ // W3C credentials
150+ let credential_definition : undefined | Partial < CredentialDefinitionJwtVcJsonV1_0_13 | CredentialDefinitionJwtVcJsonLdAndLdpVcV1_0_13 > =
151+ undefined ;
152+ if ( isW3cCredentialSupported ( cred ) ) {
153+ credential_definition = {
154+ ...cred . credential_definition ,
155+ // type: OPTIONAL. Array as defined in Appendix A.1.1.2. This claim contains the type values the Wallet requests authorization for at the Credential Issuer. It MUST be present if the claim format is present in the root of the authorization details object. It MUST not be present otherwise.
156+ // It meens we have a config_id, already mapping it to an explicit format and types
157+ type : format ? cred . credential_definition . type : undefined ,
158+ credentialSubject : cred . credential_definition . credentialSubject
159+ ? removeDisplayAndValueTypes ( cred . credential_definition . credentialSubject )
160+ : undefined ,
161+ } ;
155162 }
156163
157164 return {
158165 type : 'openid_credential' ,
159- ...meta ,
160166 locations,
161167 ...( credential_definition && { credential_definition } ) ,
162168 ...( credential_configuration_id && { credential_configuration_id } ) ,
163169 ...( format && { format } ) ,
164- ...( vct && { vct } ) ,
165- ...( cred . claims && { claims : removeDisplayAndValueTypes ( JSON . parse ( JSON . stringify ( cred . claims ) ) ) } ) ,
170+ ...( vct && { vct, claims : cred . claims ? removeDisplayAndValueTypes ( cred . claims ) : undefined } ) ,
166171 } as AuthorizationDetails ;
167172 } ) ;
168173 if ( ! authorizationDetails || authorizationDetails . length === 0 ) {
0 commit comments