Skip to content

Commit

Permalink
allow for registration credential if not defined in PD
Browse files Browse the repository at this point in the history
  • Loading branch information
woutslakhorst committed Sep 20, 2024
1 parent 303d2d5 commit 084d94f
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 28 deletions.
17 changes: 15 additions & 2 deletions discovery/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,9 +220,9 @@ func (r *defaultClientRegistrationManager) findCredentialsAndBuildPresentation(c
if err != nil {
return nil, err
}
// add registration params as credential
var registrationCredential vc.VerifiableCredential
if len(parameters) > 0 {
registrationCredential := vc.VerifiableCredential{
registrationCredential = vc.VerifiableCredential{
Context: []ssi.URI{vc.VCContextV1URI(), credential.NutsV1ContextURI},
Type: []ssi.URI{vc.VerifiableCredentialTypeV1URI(), credential.DiscoveryRegistrationCredentialTypeV1URI()},
CredentialSubject: []interface{}{parameters},
Expand All @@ -235,6 +235,19 @@ func (r *defaultClientRegistrationManager) findCredentialsAndBuildPresentation(c
if err != nil {
return nil, fmt.Errorf(errStr, service.ID, subjectDID, err)
}

// add registration params as credential if not already done so by the Presentation Definition
var found bool
for _, cred := range matchingCredentials {
if cred.ID == registrationCredential.ID {
found = true
break
}
}
if !found {
matchingCredentials = append(matchingCredentials, credential.AutoCorrectSelfAttestedCredential(registrationCredential, subjectDID))
}

return r.buildPresentation(ctx, subjectDID, service, matchingCredentials, nil)
}

Expand Down
6 changes: 5 additions & 1 deletion discovery/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,11 @@ func Test_defaultClientRegistrationManager_activate(t *testing.T) {
mockVCR := vcr.NewMockVCR(ctrl)
wallet := holder.NewMockWallet(ctrl)
wallet.EXPECT().List(gomock.Any(), gomock.Any()).Return(nil, nil)
wallet.EXPECT().BuildPresentation(gomock.Any(), []vc.VerifiableCredential{}, gomock.Any(), gomock.Any(), false).Return(&vpAlice, nil)
wallet.EXPECT().BuildPresentation(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), false).DoAndReturn(func(_ interface{}, credentials []vc.VerifiableCredential, _ interface{}, _ interface{}, _ interface{}) (*vc.VerifiablePresentation, error) {
// expect registration credential
assert.Len(t, credentials, 1)
return &vpAlice, nil
})
mockVCR.EXPECT().Wallet().Return(wallet).AnyTimes()
mockSubjectManager := didsubject.NewMockSubjectManager(ctrl)
mockSubjectManager.EXPECT().ListDIDs(gomock.Any(), aliceSubject).Return([]did.DID{aliceDID}, nil)
Expand Down
21 changes: 21 additions & 0 deletions discovery/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -258,13 +258,34 @@ func (m *Module) validateRegistration(definition ServiceDefinition, presentation
return errPresentationValidityExceedsCredentials
}
}

// VP must fulfill the PEX Presentation ServiceDefinition
// We don't have a PresentationSubmission, so we can't use Validate().
creds, _, err := definition.PresentationDefinition.Match(presentation.VerifiableCredential)
if err != nil {
return fmt.Errorf("verifiable presentation doesn't match required presentation definition: %w", err)
}
if len(creds) != len(presentation.VerifiableCredential) {
// it could be the case that the VP contains a registration credential and the matching credentials do not.
// only return errPresentationDoesNotFulfillDefinition if both contain the registration credential or neither do.
vpContainsRegistrationCredential := false
for _, cred := range presentation.VerifiableCredential {
if slices.Contains(cred.Type, credential.DiscoveryRegistrationCredentialTypeV1URI()) {
vpContainsRegistrationCredential = true
break
}
}
matchingContainsRegistrationCredential := false
for _, cred := range creds {
if slices.Contains(cred.Type, credential.DiscoveryRegistrationCredentialTypeV1URI()) {
matchingContainsRegistrationCredential = true
break
}
}
if vpContainsRegistrationCredential && !matchingContainsRegistrationCredential && len(presentation.VerifiableCredential)-len(creds) == 1 {
return nil
}

return errPresentationDoesNotFulfillDefinition
}
return nil
Expand Down
4 changes: 1 addition & 3 deletions discovery/module_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -423,9 +423,7 @@ func TestModule_Search(t *testing.T) {
{
Presentation: vpAlice,
Fields: map[string]interface{}{
"auth_server_url_field": "https://example.com/oauth2/alice",
"issuer_field": authorityDID,
"type_field": []string{vc.VerifiableCredentialType, credential.DiscoveryRegistrationCredentialType},
"issuer_field": authorityDID,
},
Parameters: defaultRegistrationParams(aliceSubject),
},
Expand Down
22 changes: 0 additions & 22 deletions discovery/test.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,28 +101,6 @@ func testDefinitions() map[string]ServiceDefinition {
},
},
},
{
Id: "2",
Constraints: &pe.Constraints{
Fields: []pe.Field{
{
Id: to.Ptr("auth_server_url_field"),
Path: []string{"$.credentialSubject.authServerURL", "$.credentialSubject[0].authServerURL"},
Filter: &pe.Filter{
Type: "string",
},
},
{
Id: to.Ptr("type_field"),
Path: []string{"$.type"},
Filter: &pe.Filter{
Type: "string",
Const: to.Ptr(credential.DiscoveryRegistrationCredentialType),
},
},
},
},
},
},
},
PresentationMaxValidity: int((24 * time.Hour).Seconds()),
Expand Down
8 changes: 8 additions & 0 deletions e2e-tests/discovery/run-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,14 @@ else
exitWithDockerLogs 1
fi

if echo $RESPONSE | grep -q "authServerURL"; then
echo "Authorization server URL found"
else
echo "FAILED: Could not find authServerURL" 1>&2
echo $RESPONSE
exitWithDockerLogs 1
fi

echo "------------------------------------"
echo "Stopping Docker containers..."
echo "------------------------------------"
Expand Down

0 comments on commit 084d94f

Please sign in to comment.