Fix JWT claims request (#61650)

* Fix JWT claims request

* Add test scenarios for missing config options
This commit is contained in:
linoman 2023-01-19 16:03:09 +01:00 committed by GitHub
parent f28a437eb2
commit 56c2755b3b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 113 additions and 2 deletions

View File

@ -115,10 +115,10 @@ func (s *JWT) Authenticate(ctx context.Context, r *authn.Request) (*authn.Identi
}
}
if id.Login == "" || id.Email == "" {
if id.Login == "" && id.Email == "" {
s.log.Debug("Failed to get an authentication claim from JWT",
"login", id.Login, "email", id.Email)
return nil, ErrJWTMissingClaim.Errorf("missing login or email claim in JWT")
return nil, ErrJWTMissingClaim.Errorf("missing login and email claim in JWT")
}
if s.cfg.JWTAuthAutoSignUp {

View File

@ -85,6 +85,117 @@ func TestAuthenticateJWT(t *testing.T) {
assert.EqualValues(t, wantID, id, fmt.Sprintf("%+v", id))
}
func TestJWTClaimConfig(t *testing.T) {
jwtService := &models.FakeJWTService{
VerifyProvider: func(context.Context, string) (models.JWTClaims, error) {
return models.JWTClaims{
"sub": "1234567890",
"email": "eai.doe@cor.po",
"preferred_username": "eai-doe",
"name": "Eai Doe",
"roles": "Admin",
}, nil
},
}
jwtHeaderName := "X-Forwarded-User"
cfg := &setting.Cfg{
JWTAuthEnabled: true,
JWTAuthHeaderName: jwtHeaderName,
JWTAuthAutoSignUp: true,
JWTAuthAllowAssignGrafanaAdmin: true,
JWTAuthRoleAttributeStrict: true,
JWTAuthRoleAttributePath: "roles",
}
// #nosec G101 -- This is a dummy/test token
token := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.XbPfbIHMI6arZ3Y922BhjWgQzWXcXNrz0ogtVhfEd2o"
type Dictionary map[string]interface{}
type testCase struct {
desc string
claimsConfigurations []Dictionary
valid bool
}
testCases := []testCase{
{
desc: "JWT configuration with email and username claims",
claimsConfigurations: []Dictionary{
{
"JWTAuthEmailClaim": true,
"JWTAuthUsernameClaim": true,
},
},
valid: true,
},
{
desc: "JWT configuration with email claim",
claimsConfigurations: []Dictionary{
{
"JWTAuthEmailClaim": true,
"JWTAuthUsernameClaim": false,
},
},
valid: true,
},
{
desc: "JWT configuration with username claim",
claimsConfigurations: []Dictionary{
{
"JWTAuthEmailClaim": false,
"JWTAuthUsernameClaim": true,
},
},
valid: true,
},
{
desc: "JWT configuration without email and username claims",
claimsConfigurations: []Dictionary{
{
"JWTAuthEmailClaim": false,
"JWTAuthUsernameClaim": false,
},
},
valid: false,
},
}
for _, tc := range testCases {
t.Run(tc.desc, func(t *testing.T) {
for _, claims := range tc.claimsConfigurations {
cfg.JWTAuthEmailClaim = ""
cfg.JWTAuthUsernameClaim = ""
if claims["JWTAuthEmailClaim"] == true {
cfg.JWTAuthEmailClaim = "email"
}
if claims["JWTAuthUsernameClaim"] == true {
cfg.JWTAuthUsernameClaim = "preferred_username"
}
}
})
httpReq := &http.Request{
URL: &url.URL{RawQuery: "auth_token=" + token},
Header: map[string][]string{
jwtHeaderName: {token}},
}
jwtClient := ProvideJWT(jwtService, cfg)
_, err := jwtClient.Authenticate(context.Background(), &authn.Request{
OrgID: 1,
HTTPRequest: httpReq,
Resp: nil,
})
if tc.valid {
require.NoError(t, err)
} else {
require.Error(t, err)
}
}
}
func TestJWTTest(t *testing.T) {
jwtService := &models.FakeJWTService{}
jwtHeaderName := "X-Forwarded-User"