Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion openapi/api_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ func handleAuthenticationResponse(c *gin.Context, state string, vpToken string)

sameDeviceResponse, err := getApiVerifier().AuthenticationResponse(state, rawCredentials, holder)
if err != nil {
logging.Log().Warnf("Was not able to get fullfil the authentication response. Err: %v", err)
logging.Log().Warnf("Was not able to fullfil the authentication response. Err: %v", err)
c.AbortWithStatusJSON(400, ErrorMessage{Summary: err.Error()})
return
}
Expand Down
23 changes: 19 additions & 4 deletions verifier/verifiable_credential.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package verifier

import (
"errors"
"reflect"

logging "github.com/fiware/VCVerifier/logging"
"github.com/mitchellh/mapstructure"
"golang.org/x/exp/slices"
)

// Subset of the structure of a Verifiable Credential
Expand All @@ -27,6 +29,10 @@ type CredentialSubject struct {
SubjectType string `mapstructure:"type"`
}

func optionalFields() []string {
return []string{"credentialSubject.id", "credentialSubject.type"}
}

func (vc VerifiableCredential) GetCredentialType() string {
return vc.CredentialSubject.SubjectType
}
Expand All @@ -41,6 +47,7 @@ func (vc VerifiableCredential) GetIssuer() string {

func MapVerifiableCredential(raw map[string]interface{}) (VerifiableCredential, error) {
var data MappableVerifiableCredential
var metaData mapstructure.Metadata

credentialSubjectArrayDecoder := func(from, to reflect.Type, data interface{}) (interface{}, error) {
if to != reflect.TypeOf((*CredentialSubject)(nil)).Elem() {
Expand All @@ -50,18 +57,19 @@ func MapVerifiableCredential(raw map[string]interface{}) (VerifiableCredential,
return data, nil
}
vcArray := data.([]interface{})
if len(vcArray) > 0{
if len(vcArray) > 0 {
logging.Log().Warn("Found more than one credential subject. Will only use/validate first one.")
return vcArray[0], nil
}else{
return []interface{}{},nil
} else {
return []interface{}{}, nil
}
}

config := &mapstructure.DecoderConfig{
ErrorUnused: false,
Result: &data,
ErrorUnset: true,
Metadata: &metaData,
ErrorUnset: false,
IgnoreUntaggedFields: true,
DecodeHook: credentialSubjectArrayDecoder,
}
Expand All @@ -72,5 +80,12 @@ func MapVerifiableCredential(raw map[string]interface{}) (VerifiableCredential,
if err := decoder.Decode(raw); err != nil {
return VerifiableCredential{}, err
}

for _, unsetField := range metaData.Unset {
if !slices.Contains(optionalFields(), unsetField) {
return VerifiableCredential{}, errors.New("unset_field")
}
}

return VerifiableCredential{data, raw}, nil
}
62 changes: 59 additions & 3 deletions verifier/verifiable_credential_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,40 @@ var exampleCredential = map[string]interface{}{
"type": "gx:compliance",
},
}

var exampleEmptySubjectCredential = map[string]interface{}{
"@context": []string{
"https://www.w3.org/2018/credentials/v1",
"https://happypets.fiware.io/2022/credentials/employee/v1",
},
"id": "https://happypets.fiware.io/credential/25159389-8dd17b796ac0",
"type": []string{
"VerifiableCredential",
"CustomerCredential",
},
"issuer": "did:key:verifier",
"issuanceDate": "2022-11-23T15:23:13Z",
"validFrom": "2022-11-23T15:23:13Z",
"expirationDate": "2032-11-23T15:23:13Z",
"credentialSubject": map[string]interface{}{},
}

var exampleNoIdCredential = map[string]interface{}{
"@context": []string{
"https://www.w3.org/2018/credentials/v1",
"https://happypets.fiware.io/2022/credentials/employee/v1",
},
"type": []string{
"VerifiableCredential",
"CustomerCredential",
},
"issuer": "did:key:verifier",
"issuanceDate": "2022-11-23T15:23:13Z",
"validFrom": "2022-11-23T15:23:13Z",
"expirationDate": "2032-11-23T15:23:13Z",
"credentialSubject": map[string]interface{}{},
}

var exampleCredentialArraySubject = map[string]interface{}{
"@context": []string{
"https://www.w3.org/2018/credentials/v1",
Expand Down Expand Up @@ -84,7 +118,6 @@ func getComplianceVCFromJson() map[string]interface{} {
return x
}


func TestActualComplianceCredential(t *testing.T) {
_, err := MapVerifiableCredential(getComplianceVCFromJson())

Expand All @@ -105,7 +138,7 @@ func TestMapVerifiableCredential(t *testing.T) {
wantErr bool
}{
{
"ValidCertificate",
"ValidCredential",
args{exampleCredential},
VerifiableCredential{
MappableVerifiableCredential{
Expand All @@ -124,6 +157,23 @@ func TestMapVerifiableCredential(t *testing.T) {
},
false,
},
{
"ValidCredentialWithEmptySubject",
args{exampleEmptySubjectCredential},
VerifiableCredential{
MappableVerifiableCredential{
Id: "https://happypets.fiware.io/credential/25159389-8dd17b796ac0",
Types: []string{
"VerifiableCredential",
"CustomerCredential",
},
Issuer: "did:key:verifier",
CredentialSubject: CredentialSubject{},
},
exampleEmptySubjectCredential,
},
false,
},
{
"ValidCertificateArraySubject",
args{exampleCredentialArraySubject},
Expand All @@ -145,11 +195,17 @@ func TestMapVerifiableCredential(t *testing.T) {
false,
},
{
"InvalidCertificate",
"InvalidCredential",
args{map[string]interface{}{"someThing": "else"}},
VerifiableCredential{},
true,
},
{
"NoIdCredential",
args{exampleNoIdCredential},
VerifiableCredential{},
true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand Down