Skip to content

Commit c58c400

Browse files
committed
chore: fixed decodeJsonProperties & tests
1 parent 8bd61e8 commit c58c400

5 files changed

Lines changed: 46 additions & 17 deletions

File tree

packages/client/lib/CredentialOfferClient.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,15 +47,17 @@ export class CredentialOfferClient {
4747
if (uri.includes('credential_offer_uri')) {
4848
const uriObj = getURIComponentsAsArray(uri) as unknown as Record<string, string> // FIXME
4949
const credentialOfferUri = uriObj['credential_offer_uri']
50-
const response = await fetch(credentialOfferUri)
50+
const response = await fetch(decodeURIComponent(credentialOfferUri))
5151
if (!(response && response.status >= 200 && response.status < 400)) {
5252
return Promise.reject(`the credential offer URI endpoint call was not successful. http code ${response.status} - reason ${response.statusText}`)
5353
}
5454

5555
if (response.headers.get('Content-Type')?.startsWith('application/json') === false) {
5656
return Promise.reject('the credential offer URI endpoint did not return content type application/json')
5757
}
58-
credentialOffer = decodeJsonProperties(await response.json()) as CredentialOfferV1_0_11 | CredentialOfferV1_0_13
58+
credentialOffer = {
59+
credential_offer: decodeJsonProperties(await response.json())
60+
} as CredentialOfferV1_0_11 | CredentialOfferV1_0_13
5961
} else {
6062
credentialOffer = convertURIToJsonObject(uri, {
6163
// It must have the '=' sign after credential_offer otherwise the uri will get split at openid_credential_offer

packages/client/lib/__tests__/MetadataClient.spec.ts

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
import { getIssuerFromCredentialOfferPayload, PRE_AUTH_GRANT_LITERAL, WellKnownEndpoints } from '@sphereon/oid4vci-common';
1+
import {
2+
AuthorizationServerMetadata,
3+
getIssuerFromCredentialOfferPayload,
4+
PRE_AUTH_GRANT_LITERAL,
5+
WellKnownEndpoints
6+
} from '@sphereon/oid4vci-common'
27
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
38
// @ts-ignore
49
import nock from 'nock';
@@ -299,6 +304,25 @@ describe.skip('Metadataclient with SpruceId should', () => {
299304
});
300305

301306
describe('Metadataclient with Credenco should', () => {
307+
beforeEach(() => {
308+
const mockData = getMockData('credenco')
309+
if (!mockData?.metadata?.openid4vci_metadata) {
310+
throw new Error('Credenco mock data not found or invalid structure')
311+
}
312+
nock('https://mijnkvk.acc.credenco.com')
313+
.get('/.well-known/openid-credential-issuer')
314+
.reply(200, mockData.metadata.openid4vci_metadata)
315+
nock('https://mijnkvk.acc.credenco.com').get('/.well-known/openid-configuration').reply(404)
316+
const authMetadata: AuthorizationServerMetadata = {
317+
authorization_endpoint: 'https://mijnkvk.acc.credenco.com',
318+
"pre-authorized_grant_anonymous_access_supported": true,
319+
issuer: 'https://issuer.research.identiproof.io',
320+
token_endpoint: 'https://mijnkvk.acc.credenco.com/token',
321+
response_types_supported: ['token']
322+
}
323+
nock('https://mijnkvk.acc.credenco.com').get('/.well-known/oauth-authorization-server').reply(200, JSON.stringify(authMetadata));
324+
})
325+
302326
it('succeed without OID4VCI and with OIDC metadata', async () => {
303327
const metadata = await MetadataClient.retrieveAllMetadata('https://mijnkvk.acc.credenco.com/');
304328
expect(metadata.credential_endpoint).toEqual('https://mijnkvk.acc.credenco.com/credential');

packages/issuer/lib/VcIssuer.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ import {
5151
System,
5252
W3CVerifiableCredential
5353
} from '@sphereon/ssi-types'
54+
import ShortUUID from 'short-uuid'
5455

5556
import {
5657
assertValidPinNumber,
@@ -66,10 +67,11 @@ import {
6667
CredentialSignerCallback
6768
} from './types'
6869

69-
import uuid from 'short-uuid'
7070

7171
import { LOG } from './index'
7272

73+
const shortUUID = ShortUUID()
74+
7375
export class VcIssuer<DIDDoc extends object> {
7476
private readonly _issuerMetadata: CredentialIssuerMetadataOptsV1_0_13
7577
private readonly _authorizationServerMetadata: AuthorizationServerMetadata
@@ -230,7 +232,7 @@ export class VcIssuer<DIDDoc extends object> {
230232
if (!this.uris) {
231233
throw Error('No URI state manager set, whilst apparently credential offer URIs are being used')
232234
}
233-
const credentialOfferCorrelationId = uuid.uuid() // TODO allow to be supplied
235+
const credentialOfferCorrelationId = shortUUID.generate()// TODO allow to be supplied
234236
credentialOfferObject.credential_offer_uri = opts.credentialOfferUri ?? `${issuerPayloadUri}/${credentialOfferCorrelationId}` // TODO how is this going to work with auth code flow?
235237
await this.uris.set(credentialOfferObject.credential_offer_uri, {
236238
uri: credentialOfferObject.credential_offer_uri,

packages/issuer/lib/__tests__/VcIssuer.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -722,9 +722,9 @@ describe('VcIssuer without did', () => {
722722
baseUri: 'issuer-example.com'
723723
})
724724

725-
expect(result.uri).toMatch(/http:\/\/issuer-example\.com\?credential_offer_uri=https%3A%2F%2Fexample\.com%2Fapi%2Fcredentials%3Fid%3D[\w-]+/)
725+
expect(result.uri).toMatch(/http:\/\/issuer-example\.com\?credential_offer_uri=https%3A%2F%2Fexample\.com%2Fapi%2Fcredentials%2F[\w-]+/)
726726
expect(result.session).toBeDefined()
727-
expect(result.session.credentialOffer.credential_offer_uri).toMatch(/https:\/\/example\.com\/api\/credentials\?id=[\w-]+/)
727+
expect(result.session.credentialOffer.credential_offer_uri).toMatch(/https:\/\/example\.com\/api\/credentials\/[\w-]+/)
728728
})
729729

730730
it('should throw error if issuePayloadPath is missing with by_uri_reference mode', async () => {

packages/oid4vci-common/lib/functions/Encoding.ts

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -98,34 +98,35 @@ export function convertURIToJsonObject(uri: string, opts?: DecodeURIAsJsonOpts):
9898
}
9999

100100
export function decodeJsonProperties(parts: string[] | string[][]): unknown {
101-
const json: { [s: string]: unknown } | ArrayLike<unknown> = {};
101+
const result: { [s: string]: unknown } | ArrayLike<unknown> = {};
102102
for (const key in parts) {
103103
const value = parts[key];
104104
if (!value) {
105105
continue;
106106
}
107107
if (Array.isArray(value)) {
108-
// if (value.length > 1) {
109-
json[decodeURIComponent(key)] = value.map((v) => decodeURIComponent(v));
110-
/*} else {
111-
json[decodeURIComponent(key)] = decodeURIComponent(value[0]);
112-
}*/
108+
result[decodeURIComponent(key)] = value.map((v) => decodeURIComponent(v));
109+
continue
113110
}
111+
114112
const isBool = typeof value == 'boolean';
115113
const isNumber = typeof value == 'number';
116114
const isString = typeof value == 'string';
115+
const isObject = typeof value == 'object';
117116
if (isBool || isNumber) {
118-
json[decodeURIComponent(key)] = value;
117+
result[decodeURIComponent(key)] = value;
119118
} else if (isString) {
120119
const decoded = decodeURIComponent(value);
121120
if (decoded.startsWith('{') && decoded.endsWith('}')) {
122-
json[decodeURIComponent(key)] = JSON.parse(decoded);
121+
result[decodeURIComponent(key)] = JSON.parse(decoded);
123122
} else {
124-
json[decodeURIComponent(key)] = decoded;
123+
result[decodeURIComponent(key)] = decoded;
125124
}
125+
} else if(isObject) {
126+
result[decodeURIComponent(key)] = decodeJsonProperties(value)
126127
}
127128
}
128-
return json;
129+
return result;
129130
}
130131

131132
/**

0 commit comments

Comments
 (0)