Skip to content

Commit b8557d8

Browse files
authored
Merge pull request #504 from privacybydesign/fix-credential-removal-logs
Fix credential removal logs
2 parents 94a8e36 + d62a4f9 commit b8557d8

5 files changed

Lines changed: 84 additions & 71 deletions

File tree

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
66

77
## Unreleased
88

9+
## [0.19.1] - 2025-10-13
10+
### Fix
11+
- Bug in `irmaclient` that caused attributes to be stored in the wrong order in credential removal logs
12+
913
## [0.19.0] - 2025-09-30
1014
### Changed
1115
- Remove legacy storage from irmaclient
@@ -580,6 +584,7 @@ This release contains several large new features. In particular, the shoulder su
580584
- Combined issuance-disclosure requests with two schemes one of which has a keyshare server now work as expected
581585
- Various other bugfixes
582586

587+
[0.19.1]: https://github.com/privacybydesign/irmago/compare/v0.19.0...v0.19.1
583588
[0.19.0]: https://github.com/privacybydesign/irmago/compare/v0.18.1...v0.19.0
584589
[0.18.1]: https://github.com/privacybydesign/irmago/compare/v0.18.0...v0.18.1
585590
[0.18.0]: https://github.com/privacybydesign/irmago/compare/v0.17.1...v0.18.0

internal/sessiontest/client_integration_test.go

Lines changed: 69 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ func testDoubleSdJwtIssuanceReplacesInstances(t *testing.T) {
6060
client := createClient(t)
6161
defer client.Close()
6262

63-
issueSdJwtAndIdemixToClient(t, client, irmaServer)
63+
performIrmaIssuanceSession(t, client, irmaServer, createIrmaIssuanceRequestWithSdJwts("test.test.email", "email"))
6464

6565
info := client.CredentialInfoList()
6666
require.Len(t, info, 3)
@@ -72,7 +72,7 @@ func testDoubleSdJwtIssuanceReplacesInstances(t *testing.T) {
7272

7373
require.Equal(t, 10, int(*cred.InstanceCount))
7474

75-
issueSdJwtAndIdemixToClient(t, client, irmaServer)
75+
performIrmaIssuanceSession(t, client, irmaServer, createIrmaIssuanceRequestWithSdJwts("test.test.email", "email"))
7676

7777
info = client.CredentialInfoList()
7878
require.Len(t, info, 3)
@@ -95,7 +95,7 @@ func testCredentialInstanceCount(t *testing.T) {
9595
client := createClient(t)
9696
defer client.Close()
9797

98-
issueSdJwtAndIdemixToClient(t, client, irmaServer)
98+
performIrmaIssuanceSession(t, client, irmaServer, createIrmaIssuanceRequestWithSdJwts("test.test.email", "email"))
9999

100100
info := client.CredentialInfoList()
101101
require.Len(t, info, 3)
@@ -153,6 +153,20 @@ func testLogsForCombinedIssuanceAndDisclosure(t *testing.T) {
153153
require.Len(t, latestLog.IssuanceLog.Credentials, 1)
154154
}
155155

156+
func createMijnOverheidIssuanceRequest() *irma.IssuanceRequest {
157+
return irma.NewIssuanceRequest([]*irma.CredentialRequest{
158+
{
159+
CredentialTypeID: irma.NewCredentialTypeIdentifier("irma-demo.MijnOverheid.fullName"),
160+
Attributes: map[string]string{
161+
"firstnames": "Barry",
162+
"firstname": "",
163+
"familyname": "Batsbak",
164+
"prefix": "Sir",
165+
},
166+
},
167+
})
168+
}
169+
156170
func performCombinedIssuanceAndDisclosureSession(t *testing.T, client *irmaclient.Client, irmaServer *IrmaServer) {
157171
regularIssuanceRequest := irma.NewIssuanceRequest([]*irma.CredentialRequest{
158172
{
@@ -268,7 +282,7 @@ func testRemoveStorageWithOnlyIdemixCredentials(t *testing.T) {
268282
client := createClient(t)
269283
defer client.Close()
270284

271-
issueIdemixOnlyToClient(t, client, irmaServer)
285+
performIrmaIssuanceSession(t, client, irmaServer, createIdemixOnlyIssuanceRequest())
272286

273287
require.NoError(t, client.RemoveStorage())
274288
}
@@ -287,32 +301,55 @@ func testRemoveStorageEmptyClient(t *testing.T) {
287301
require.NoError(t, client.RemoveStorage())
288302
}
289303

290-
func testIdemixAndSdJwtCombinedRemovalLog(t *testing.T) {
291-
conf := irmaServerConfWithSdJwtEnabled(t)
292-
irmaServer := StartIrmaServer(t, conf)
293-
defer irmaServer.Stop()
304+
func testIdemixOnlyCredentialRemovalLog(t *testing.T) {
305+
// This test makes sure the attributes in the log are not in incorrect order.
306+
// It solves a bug we had where the list of attributes had an incorrect order due to a (unordered) map being converted to a list.
307+
tester := func(t *testing.T) {
308+
conf := IrmaServerConfigurationWithTempStorage(t)
309+
irmaServer := StartIrmaServer(t, conf)
310+
defer irmaServer.Stop()
294311

295-
keyshareServer := testkeyshare.StartKeyshareServer(t, logger, irma.NewSchemeManagerIdentifier("test"), 0)
296-
defer keyshareServer.Stop()
312+
keyshareServer := testkeyshare.StartKeyshareServer(t, logger, irma.NewSchemeManagerIdentifier("test"), 0)
313+
defer keyshareServer.Stop()
297314

298-
client := createClient(t)
299-
defer client.Close()
315+
client := createClient(t)
316+
defer client.Close()
300317

301-
issueSdJwtAndIdemixToClient(t, client, irmaServer)
318+
performIrmaIssuanceSession(t, client, irmaServer, createMijnOverheidIssuanceRequest())
302319

303-
credentials := client.CredentialInfoList()
304-
emailCreds := collectCredentialsWithId(credentials, "test.test.email")
320+
credentials := client.CredentialInfoList()
321+
emailCreds := collectCredentialsWithId(credentials, "irma-demo.MijnOverheid.fullName")
305322

306-
require.NoError(t, client.RemoveCredentialsByHash(hashByFormat(emailCreds)))
323+
require.NoError(t, client.RemoveCredentialsByHash(hashByFormat(emailCreds)))
307324

308-
logs, err := client.LoadNewestLogs(100)
309-
require.NoError(t, err)
325+
logs, err := client.LoadNewestLogs(100)
326+
require.NoError(t, err)
327+
328+
require.Equal(t, logs[0].Type, irmaclient.LogType_CredentialRemoval)
329+
removalLog := logs[0].RemovalLog
330+
331+
// one credential was removed
332+
require.Len(t, removalLog.Credentials, 1)
333+
334+
credential := removalLog.Credentials[0]
335+
336+
require.Contains(t, credential.Formats, irmaclient.Format_Idemix)
337+
338+
attrs := credential.Attributes
310339

311-
requireIdemixAndSdJwtCredentialRemovalLog(t, logs[0])
340+
require.Equal(t, attrs["firstnames"], "Barry")
341+
require.Equal(t, attrs["firstname"], "")
342+
require.Equal(t, attrs["familyname"], "Batsbak")
343+
require.Equal(t, attrs["prefix"], "Sir")
344+
}
345+
346+
for range 10 {
347+
tester(t)
348+
}
312349
}
313350

314-
func testIdemixOnlyCredentialRemovalLog(t *testing.T) {
315-
conf := IrmaServerConfigurationWithTempStorage(t)
351+
func testIdemixAndSdJwtCombinedRemovalLog(t *testing.T) {
352+
conf := irmaServerConfWithSdJwtEnabled(t)
316353
irmaServer := StartIrmaServer(t, conf)
317354
defer irmaServer.Stop()
318355

@@ -322,7 +359,7 @@ func testIdemixOnlyCredentialRemovalLog(t *testing.T) {
322359
client := createClient(t)
323360
defer client.Close()
324361

325-
issueIdemixOnlyToClient(t, client, irmaServer)
362+
performIrmaIssuanceSession(t, client, irmaServer, createIdemixOnlyIssuanceRequest())
326363

327364
credentials := client.CredentialInfoList()
328365
emailCreds := collectCredentialsWithId(credentials, "test.test.email")
@@ -405,7 +442,7 @@ func testDoubleSdJwtIssuanceFailsAfterRevocationListUpdate(t *testing.T) {
405442
time.Sleep(4 * time.Second)
406443

407444
// Execute first issuance
408-
issueSdJwtAndIdemixToClient(t, client, irmaServer)
445+
performIrmaIssuanceSession(t, client, irmaServer, createIrmaIssuanceRequestWithSdJwts("test.test.email", "email"))
409446

410447
info := client.CredentialInfoList()
411448
require.Len(t, info, 3)
@@ -450,19 +487,6 @@ func testDoubleSdJwtIssuanceFailsAfterRevocationListUpdate(t *testing.T) {
450487
require.Equal(t, 10, int(*cred.InstanceCount))
451488
}
452489

453-
func requireIdemixAndSdJwtCredentialRemovalLog(t *testing.T, log irmaclient.LogInfo) {
454-
require.Equal(t, log.Type, irmaclient.LogType_CredentialRemoval)
455-
456-
credLog := log.RemovalLog.Credentials[0]
457-
458-
require.Equal(t, credLog.CredentialType, "test.test.email")
459-
require.Contains(t, credLog.Formats, irmaclient.Format_Idemix)
460-
require.Contains(t, credLog.Formats, irmaclient.Format_SdJwtVc)
461-
require.Equal(t, credLog.Attributes, map[string]string{
462-
"email": "test@gmail.com",
463-
})
464-
}
465-
466490
func requireIdemixOnlyCredentialRemovalLog(t *testing.T, log irmaclient.LogInfo) {
467491
require.Equal(t, log.Type, irmaclient.LogType_CredentialRemoval)
468492
require.Equal(t, log.RemovalLog.Credentials, []irmaclient.CredentialLog{
@@ -487,7 +511,7 @@ func testIrmaDisclosureSessionLogs(t *testing.T) {
487511
client := createClient(t)
488512
defer client.Close()
489513

490-
issueIdemixOnlyToClient(t, client, irmaServer)
514+
performIrmaIssuanceSession(t, client, irmaServer, createIdemixOnlyIssuanceRequest())
491515
performIrmaDisclosureSession(t, client, irmaServer)
492516

493517
logs, err := client.LoadNewestLogs(100)
@@ -508,7 +532,7 @@ func testIrmaSignatureSessionLogs(t *testing.T) {
508532
client := createClient(t)
509533
defer client.Close()
510534

511-
issueIdemixOnlyToClient(t, client, irmaServer)
535+
performIrmaIssuanceSession(t, client, irmaServer, createIdemixOnlyIssuanceRequest())
512536
performIrmaSignatureSession(t, client, irmaServer)
513537

514538
logs, err := client.LoadNewestLogs(100)
@@ -565,7 +589,7 @@ func testEudiSessionLogs(t *testing.T) {
565589
// only keyshare enrollment log should be there
566590
require.Len(t, logs, 1)
567591

568-
issueSdJwtAndIdemixToClient(t, client, irmaServer)
592+
performIrmaIssuanceSession(t, client, irmaServer, createIrmaIssuanceRequestWithSdJwts("test.test.email", "email"))
569593

570594
logs, err = client.LoadNewestLogs(100)
571595
require.NoError(t, err)
@@ -636,7 +660,7 @@ func testDeletingCombinedCredentialDeletesBothFormats(t *testing.T) {
636660
client := createClient(t)
637661
defer client.Close()
638662

639-
issueSdJwtAndIdemixToClient(t, client, irmaServer)
663+
performIrmaIssuanceSession(t, client, irmaServer, createIrmaIssuanceRequestWithSdJwts("test.test.email", "email"))
640664

641665
credentialInfoList := client.CredentialInfoList()
642666
require.Len(t, credentialInfoList, 3)
@@ -661,7 +685,7 @@ func testIdemixAndSdJwtShowUpAsSeparateCredentialInfos(t *testing.T) {
661685
client := createClient(t)
662686
defer client.Close()
663687

664-
issueSdJwtAndIdemixToClient(t, client, irmaServer)
688+
performIrmaIssuanceSession(t, client, irmaServer, createIrmaIssuanceRequestWithSdJwts("test.test.email", "email"))
665689

666690
credentialInfoList := client.CredentialInfoList()
667691
require.Len(t, credentialInfoList, 3)
@@ -681,7 +705,7 @@ func testIdemixAndSdJwtCombinedIssuance(t *testing.T) {
681705
client := createClient(t)
682706
defer client.Close()
683707

684-
issueSdJwtAndIdemixToClient(t, client, irmaServer)
708+
performIrmaIssuanceSession(t, client, irmaServer, createIrmaIssuanceRequestWithSdJwts("test.test.email", "email"))
685709
}
686710

687711
func testDiscloseOverOpenID4VP(t *testing.T) {
@@ -695,7 +719,7 @@ func testDiscloseOverOpenID4VP(t *testing.T) {
695719
client := createClient(t)
696720
defer client.Close()
697721

698-
issueSdJwtAndIdemixToClient(t, client, irmaServer)
722+
performIrmaIssuanceSession(t, client, irmaServer, createIrmaIssuanceRequestWithSdJwts("test.test.email", "email"))
699723
discloseOverOpenID4VP(t, client, testdata.OpenID4VP_DirectPost_Host)
700724
discloseOverOpenID4VP(t, client, testdata.OpenID4VP_DirectPostJwt_Host)
701725
}
@@ -730,35 +754,15 @@ func discloseOverOpenID4VP(t *testing.T, client *irmaclient.Client, openid4vpHos
730754
require.True(t, sessionHandler.AwaitSessionEnd())
731755
}
732756

733-
func issueIdemixOnlyToClient(t *testing.T, client *irmaclient.Client, irmaServer *IrmaServer) {
734-
req := irma.NewIssuanceRequest([]*irma.CredentialRequest{
757+
func createIdemixOnlyIssuanceRequest() *irma.IssuanceRequest {
758+
return irma.NewIssuanceRequest([]*irma.CredentialRequest{
735759
{
736760
CredentialTypeID: irma.NewCredentialTypeIdentifier("test.test.email"),
737761
Attributes: map[string]string{
738762
"email": "test@gmail.com",
739763
},
740764
},
741765
})
742-
session := startIrmaSessionAtServer(t, irmaServer, req)
743-
sessionHandler := irmaclient.NewMockSessionHandler(t)
744-
745-
client.NewSession(session, sessionHandler)
746-
permissionReq := sessionHandler.AwaitPermissionRequest()
747-
748-
permissionReq.PermissionHandler(true, nil)
749-
sessionHandler.AwaitSessionEnd()
750-
}
751-
752-
func issueSdJwtAndIdemixToClient(t *testing.T, client *irmaclient.Client, irmaServer *IrmaServer) {
753-
sessionReq := createIrmaIssuanceRequestWithSdJwts("test.test.email", "email")
754-
sessionRequestJson := startIrmaSessionAtServer(t, irmaServer, sessionReq)
755-
756-
sessionHandler := irmaclient.NewMockSessionHandler(t)
757-
client.NewSession(sessionRequestJson, sessionHandler)
758-
details := sessionHandler.AwaitPermissionRequest()
759-
details.PermissionHandler(true, nil)
760-
761-
require.True(t, sessionHandler.AwaitSessionEnd())
762766
}
763767

764768
func failIssueSdJwtAndIdemixToClient(t *testing.T, client *irmaclient.Client, irmaServer *IrmaServer) {

internal/sessiontest/ios_logo_path_bug_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ func test_iOSLogoPathBugEudiLogs(t *testing.T) {
3333
client, handler := createClientWithStorageAndSigner(t, storagePath, irmaConfigurationPath, signer)
3434
keyshareEnrollClient(t, client, handler)
3535

36-
issueSdJwtAndIdemixToClient(t, client, irmaServer)
36+
performIrmaIssuanceSession(t, client, irmaServer, createIrmaIssuanceRequestWithSdJwts("test.test.email", "email"))
3737
discloseOverOpenID4VP(t, client, testdata.OpenID4VP_DirectPost_Host)
3838

3939
logs, err := client.LoadNewestLogs(1)
@@ -89,7 +89,7 @@ func test_iOSLogoPathBug(t *testing.T) {
8989
client, handler := createClientWithStorageAndSigner(t, storagePath, irmaConfigurationPath, signer)
9090
keyshareEnrollClient(t, client, handler)
9191

92-
issueSdJwtAndIdemixToClient(t, client, irmaServer)
92+
performIrmaIssuanceSession(t, client, irmaServer, createIrmaIssuanceRequestWithSdJwts("test.test.email", "email"))
9393

9494
logs, err := client.LoadNewestLogs(1)
9595
require.NoError(t, err)

irmaclient/client.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ func (client *Client) RemoveCredentialsByHash(hashByFormat map[CredentialFormat]
292292
}
293293

294294
info := relevantCreds[0]
295-
logEntry, err := createRemovalLog(info.Identifier(), info.Attributes, formats)
295+
logEntry, err := createRemovalLog(client.GetIrmaConfiguration(), info.Identifier(), info.Attributes, formats)
296296
if err != nil {
297297
return fmt.Errorf("failed to create delete log: %v", err)
298298
}
@@ -301,13 +301,17 @@ func (client *Client) RemoveCredentialsByHash(hashByFormat map[CredentialFormat]
301301
}
302302

303303
func createRemovalLog(
304+
irmaConfiguration *irma.Configuration,
304305
credentialType irma.CredentialTypeIdentifier,
305306
attributes map[irma.AttributeTypeIdentifier]irma.TranslatedString,
306307
formats []CredentialFormat,
307308
) (*LogEntry, error) {
308309
attrs := []irma.TranslatedString{}
309-
for _, attr := range attributes {
310-
attrs = append(attrs, attr)
310+
311+
// loop over it in the order as defined in the scheme
312+
for _, t := range irmaConfiguration.CredentialTypes[credentialType].AttributeTypes {
313+
id := t.GetAttributeTypeIdentifier()
314+
attrs = append(attrs, attributes[id])
311315
}
312316

313317
return &LogEntry{

version.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@
55
package irma
66

77
// Version of the IRMA command line and libraries
8-
const Version = "0.19.0"
8+
const Version = "0.19.1"

0 commit comments

Comments
 (0)