JWT: Add support for assigning org roles (#54277)
* feat: allow jwt role to be set * chore: update documentation * fix: cr suggestions * fix: lint issues * respect org auto assign and default org ID * add server admin to devenv Co-authored-by: jguer <joao.guerreiro@grafana.com>
This commit is contained in:
co-authored by
jguer
parent
4825707853
commit
9e704fec3c
@@ -5,6 +5,7 @@ import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/org"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
@@ -14,6 +15,7 @@ import (
|
||||
)
|
||||
|
||||
func TestMiddlewareJWTAuth(t *testing.T) {
|
||||
const myEmail = "vladimir@example.com"
|
||||
const id int64 = 12
|
||||
const orgID int64 = 2
|
||||
|
||||
@@ -34,6 +36,19 @@ func TestMiddlewareJWTAuth(t *testing.T) {
|
||||
cfg.JWTAuthAutoSignUp = true
|
||||
}
|
||||
|
||||
configureRole := func(cfg *setting.Cfg) {
|
||||
cfg.JWTAuthEmailClaim = "sub"
|
||||
cfg.JWTAuthRoleAttributePath = "role"
|
||||
}
|
||||
|
||||
configureRoleStrict := func(cfg *setting.Cfg) {
|
||||
cfg.JWTAuthRoleAttributeStrict = true
|
||||
}
|
||||
|
||||
configureRoleAllowAdmin := func(cfg *setting.Cfg) {
|
||||
cfg.JWTAuthAllowAssignGrafanaAdmin = true
|
||||
}
|
||||
|
||||
token := "some-token"
|
||||
|
||||
middlewareScenario(t, "Valid token with valid login claim", func(t *testing.T, sc *scenarioContext) {
|
||||
@@ -58,7 +73,6 @@ func TestMiddlewareJWTAuth(t *testing.T) {
|
||||
}, configure, configureUsernameClaim)
|
||||
|
||||
middlewareScenario(t, "Valid token with valid email claim", func(t *testing.T, sc *scenarioContext) {
|
||||
myEmail := "vladimir@example.com"
|
||||
var verifiedToken string
|
||||
sc.jwtAuthService.VerifyProvider = func(ctx context.Context, token string) (models.JWTClaims, error) {
|
||||
verifiedToken = token
|
||||
@@ -79,7 +93,6 @@ func TestMiddlewareJWTAuth(t *testing.T) {
|
||||
}, configure, configureEmailClaim)
|
||||
|
||||
middlewareScenario(t, "Valid token with no user and auto_sign_up disabled", func(t *testing.T, sc *scenarioContext) {
|
||||
myEmail := "vladimir@example.com"
|
||||
var verifiedToken string
|
||||
sc.jwtAuthService.VerifyProvider = func(ctx context.Context, token string) (models.JWTClaims, error) {
|
||||
verifiedToken = token
|
||||
@@ -98,7 +111,6 @@ func TestMiddlewareJWTAuth(t *testing.T) {
|
||||
}, configure, configureEmailClaim)
|
||||
|
||||
middlewareScenario(t, "Valid token with no user and auto_sign_up enabled", func(t *testing.T, sc *scenarioContext) {
|
||||
myEmail := "vladimir@example.com"
|
||||
var verifiedToken string
|
||||
sc.jwtAuthService.VerifyProvider = func(ctx context.Context, token string) (models.JWTClaims, error) {
|
||||
verifiedToken = token
|
||||
@@ -151,6 +163,97 @@ func TestMiddlewareJWTAuth(t *testing.T) {
|
||||
assert.Equal(t, contexthandler.InvalidJWT, sc.respJson["message"])
|
||||
}, configure, configureEmailClaim)
|
||||
|
||||
middlewareScenario(t, "Valid token with role", func(t *testing.T, sc *scenarioContext) {
|
||||
var verifiedToken string
|
||||
sc.jwtAuthService.VerifyProvider = func(ctx context.Context, token string) (models.JWTClaims, error) {
|
||||
verifiedToken = token
|
||||
return models.JWTClaims{
|
||||
"sub": myEmail,
|
||||
"role": "Editor",
|
||||
}, nil
|
||||
}
|
||||
sc.userService.ExpectedSignedInUser = &user.SignedInUser{UserID: id, OrgID: orgID, Email: myEmail, OrgRole: org.RoleEditor}
|
||||
|
||||
sc.fakeReq("GET", "/").withJWTAuthHeader(token).exec()
|
||||
assert.Equal(t, verifiedToken, token)
|
||||
assert.Equal(t, 200, sc.resp.Code)
|
||||
assert.True(t, sc.context.IsSignedIn)
|
||||
assert.Equal(t, org.RoleEditor, sc.context.OrgRole)
|
||||
}, configure, configureAutoSignUp, configureRole)
|
||||
|
||||
middlewareScenario(t, "Valid token with invalid role", func(t *testing.T, sc *scenarioContext) {
|
||||
var verifiedToken string
|
||||
sc.jwtAuthService.VerifyProvider = func(ctx context.Context, token string) (models.JWTClaims, error) {
|
||||
verifiedToken = token
|
||||
return models.JWTClaims{
|
||||
"sub": myEmail,
|
||||
"role": "test",
|
||||
}, nil
|
||||
}
|
||||
sc.userService.ExpectedSignedInUser = &user.SignedInUser{UserID: id, OrgID: orgID, Email: myEmail, OrgRole: org.RoleViewer}
|
||||
|
||||
sc.fakeReq("GET", "/").withJWTAuthHeader(token).exec()
|
||||
assert.Equal(t, verifiedToken, token)
|
||||
assert.Equal(t, 200, sc.resp.Code)
|
||||
assert.True(t, sc.context.IsSignedIn)
|
||||
assert.Equal(t, org.RoleViewer, sc.context.OrgRole)
|
||||
}, configure, configureAutoSignUp, configureRole)
|
||||
|
||||
middlewareScenario(t, "Valid token with invalid role in strict mode", func(t *testing.T, sc *scenarioContext) {
|
||||
var verifiedToken string
|
||||
sc.jwtAuthService.VerifyProvider = func(ctx context.Context, token string) (models.JWTClaims, error) {
|
||||
verifiedToken = token
|
||||
return models.JWTClaims{
|
||||
"sub": myEmail,
|
||||
"role": "test",
|
||||
}, nil
|
||||
}
|
||||
sc.userService.ExpectedSignedInUser = &user.SignedInUser{UserID: id, OrgID: orgID, Email: myEmail, OrgRole: org.RoleViewer}
|
||||
|
||||
sc.fakeReq("GET", "/").withJWTAuthHeader(token).exec()
|
||||
assert.Equal(t, verifiedToken, token)
|
||||
assert.Equal(t, 403, sc.resp.Code)
|
||||
assert.Equal(t, contexthandler.InvalidRole, sc.respJson["message"])
|
||||
}, configure, configureAutoSignUp, configureRole, configureRoleStrict)
|
||||
|
||||
middlewareScenario(t, "Valid token with grafana admin role not allowed", func(t *testing.T, sc *scenarioContext) {
|
||||
var verifiedToken string
|
||||
sc.jwtAuthService.VerifyProvider = func(ctx context.Context, token string) (models.JWTClaims, error) {
|
||||
verifiedToken = token
|
||||
return models.JWTClaims{
|
||||
"sub": myEmail,
|
||||
"role": "GrafanaAdmin",
|
||||
}, nil
|
||||
}
|
||||
sc.userService.ExpectedSignedInUser = &user.SignedInUser{UserID: id, OrgID: orgID, Email: myEmail, OrgRole: org.RoleAdmin}
|
||||
|
||||
sc.fakeReq("GET", "/").withJWTAuthHeader(token).exec()
|
||||
assert.Equal(t, verifiedToken, token)
|
||||
assert.Equal(t, 200, sc.resp.Code)
|
||||
assert.True(t, sc.context.IsSignedIn)
|
||||
assert.Equal(t, org.RoleAdmin, sc.context.OrgRole)
|
||||
assert.False(t, sc.context.IsGrafanaAdmin)
|
||||
}, configure, configureAutoSignUp, configureRole)
|
||||
|
||||
middlewareScenario(t, "Valid token with grafana admin role allowed", func(t *testing.T, sc *scenarioContext) {
|
||||
var verifiedToken string
|
||||
sc.jwtAuthService.VerifyProvider = func(ctx context.Context, token string) (models.JWTClaims, error) {
|
||||
verifiedToken = token
|
||||
return models.JWTClaims{
|
||||
"sub": myEmail,
|
||||
"role": "GrafanaAdmin",
|
||||
}, nil
|
||||
}
|
||||
sc.userService.ExpectedSignedInUser = &user.SignedInUser{UserID: id, OrgID: orgID, Email: myEmail, OrgRole: org.RoleAdmin, IsGrafanaAdmin: true}
|
||||
|
||||
sc.fakeReq("GET", "/").withJWTAuthHeader(token).exec()
|
||||
assert.Equal(t, verifiedToken, token)
|
||||
assert.Equal(t, 200, sc.resp.Code)
|
||||
assert.True(t, sc.context.IsSignedIn)
|
||||
assert.Equal(t, org.RoleAdmin, sc.context.OrgRole)
|
||||
assert.True(t, sc.context.IsGrafanaAdmin)
|
||||
}, configure, configureAutoSignUp, configureRole, configureRoleAllowAdmin)
|
||||
|
||||
middlewareScenario(t, "Invalid token", func(t *testing.T, sc *scenarioContext) {
|
||||
var verifiedToken string
|
||||
sc.jwtAuthService.VerifyProvider = func(ctx context.Context, token string) (models.JWTClaims, error) {
|
||||
|
||||
Reference in New Issue
Block a user