Skip to content

Commit 860bc6b

Browse files
authored
Merge pull request #76 from FIWARE/fix/invalid-credential-types
fix(vc): Check if the VC has valid types before generating the token
2 parents a1e1944 + dc6ac78 commit 860bc6b

3 files changed

Lines changed: 112 additions & 2 deletions

File tree

verifier/trustedissuer.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ func verifyWithCredentialsConfig(verifiableCredential *verifiable.Credential, cr
115115
for _, credentialType := range verifiableCredential.Contents().Types {
116116
config, exists := credentialsConfigMap[credentialType]
117117
if !exists {
118+
logging.Log().Warnf("The credential type %s is not allowed by the config %s.", credentialType, logging.PrettyPrintObject(credentialsConfigMap))
118119
subjectAllowed = false
119120
break
120121
}
@@ -135,9 +136,10 @@ func verifyForType(subjectToVerfiy verifiable.Subject, credentialConfig tir.Cred
135136
if claim.Path != "" {
136137
validClaim := verifyWithJsonPath(subjectToVerfiy, claim)
137138
if validClaim {
138-
logging.Log().Debugf("Claim with path %s is valid.", claim.Path)
139+
logging.Log().Debugf("Claim with path %s is valid. Credential Subject %s", claim.Path, logging.PrettyPrintObject(subjectToVerfiy))
139140
continue
140141
} else {
142+
logging.Log().Warnf("Claim with path %s is not valid.", claim.Path)
141143
return false
142144
}
143145
} else {

verifier/verifier.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ var ErrorRedirectUriMismatch = errors.New("redirect_uri_does_not_match")
6868
var ErrorVerficationContextSetup = errors.New("no_valid_verification_context")
6969
var ErrorTokenUnparsable = errors.New("unable_to_parse_token")
7070
var ErrorRequiredCredentialNotProvided = errors.New("required_credential_not_provided")
71+
var ErrorNoValidCredentialTypeProvided = errors.New("no_valid_credential_type_provided")
7172
var ErrorUnsupportedRequestMode = errors.New("unsupported_request_mode")
7273
var ErrorNoExpiration = errors.New("no_jwt_expiration_set")
7374
var ErrorNoKeyId = errors.New("no_key_id_available")
@@ -613,6 +614,14 @@ func (v *CredentialVerifier) GenerateToken(clientId, subject, audience string, s
613614
flatClaims, _ = v.credentialsConfig.GetFlatClaims(clientId, scope)
614615
}
615616
}
617+
if len(credentialsToBeIncluded) == 0 {
618+
vcTypes := []string{}
619+
for k := range credentialsByType {
620+
vcTypes = append(vcTypes, k)
621+
}
622+
logging.Log().Warnf("No valid credential type was provided. Provided credential type: %v", vcTypes)
623+
return 0, "", ErrorNoValidCredentialTypeProvided
624+
}
616625
token, err := v.generateJWT(credentialsToBeIncluded, holder, audience, flatClaims)
617626
if err != nil {
618627
logging.Log().Warnf("Was not able to create the token. Err: %v", err)
@@ -1116,7 +1125,7 @@ func (v *CredentialVerifier) generateJWT(credentials []map[string]interface{}, h
11161125
jwtBuilder.Claim("verifiablePresentation", credentials)
11171126
} else {
11181127
logging.Log().Debugf("Credentials %s", logging.PrettyPrintObject(credentials))
1119-
jwtBuilder.Claim("verifiableCredential", credentials[0])
1128+
jwtBuilder.Claim("verifiableCredential", credentials)
11201129
}
11211130

11221131
token, err := jwtBuilder.Build()

verifier/verifier_test.go

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1170,4 +1170,103 @@ func TestExtractCredentialTypes(t *testing.T) {
11701170
}
11711171
})
11721172
}
1173+
1174+
}
1175+
func TestGenerateToken(t *testing.T) {
1176+
1177+
logging.Configure(true, "DEBUG", true, []string{})
1178+
1179+
type test struct {
1180+
testName string
1181+
clientId string
1182+
subject string
1183+
audience string
1184+
scopes []string
1185+
presentation *verifiable.Presentation
1186+
credentialScopes map[string]map[string]configModel.ScopeEntry
1187+
configError error
1188+
mockTokenSignError error
1189+
expectedError error
1190+
}
1191+
1192+
testKey := getECDSAKey()
1193+
emptyPresentation, _ := verifiable.NewPresentation()
1194+
vc1, _ := verifiable.CreateCredential(verifiable.CredentialContents{
1195+
ID: "vc1",
1196+
Types: []string{"type1", "typeA"},
1197+
}, verifiable.CustomFields{})
1198+
invalidPresentation, _ := verifiable.NewPresentation(verifiable.WithCredentials(vc1))
1199+
1200+
tests := []test{
1201+
{
1202+
testName: "When presentation is empty, ErrorNoValidCredentialTypeProvided should be returned",
1203+
clientId: "test-client",
1204+
subject: "subject-id",
1205+
audience: "audience-id",
1206+
scopes: []string{"test-scope"},
1207+
presentation: emptyPresentation,
1208+
credentialScopes: map[string]map[string]configModel.ScopeEntry{},
1209+
configError: nil,
1210+
mockTokenSignError: nil,
1211+
expectedError: ErrorNoValidCredentialTypeProvided,
1212+
},
1213+
{
1214+
testName: "When presentation has not valid types, ErrorNoValidCredentialTypeProvided should be returned",
1215+
clientId: "test-client",
1216+
subject: "subject-id",
1217+
audience: "audience-id",
1218+
scopes: []string{"test-scope"},
1219+
presentation: invalidPresentation,
1220+
credentialScopes: map[string]map[string]configModel.ScopeEntry{},
1221+
configError: nil,
1222+
mockTokenSignError: nil,
1223+
expectedError: ErrorNoValidCredentialTypeProvided,
1224+
},
1225+
}
1226+
1227+
for _, tc := range tests {
1228+
t.Run(tc.testName, func(t *testing.T) {
1229+
mockConfig := mockCredentialConfig{mockScopes: tc.credentialScopes, mockError: tc.configError}
1230+
1231+
verifier := CredentialVerifier{
1232+
credentialsConfig: &mockConfig,
1233+
validationServices: []ValidationService{},
1234+
signingKey: testKey,
1235+
clock: mockClock{},
1236+
tokenSigner: mockTokenSigner{tc.mockTokenSignError},
1237+
signingAlgorithm: "ES256",
1238+
host: "https://verifier.example.com",
1239+
jwtExpiration: time.Hour,
1240+
}
1241+
1242+
expiration, tokenString, err := verifier.GenerateToken(tc.clientId, tc.subject, tc.audience, tc.scopes, tc.presentation)
1243+
1244+
if tc.expectedError != nil {
1245+
if err == nil {
1246+
t.Errorf("%s - Expected error %v but got none.", tc.testName, tc.expectedError)
1247+
return
1248+
}
1249+
if err.Error() != tc.expectedError.Error() {
1250+
t.Errorf("%s - Expected error %v but was %v.", tc.testName, tc.expectedError, err)
1251+
return
1252+
}
1253+
return
1254+
}
1255+
1256+
if err != nil {
1257+
t.Errorf("%s - Expected no error but got %v.", tc.testName, err)
1258+
return
1259+
}
1260+
1261+
if tokenString == "" {
1262+
t.Errorf("%s - Expected token string but got empty.", tc.testName)
1263+
return
1264+
}
1265+
1266+
if expiration == 0 {
1267+
t.Errorf("%s - Expected expiration but got 0.", tc.testName)
1268+
return
1269+
}
1270+
})
1271+
}
11731272
}

0 commit comments

Comments
 (0)