mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
JWT: Find login and email claims with JMESPATH (#85305)
* add function to static function to static service * find email and login claims with jmespath * rename configuration files * Replace JWTClaims struct for map * check for subclaims error
This commit is contained in:
@@ -78,10 +78,23 @@ func (s *JWT) Authenticate(ctx context.Context, r *authn.Request) (*authn.Identi
|
||||
if key := s.cfg.JWTAuth.UsernameClaim; key != "" {
|
||||
id.Login, _ = claims[key].(string)
|
||||
id.ClientParams.LookUpParams.Login = &id.Login
|
||||
} else if key := s.cfg.JWTAuth.UsernameAttributePath; key != "" {
|
||||
id.Login, err = util.SearchJSONForStringAttr(s.cfg.JWTAuth.UsernameAttributePath, claims)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
id.ClientParams.LookUpParams.Login = &id.Login
|
||||
}
|
||||
|
||||
if key := s.cfg.JWTAuth.EmailClaim; key != "" {
|
||||
id.Email, _ = claims[key].(string)
|
||||
id.ClientParams.LookUpParams.Email = &id.Email
|
||||
} else if key := s.cfg.JWTAuth.EmailAttributePath; key != "" {
|
||||
id.Email, err = util.SearchJSONForStringAttr(s.cfg.JWTAuth.EmailAttributePath, claims)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
id.ClientParams.LookUpParams.Email = &id.Email
|
||||
}
|
||||
|
||||
if name, _ := claims["name"].(string); name != "" {
|
||||
|
||||
@@ -30,7 +30,7 @@ func TestAuthenticateJWT(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
wantID *authn.Identity
|
||||
verifyProvider func(context.Context, string) (jwt.JWTClaims, error)
|
||||
verifyProvider func(context.Context, string) (map[string]any, error)
|
||||
cfg *setting.Cfg
|
||||
}{
|
||||
{
|
||||
@@ -63,8 +63,8 @@ func TestAuthenticateJWT(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
verifyProvider: func(context.Context, string) (jwt.JWTClaims, error) {
|
||||
return jwt.JWTClaims{
|
||||
verifyProvider: func(context.Context, string) (map[string]any, error) {
|
||||
return map[string]any{
|
||||
"sub": "1234567890",
|
||||
"email": "eai.doe@cor.po",
|
||||
"preferred_username": "eai-doe",
|
||||
@@ -117,8 +117,8 @@ func TestAuthenticateJWT(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
verifyProvider: func(context.Context, string) (jwt.JWTClaims, error) {
|
||||
return jwt.JWTClaims{
|
||||
verifyProvider: func(context.Context, string) (map[string]any, error) {
|
||||
return map[string]any{
|
||||
"sub": "1234567890",
|
||||
"email": "eai.doe@cor.po",
|
||||
"preferred_username": "eai-doe",
|
||||
@@ -171,8 +171,8 @@ func TestAuthenticateJWT(t *testing.T) {
|
||||
func TestJWTClaimConfig(t *testing.T) {
|
||||
t.Parallel()
|
||||
jwtService := &jwt.FakeJWTService{
|
||||
VerifyProvider: func(context.Context, string) (jwt.JWTClaims, error) {
|
||||
return jwt.JWTClaims{
|
||||
VerifyProvider: func(context.Context, string) (map[string]any, error) {
|
||||
return map[string]any{
|
||||
"sub": "1234567890",
|
||||
"email": "eai.doe@cor.po",
|
||||
"preferred_username": "eai-doe",
|
||||
@@ -399,8 +399,8 @@ func TestJWTTest(t *testing.T) {
|
||||
func TestJWTStripParam(t *testing.T) {
|
||||
t.Parallel()
|
||||
jwtService := &jwt.FakeJWTService{
|
||||
VerifyProvider: func(context.Context, string) (jwt.JWTClaims, error) {
|
||||
return jwt.JWTClaims{
|
||||
VerifyProvider: func(context.Context, string) (map[string]any, error) {
|
||||
return map[string]any{
|
||||
"sub": "1234567890",
|
||||
"email": "eai.doe@cor.po",
|
||||
"preferred_username": "eai-doe",
|
||||
@@ -442,3 +442,61 @@ func TestJWTStripParam(t *testing.T) {
|
||||
// auth_token should be removed from the query string
|
||||
assert.Equal(t, "other_param=other_value", httpReq.URL.RawQuery)
|
||||
}
|
||||
|
||||
func TestJWTSubClaimsConfig(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// #nosec G101 -- This is a dummy/test token
|
||||
token := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ2ZXIiOiIxLjAiLCJpc3MiOiJodHRwczovL2F6dXJlZG9tYWlubmFtZS5iMmNsb2dpbi5jb20vNjIwYjI2MzQtYmI4OC00MzdiLTgwYWQtYWM0YTkwZGZkZTkxL3YyLjAvIiwic3ViIjoiOWI4OTg5MDgtMWFlYy00NDc1LTljNDgtNzg1MWQyNjVkZGIxIiwiYXVkIjoiYmEyNzM0NDktMmZiNS00YTRhLTlmODItYTA2MTRhM2MxODQ1IiwiZXhwIjoxNzExNTYwMDcxLCJub25jZSI6ImRlZmF1bHROb25jZSIsImlhdCI6MTcxMTU1NjQ3MSwiYXV0aF90aW1lIjoxNzExNTU2NDcxLCJuYW1lIjoibmFtZV9vZl90aGVfdXNlciIsImdpdmVuX25hbWUiOiJVc2VyTmFtZSIsImZhbWlseV9uYW1lIjoiVXNlclN1cm5hbWUiLCJlbWFpbHMiOlsibWFpbmVtYWlsK2V4dHJhZW1haWwwNUBnbWFpbC5jb20iLCJtYWluZW1haWwrZXh0cmFlbWFpbDA0QGdtYWlsLmNvbSIsIm1haW5lbWFpbCtleHRyYWVtYWlsMDNAZ21haWwuY29tIiwibWFpbmVtYWlsK2V4dHJhZW1haWwwMkBnbWFpbC5jb20iLCJtYWluZW1haWwrZXh0cmFlbWFpbDAxQGdtYWlsLmNvbSIsIm1haW5lbWFpbEBnbWFpbC5jb20iXSwidGZwIjoiQjJDXzFfdXNlcmZsb3ciLCJuYmYiOjE3MTE1NTY0NzF9.qpN3upxUB5CTJ7kmYPHFuhlwG95vdQqJaDDC_8KJFZ8"
|
||||
jwtHeaderName := "X-Forwarded-User"
|
||||
response := map[string]any{
|
||||
"ver": "1.0",
|
||||
"iss": "https://azuredomainname.b2clogin.com/620b2634-bb88-437b-80ad-ac4a90dfde91/v2.0/",
|
||||
"sub": "9b898908-1aec-4475-9c48-7851d265ddb1",
|
||||
"aud": "ba273449-2fb5-4a4a-9f82-a0614a3c1845",
|
||||
"exp": 1711560071,
|
||||
"nonce": "defaultNonce",
|
||||
"iat": 1711556471,
|
||||
"auth_time": 1711556471,
|
||||
"name": "name_of_the_user",
|
||||
"given_name": "UserName",
|
||||
"family_name": "UserSurname",
|
||||
"emails": []string{
|
||||
"mainemail+extraemail04@gmail.com",
|
||||
"mainemail+extraemail03@gmail.com",
|
||||
"mainemail+extraemail02@gmail.com",
|
||||
"mainemail+extraemail01@gmail.com",
|
||||
"mainemail@gmail.com",
|
||||
},
|
||||
"tfp": "B2C_1_userflow",
|
||||
"nbf": 1711556471,
|
||||
}
|
||||
cfg := &setting.Cfg{
|
||||
JWTAuth: setting.AuthJWTSettings{
|
||||
HeaderName: jwtHeaderName,
|
||||
EmailAttributePath: "emails[2]",
|
||||
UsernameAttributePath: "name",
|
||||
},
|
||||
}
|
||||
httpReq := &http.Request{
|
||||
URL: &url.URL{RawQuery: "auth_token=" + token},
|
||||
Header: map[string][]string{
|
||||
jwtHeaderName: {token}},
|
||||
}
|
||||
jwtService := &jwt.FakeJWTService{
|
||||
VerifyProvider: func(context.Context, string) (map[string]any, error) {
|
||||
return response, nil
|
||||
},
|
||||
}
|
||||
|
||||
jwtClient := ProvideJWT(jwtService, cfg)
|
||||
identity, err := jwtClient.Authenticate(context.Background(), &authn.Request{
|
||||
OrgID: 1,
|
||||
HTTPRequest: httpReq,
|
||||
Resp: nil,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "mainemail+extraemail02@gmail.com", identity.Email)
|
||||
require.Equal(t, "name_of_the_user", identity.Name)
|
||||
fmt.Println("identity.Email", identity.Email)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user