Skip to content

Commit 7af530e

Browse files
robsdedudefbiville
andauthored
Fix Kerberos and improve custom auth
* Kerberos auth requires principal for backwards compatibility * Make realm an optional field in TestKit authToken * Add missing Testkit feature flags for authentication tests * Reduce custom auth payload when sending default values Co-authored-by: Florent Biville <florent.biville@neo4j.com>
1 parent bafdae0 commit 7af530e

File tree

3 files changed

+34
-17
lines changed

3 files changed

+34
-17
lines changed

neo4j/auth_tokens.go

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ const schemeBearer = "bearer"
3232
const keyPrincipal = "principal"
3333
const keyCredentials = "credentials"
3434
const keyRealm = "realm"
35-
const keyTicket = "ticket"
35+
36+
// Deprecated: will be removed in 5.0. Use keyCredentials instead.
37+
const keyTicket = keyCredentials
3638

3739
// NoAuth generates an empty authentication token
3840
func NoAuth() AuthToken {
@@ -61,7 +63,9 @@ func KerberosAuth(ticket string) AuthToken {
6163
token := AuthToken{
6264
tokens: map[string]interface{}{
6365
keyScheme: schemeKerberos,
64-
keyTicket: ticket,
66+
// Backwards compatibility: Neo4j servers pre 4.4 require the presence of the principal.
67+
keyPrincipal: "",
68+
keyCredentials: ticket,
6569
},
6670
}
6771

@@ -72,7 +76,7 @@ func KerberosAuth(ticket string) AuthToken {
7276
func BearerAuth(token string) AuthToken {
7377
result := AuthToken{
7478
tokens: map[string]interface{}{
75-
keyScheme: schemeBearer,
79+
keyScheme: schemeBearer,
7680
keyCredentials: token,
7781
},
7882
}
@@ -83,16 +87,19 @@ func BearerAuth(token string) AuthToken {
8387
// CustomAuth generates a custom authentication token with provided parameters
8488
func CustomAuth(scheme string, username string, password string, realm string, parameters map[string]interface{}) AuthToken {
8589
tokens := map[string]interface{}{
86-
keyScheme: scheme,
87-
keyPrincipal: username,
88-
keyCredentials: password,
90+
keyScheme: scheme,
91+
keyPrincipal: username,
92+
}
93+
94+
if password != "" {
95+
tokens[keyCredentials] = password
8996
}
9097

9198
if realm != "" {
9299
tokens[keyRealm] = realm
93100
}
94101

95-
if parameters != nil {
102+
if len(parameters) > 0 {
96103
tokens["parameters"] = parameters
97104
}
98105

neo4j/auth_tokens_test.go

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -92,16 +92,20 @@ func TestKerberosAuth(t *testing.T) {
9292

9393
token := KerberosAuth(ticket)
9494

95-
if len(token.tokens) != 2 {
96-
t.Errorf("should contain 2 keys")
95+
if len(token.tokens) != 3 {
96+
t.Errorf("should contain 3 keys")
9797
}
9898

9999
if token.tokens[keyScheme] != schemeKerberos {
100100
t.Errorf("the key scheme should be 'kerberos' %v", token.tokens[keyScheme])
101101
}
102102

103-
if token.tokens[keyTicket] != ticket {
104-
t.Errorf("the key ticket was not properly set %v", token.tokens[keyTicket])
103+
if token.tokens[keyPrincipal] != "" {
104+
t.Errorf("the key principal was not properly set %v", token.tokens[keyPrincipal])
105+
}
106+
107+
if token.tokens[keyCredentials] != ticket {
108+
t.Errorf("the key ticket was not properly set %v", token.tokens[keyCredentials])
105109
}
106110
}
107111

@@ -144,8 +148,8 @@ func TestCustomAuthWithEmptyParameters(t *testing.T) {
144148

145149
token := CustomAuth(scheme, userName, password, realm, parameters)
146150

147-
if len(token.tokens) != 5 {
148-
t.Errorf("should contain 5 keys when parameters data was passed %v", len(token.tokens))
151+
if len(token.tokens) != 4 {
152+
t.Errorf("should contain 4 keys when parameters data was passed %v", len(token.tokens))
149153
}
150154

151155
if token.tokens[keyScheme] != scheme {

testkit-backend/backend.go

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -367,12 +367,16 @@ func (b *backend) handleRequest(req map[string]interface{}) {
367367
authTokenMap["credentials"].(string),
368368
realm)
369369
case "kerberos":
370-
authToken = neo4j.KerberosAuth(authTokenMap["ticket"].(string))
370+
authToken = neo4j.KerberosAuth(authTokenMap["credentials"].(string))
371371
case "bearer":
372372
authToken = neo4j.BearerAuth(authTokenMap["credentials"].(string))
373373
default:
374-
b.writeError(errors.New("Unsupported scheme"))
375-
return
374+
authToken = neo4j.CustomAuth(
375+
authTokenMap["scheme"].(string),
376+
authTokenMap["principal"].(string),
377+
authTokenMap["credentials"].(string),
378+
authTokenMap["realm"].(string),
379+
authTokenMap["parameters"].(map[string]interface{}))
376380
}
377381
// Parse URI (or rather type cast)
378382
uri := data["uri"].(string)
@@ -578,10 +582,12 @@ func (b *backend) handleRequest(req map[string]interface{}) {
578582
b.writeResponse("FeatureList", map[string]interface{}{
579583
"features": []string{
580584
"ConfHint:connection.recv_timeout_seconds",
585+
"Feature:Auth:Custom",
586+
"Feature:Auth:Bearer",
587+
"Feature:Auth:Kerberos",
581588
"Optimization:ConnectionReuse",
582589
"Optimization:ImplicitDefaultArguments",
583590
"Optimization:PullPipelining",
584-
"Feature:Auth:Bearer",
585591
},
586592
})
587593

0 commit comments

Comments
 (0)