Skip to content

Commit 748e526

Browse files
authored
Merge pull request #406 from openwallet-foundation-labs/fix/dc-api-sdk
Fix/dc-api-sdk
2 parents ab41512 + a8bc386 commit 748e526

File tree

13 files changed

+468
-94
lines changed

13 files changed

+468
-94
lines changed

apps/backend/src/issuer/configuration/credentials/credential-config/credential-config.service.ts

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -131,18 +131,6 @@ export class CredentialConfigService {
131131
(config as CredentialConfig).cert = cert;
132132
}
133133

134-
//check if status revocation is enabled and if yes, ensure a status list is available
135-
if (config.statusManagement) {
136-
const hasEntries = await this.statusListService.hasStillFreeEntries(
137-
tenantId,
138-
config.id,
139-
);
140-
if (!hasEntries) {
141-
// Create a new shared list if no available list exists
142-
await this.statusListService.createNewList(tenantId);
143-
}
144-
}
145-
146134
await this.store(tenantId, config);
147135
}
148136

apps/backend/src/verifier/oid4vp/oid4vp.service.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,7 @@ export class Oid4vpService {
138138
payload: {
139139
response_type: "vp_token",
140140
client_id: "x509_hash:" + certHash,
141-
response_uri: session.useDcApi
142-
? undefined
143-
: `${host}/${session.id}/oid4vp`,
141+
response_uri: `${host}/${session.id}/oid4vp`,
144142
response_mode: session.useDcApi
145143
? "dc_api.jwt"
146144
: "direct_post.jwt",

apps/backend/src/verifier/presentations/credential/base-verifier.service.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ export abstract class BaseVerifierService {
126126
* @returns Hex-encoded thumbprint
127127
*/
128128
protected async getThumbprint(cert: x509.X509Certificate): Promise<string> {
129-
const buffer = await cert.getThumbprint();
129+
const buffer = await cert.getThumbprint("SHA-256");
130130
return Array.from(new Uint8Array(buffer))
131131
.map((b) => b.toString(16).padStart(2, "0"))
132132
.join("");

apps/backend/test/utils.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -655,7 +655,7 @@ export async function setupPresentationTestApp(): Promise<PresentationTestContex
655655

656656
// Import statuslist key and cert
657657
const statusListKey = readConfig<KeyImportDto>(
658-
join(configFolder, "root/keys/status-list.json"),
658+
join(configFolder, "root/keys/sign.json"),
659659
);
660660

661661
await expectRequest(
@@ -669,7 +669,7 @@ export async function setupPresentationTestApp(): Promise<PresentationTestContex
669669
const statusListCert = readConfig<CertImportDto>(
670670
join(
671671
configFolder,
672-
"root/certs/certificate-0f6e186f-9763-49ec-8d93-6cb801ded7a4-config.json",
672+
"root/certs/certificate-b6db7c84-776e-4998-9d40-ac599a4ea1fc-config.json",
673673
),
674674
);
675675

apps/client/src/app/session-management/session-management-show/session-management-show.component.ts

Lines changed: 63 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { MatTooltipModule } from '@angular/material/tooltip';
1010
import { ActivatedRoute, Router, RouterModule } from '@angular/router';
1111
import { FlexLayoutModule } from 'ngx-flexible-layout';
1212
import * as QRCode from 'qrcode';
13-
import { Session } from '@eudiplo/sdk-core';
13+
import { Session, isDcApiAvailable, type DigitalCredentialResponse } from '@eudiplo/sdk-core';
1414
import { SessionManagementService } from '../session-management.service';
1515
import { HttpClient } from '@angular/common/http';
1616
import { firstValueFrom } from 'rxjs';
@@ -116,51 +116,81 @@ export class SessionManagementShowComponent implements OnInit, OnDestroy {
116116
}
117117

118118
async getDcApiCall() {
119-
if (!this.session?.requestUrl) return;
119+
if (!this.session?.requestObject) {
120+
this.snackBar.open('No request object available for DC API', 'Close', { duration: 3000 });
121+
return;
122+
}
120123

121-
if (
122-
!('credentials' in navigator) ||
123-
!('get' in navigator.credentials) ||
124-
!('DigitalCredential' in window)
125-
) {
124+
if (!isDcApiAvailable()) {
126125
console.warn('Digital Credentials API not available — handing off via deep link.');
126+
this.snackBar.open('Digital Credentials API not available in this browser', 'Close', {
127+
duration: 3000,
128+
});
127129
return;
128130
}
129131

130-
console.log('Calling Digital Credentials API (signed)…');
131-
console.log({
132-
mediation: 'required',
133-
digital: {
134-
requests: [
135-
{ protocol: 'openid4vp-v1-signed', data: { request: this.session.requestObject } },
136-
],
137-
},
138-
});
139-
const dcResponse = await navigator.credentials
140-
.get({
132+
try {
133+
console.log('Calling Digital Credentials API (signed)…');
134+
135+
// Call the Digital Credentials API
136+
const credential = (await navigator.credentials.get({
141137
mediation: 'required',
142138
digital: {
143139
requests: [
144-
{ protocol: 'openid4vp-v1-signed', data: { request: this.session.requestObject } },
140+
{
141+
protocol: 'openid4vp-v1-signed',
142+
data: { request: this.session.requestObject },
143+
},
145144
],
146145
},
147-
} as CredentialRequestOptions)
148-
.catch((err) => {
149-
console.error(err);
150-
throw err;
151-
});
152-
console.log('Digital Credentials API response:', dcResponse);
146+
} as CredentialRequestOptions)) as DigitalCredentialResponse | null;
147+
148+
console.log('Digital Credentials API response:', credential);
149+
150+
if (!credential) {
151+
throw new Error('No response from Digital Credentials API');
152+
}
153+
154+
if (credential.data?.error) {
155+
console.error('Wallet protocol error:', credential.data.error, credential.data);
156+
throw new Error(
157+
`${credential.data.error}${credential.data.error_description ? `: ${credential.data.error_description}` : ''}`
158+
);
159+
}
160+
161+
// Extract response_uri from the request object and submit
162+
const responseUri = decodeJwt<{ response_uri?: string }>(
163+
this.session.requestObject
164+
).response_uri;
165+
166+
if (!responseUri) {
167+
throw new Error('No response_uri found in request object');
168+
}
169+
170+
const submitRes = await firstValueFrom(
171+
this.httpClient.post(responseUri, { ...credential.data, sendResponse: true })
172+
);
173+
174+
console.log('Verifier response:', submitRes);
175+
this.snackBar.open('Presentation submitted successfully!', 'Close', { duration: 3000 });
153176

154-
if (dcResponse?.data?.error) {
155-
console.error('Wallet protocol error:', dcResponse.data.error, dcResponse.data);
156-
throw new Error(dcResponse.data.error);
177+
// Refresh the session to show updated status
178+
await this.loadSession(this.session.id);
179+
} catch (error) {
180+
console.error('DC API error:', error);
181+
this.snackBar.open(
182+
`DC API error: ${error instanceof Error ? error.message : 'Unknown error'}`,
183+
'Close',
184+
{ duration: 5000 }
185+
);
157186
}
187+
}
158188

159-
const responseUri = decodeJwt<any>(this.session.requestObject!).response_uri;
160-
const submitRes = await firstValueFrom(
161-
this.httpClient.post(responseUri, { ...dcResponse!.data, sendResponse: true })
162-
);
163-
console.log('Verifier response:', submitRes);
189+
/**
190+
* Check if the Digital Credentials API is available
191+
*/
192+
isDcApiAvailable(): boolean {
193+
return isDcApiAvailable();
164194
}
165195

166196
getStatusClass(status: any): string {

assets/config/root/certs/certificate-0f6e186f-9763-49ec-8d93-6cb801ded7a4-config.json

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

assets/config/root/certs/certificate-b6db7c84-776e-4998-9d40-ac599a4ea1fc-config.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"id": "b6db7c84-776e-4998-9d40-ac599a4ea1fc",
33
"keyId": "dbb65456-c358-46c1-bb5b-c777ef72c1d3",
4-
"description": "Self-signed certificate (access, signing) for tenant Root Tenant",
4+
"description": "Self-signed certificate (access, signing, statusList) for tenant Root Tenant",
55
"crt": "-----BEGIN CERTIFICATE-----\nMIIBiTCCATCgAwIBAgIBATAKBggqhkjOPQQDAjAjMQswCQYDVQQGEwJERTEUMBIG\nA1UEAxMLUm9vdCBUZW5hbnQwHhcNMjYwMTAzMTczMTAyWhcNMjcwMTAzMTczMTAy\nWjAjMQswCQYDVQQGEwJERTEUMBIGA1UEAxMLUm9vdCBUZW5hbnQwWTATBgcqhkjO\nPQIBBggqhkjOPQMBBwNCAAQceSRtSApKSSpeYvy62X5MtYiDwJhBLhY8nyP+c7jh\njNTSWNC095hLrnC0AmSVjawO31VvMqUeGX+XLrvOTY0so1UwUzAiBgNVHREEGzAZ\nghdzZXJ2aWNlLmV1ZGktd2FsbGV0LmRldjAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0O\nBBYEFG9BfgN82iWP/ERGyroyefQsnUtkMAoGCCqGSM49BAMCA0cAMEQCIECyGfF/\nNtZi/x8rwmcTi4xURmlkMLsPJhDRqFwbsGWrAiAjHVDTHiVsNyKSCDGZYDeI4mN0\nXSjy5D8WPahXZeUINQ==\n-----END CERTIFICATE-----",
66
"certUsageTypes": [
77
"access",

assets/config/root/certs/playground-vinecard.json

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

assets/config/root/keys/key.json

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

assets/config/root/keys/status-list.json

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

0 commit comments

Comments
 (0)