From 0a852a0123717784ae4b989306c52e63f4c8e550 Mon Sep 17 00:00:00 2001 From: Gerard Snaauw Date: Thu, 17 Oct 2024 12:24:55 +0200 Subject: [PATCH] fix retraction --- discovery/client.go | 1 + discovery/client_test.go | 9 ++++++++- discovery/module.go | 8 ++++++-- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/discovery/client.go b/discovery/client.go index 4ba43f3c0..09e2c6556 100644 --- a/discovery/client.go +++ b/discovery/client.go @@ -227,6 +227,7 @@ func (r *defaultClientRegistrationManager) deactivate(ctx context.Context, servi func (r *defaultClientRegistrationManager) deregisterPresentation(ctx context.Context, subjectDID did.DID, service ServiceDefinition, vp vc.VerifiablePresentation) error { presentation, err := r.buildPresentation(ctx, subjectDID, service, nil, map[string]interface{}{ "retract_jti": vp.ID.String(), + "type": []ssi.URI{vc.VerifiablePresentationTypeV1URI(), retractionPresentationType}, // this overrides the default 'type' so must include all types }) if err != nil { return err diff --git a/discovery/client_test.go b/discovery/client_test.go index 4c08cc871..5cabb6967 100644 --- a/discovery/client_test.go +++ b/discovery/client_test.go @@ -20,6 +20,7 @@ package discovery import ( "context" + "encoding/json" "errors" "github.com/lestrrat-go/jwx/v2/jwt" "github.com/nuts-foundation/go-did/did" @@ -220,7 +221,13 @@ func Test_defaultClientRegistrationManager_deactivate(t *testing.T) { t.Run("registered", func(t *testing.T) { ctx := newTestContext(t) ctx.invoker.EXPECT().Register(gomock.Any(), gomock.Any(), gomock.Any()) - ctx.wallet.EXPECT().BuildPresentation(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), false).Return(&vpAlice, nil) + ctx.wallet.EXPECT().BuildPresentation(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), false).DoAndReturn( + func(ctx context.Context, credentials []vc.VerifiableCredential, options holder.PresentationOptions, signerDID *did.DID, validateVC bool) (*vc.VerifiablePresentation, error) { + bs, err := json.Marshal(options.ProofOptions.AdditionalProperties["type"]) + require.NoError(t, err) + assert.Contains(t, string(bs), retractionPresentationType.String()) + return &vpAlice, nil // not a revocation VP + }) ctx.subjectManager.EXPECT().ListDIDs(gomock.Any(), aliceSubject).Return([]did.DID{aliceDID}, nil) _, err := ctx.store.add(testServiceID, vpAlice, testSeed, 1) require.NoError(t, err) diff --git a/discovery/module.go b/discovery/module.go index 538b7d54a..86d5ef678 100644 --- a/discovery/module.go +++ b/discovery/module.go @@ -295,11 +295,15 @@ func (m *Module) validateRegistration(definition ServiceDefinition, presentation } func (m *Module) validateRetraction(serviceID string, presentation vc.VerifiablePresentation) error { - // Presentation might be a retraction (deletion of an earlier credentialRecord) must contain no credentials, and refer to the VP being retracted by ID. - // If those conditions aren't met, we don't need to register the retraction. + // RFC022 §3.4:it MUST specify RetractedVerifiablePresentation as type, in addition to the VerifiablePresentation. + // presentation.IsType(retractionPresentationType) // satisfied by the switch one level up + + // RFC022 §3.4: it MUST NOT contain any credentials. if len(presentation.VerifiableCredential) > 0 { return errRetractionContainsCredentials } + + // RFC022 §3.4: it MUST contain a retract_jti JWT claim, containing the jti of the presentation to retract. // Check that the retraction refers to an existing presentation. // If not, it might've already been removed due to expiry or superseded by a newer presentation. retractJTIRaw, _ := presentation.JWT().Get("retract_jti")