Skip to content

Commit ece4db0

Browse files
authored
Bump credo (#868)
* chore: bump credo * fix: store legacy key id * fix: re-add encoded credential * test: remove only * refactor: remove comment * fix: only re-add for PEX
1 parent 116d385 commit ece4db0

12 files changed

Lines changed: 152 additions & 416 deletions

package-lock.json

Lines changed: 105 additions & 261 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/consumption/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,8 @@
6262
]
6363
},
6464
"dependencies": {
65-
"@credo-ts/core": "v0.6.0-alpha-20251110135447",
66-
"@credo-ts/openid4vc": "v0.6.0-alpha-20251110135447",
65+
"@credo-ts/core": "v0.6.0-alpha-20251121023030",
66+
"@credo-ts/openid4vc": "v0.6.0-alpha-20251121023030",
6767
"@js-soft/docdb-querytranslator": "^1.1.6",
6868
"@js-soft/ts-serval": "2.0.14",
6969
"@js-soft/ts-utils": "2.3.5",

packages/consumption/src/modules/openid4vc/OpenId4VcController.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ export class OpenId4VcController extends ConsumptionBaseController {
7171
const matchedCredentialsFromPresentationExchange = authorizationRequest.presentationExchange?.credentialsForRequest.requirements
7272
.map((entry) =>
7373
entry.submissionEntry
74-
.map((subEntry) => subEntry.verifiableCredentials.filter((vc) => vc.claimFormat === ClaimFormat.SdJwtDc).map((vc) => vc.credentialRecord.compactSdJwtVc))
74+
.map((subEntry) => subEntry.verifiableCredentials.filter((vc) => vc.claimFormat === ClaimFormat.SdJwtDc).map((vc) => vc.credentialRecord.encoded))
7575
.flat()
7676
)
7777
.flat();

packages/consumption/src/modules/openid4vc/local/EnmeshedHolderKeyManagmentService.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,10 @@ export class EnmshedHolderKeyManagmentService implements Kms.KeyManagementServic
112112
// store the key pair in the keystore
113113
await this.keyStorage.storeKey(options.keyId, JSON.stringify(jwkKeyPair));
114114

115+
// Credo doesn't trust the key id provided in the key binding jwk anymore, so there are two options: Storing the key id with the credential and making sure that key id is properly fetched - this turned out to be difficult - or the easy way out by storing this alternative key id computed from the public key.
116+
const credoLegacyKeyId = Kms.PublicJwk.fromPublicJwk(publicJwk as any).legacyKeyId;
117+
await this.keyStorage.storeKey(credoLegacyKeyId, JSON.stringify(jwkKeyPair));
118+
115119
return { keyId: options.keyId, publicJwk: publicJwk as Kms.KmsJwkPublic } as Kms.KmsCreateKeyReturn<Type>;
116120
}
117121

packages/consumption/src/modules/openid4vc/local/EnmeshedStorageService.ts

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,12 @@ import {
44
BaseRecordConstructor,
55
ClaimFormat,
66
injectable,
7-
Mdoc,
87
MdocRecord,
98
Query,
109
QueryOptions,
1110
SdJwtVcRecord,
1211
StorageService,
13-
W3cCredentialRecord,
14-
W3cJwtVerifiableCredential
12+
W3cCredentialRecord
1513
} from "@credo-ts/core";
1614
import { IdentityAttribute, VerifiableCredential } from "@nmshd/content";
1715
import { AccountController } from "@nmshd/transport";
@@ -123,14 +121,11 @@ export class EnmeshedStorageService<T extends BaseRecord> implements StorageServ
123121
private fromEncoded(type: string, encoded: string | Record<string, any>): BaseRecord<any, any> {
124122
switch (type) {
125123
case ClaimFormat.SdJwtDc:
126-
return new SdJwtVcRecord({ compactSdJwtVc: encoded as string });
124+
return new SdJwtVcRecord({ credentialInstances: [{ compactSdJwtVc: encoded as string }] });
127125
case ClaimFormat.MsoMdoc:
128-
return new MdocRecord({ mdoc: Mdoc.fromBase64Url(encoded as string) });
126+
return new MdocRecord({ credentialInstances: [{ issuerSignedBase64Url: encoded as string }] });
129127
case ClaimFormat.SdJwtW3cVc:
130-
return new W3cCredentialRecord({
131-
credential: W3cJwtVerifiableCredential.fromSerializedJwt(encoded as string),
132-
tags: {}
133-
});
128+
return new W3cCredentialRecord({ credentialInstances: [{ credential: encoded as string }] });
134129
default:
135130
throw new Error("Credential type not supported.");
136131
}

packages/consumption/src/modules/openid4vc/local/Holder.ts

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,4 @@
1-
import {
2-
BaseRecord,
3-
ClaimFormat,
4-
DidJwk,
5-
DidKey,
6-
InjectionSymbols,
7-
JwkDidCreateOptions,
8-
KeyDidCreateOptions,
9-
Kms,
10-
Mdoc,
11-
MdocRecord,
12-
SdJwtVcRecord,
13-
X509Module
14-
} from "@credo-ts/core";
1+
import { BaseRecord, ClaimFormat, DidJwk, DidKey, InjectionSymbols, JwkDidCreateOptions, KeyDidCreateOptions, Kms, MdocRecord, SdJwtVcRecord, X509Module } from "@credo-ts/core";
152
import { OpenId4VcModule, type OpenId4VciResolvedCredentialOffer, type OpenId4VpResolvedAuthorizationRequest } from "@credo-ts/openid4vc";
163
import { AccountController } from "@nmshd/transport";
174
import { AttributesController, OwnIdentityAttribute } from "../../attributes";
@@ -110,7 +97,7 @@ export class Holder extends BaseAgent<ReturnType<typeof getOpenIdHolderModules>>
11097
const storedCredentials = await Promise.all(
11198
credentialResponse.credentials.map((response) => {
11299
// TODO: batch issuance not yet supported
113-
const credential = response.credentials[0];
100+
const credential = response.record.firstCredential;
114101

115102
if (![ClaimFormat.SdJwtW3cVc, ClaimFormat.SdJwtDc, ClaimFormat.MsoMdoc].includes(credential.claimFormat)) {
116103
throw new Error("Unsupported credential format");
@@ -166,15 +153,15 @@ export class Holder extends BaseAgent<ReturnType<typeof getOpenIdHolderModules>>
166153
const record = new SdJwtVcRecord({
167154
id: recordUncast.id,
168155
createdAt: recordUncast.createdAt,
169-
compactSdJwtVc: recordUncast.compactSdJwtVc
156+
credentialInstances: [{ compactSdJwtVc: recordUncast.encoded }]
170157
});
171158
vc.credentialRecord = record;
172159
} else if (vc.claimFormat === ClaimFormat.MsoMdoc) {
173160
const recordUncast = vc.credentialRecord;
174161
const record = new MdocRecord({
175162
id: recordUncast.id,
176163
createdAt: recordUncast.createdAt,
177-
mdoc: Mdoc.fromBase64Url(recordUncast.base64Url)
164+
credentialInstances: [{ issuerSignedBase64Url: recordUncast.encoded }]
178165
});
179166
vc.credentialRecord = record;
180167
} else {

packages/runtime/src/useCases/consumption/openid4vc/ResolveAuthorizationRequest.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,16 @@ export class ResolveAuthorizationRequestUseCase extends UseCase<ResolveAuthoriza
3333
protected override async executeInternal(request: ResolveAuthorizationRequestRequest): Promise<Result<ResolveAuthorizationRequestResponse>> {
3434
const result = await this.openId4VcController.resolveAuthorizationRequest(request.authorizationRequestUrl);
3535

36-
return Result.ok({
37-
authorizationRequest: JSON.parse(stringifySafe(result.authorizationRequest)),
38-
usedCredentials: AttributeMapper.toAttributeDTOList(result.usedCredentials)
39-
});
36+
const authorizationRequest = JSON.parse(stringifySafe(result.authorizationRequest));
37+
// the 'get encoded' of the credential is lost while making it app-safe, we have to re-add it for PEX
38+
// quick-fix for the simplest case with one requested credential only - otherwise every [0] would have to be generalised.
39+
if (result.authorizationRequest.presentationExchange) {
40+
const encodedCredential =
41+
result.authorizationRequest.presentationExchange.credentialsForRequest.requirements[0].submissionEntry[0].verifiableCredentials[0].credentialRecord.encoded;
42+
authorizationRequest.presentationExchange.credentialsForRequest.requirements[0].submissionEntry[0].verifiableCredentials[0].credentialRecord.encoded =
43+
encodedCredential;
44+
}
45+
46+
return Result.ok({ authorizationRequest, usedCredentials: AttributeMapper.toAttributeDTOList(result.usedCredentials) });
4047
}
4148
}

patches/@openid4vc+oauth2+0.3.0-alpha-20251110130103.patch

Lines changed: 0 additions & 50 deletions
This file was deleted.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
diff --git a/node_modules/@openid4vc/oauth2/dist/index.cjs b/node_modules/@openid4vc/oauth2/dist/index.cjs
2+
index 3286de2..c99b244 100644
3+
--- a/node_modules/@openid4vc/oauth2/dist/index.cjs
4+
+++ b/node_modules/@openid4vc/oauth2/dist/index.cjs
5+
@@ -1578,11 +1578,16 @@ async function createJarAuthorizationRequest(options) {
6+
* @throws {Error} if parsing json from response fails
7+
*/
8+
async function fetchWellKnownMetadata(wellKnownMetadataUrl, schema, options) {
9+
+ try {
10+
const { result, response } = await (0, __openid4vc_utils.createZodFetcher)(options?.fetch)(schema, options?.acceptedContentType ?? [__openid4vc_utils.ContentType.Json], wellKnownMetadataUrl);
11+
if (response.status === 404) return null;
12+
if (!response.ok) throw new __openid4vc_utils.InvalidFetchResponseError(`Fetching well known metadata from '${wellKnownMetadataUrl}' resulted in an unsuccessful response with status '${response.status}'.`, await response.clone().text(), response);
13+
if (!result?.success) throw new ValidationError$1(`Validation of metadata from '${wellKnownMetadataUrl}' failed`, result?.error);
14+
return result.data;
15+
+ } catch (e) {
16+
+ console.log('Changed By JS-SOFT: Error can probably be ignored', e);
17+
+ return null;
18+
+ }
19+
}
20+
21+
//#endregion

patches/@openid4vc+openid4vci+0.3.0-alpha-20251110130103.patch

Lines changed: 0 additions & 24 deletions
This file was deleted.

0 commit comments

Comments
 (0)