Auth: Add sub claim check to JWT Auth pre-checks (#61417)
* Auth: Add sub claim check to JWT Auth pre-checks * Add #nosec annotation to the test tokens
This commit is contained in:
@@ -11,6 +11,7 @@ import (
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/services/auth"
|
||||
authJWT "github.com/grafana/grafana/pkg/services/auth/jwt"
|
||||
"github.com/grafana/grafana/pkg/services/authn"
|
||||
"github.com/grafana/grafana/pkg/services/login"
|
||||
"github.com/grafana/grafana/pkg/services/org"
|
||||
@@ -143,21 +144,14 @@ func (s *JWT) Test(ctx context.Context, r *authn.Request) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// The header is Authorization and the token does not look like a JWT,
|
||||
// this is likely an API key. Pass it on.
|
||||
if s.cfg.JWTAuthHeaderName == "Authorization" && !looksLikeJWT(jwtToken) {
|
||||
// If the "sub" claim is missing or empty then pass the control to the next handler
|
||||
if !authJWT.HasSubClaim(jwtToken) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func looksLikeJWT(token string) bool {
|
||||
// A JWT must have 3 parts separated by `.`.
|
||||
parts := strings.Split(token, ".")
|
||||
return len(parts) == 3
|
||||
}
|
||||
|
||||
const roleGrafanaAdmin = "GrafanaAdmin"
|
||||
|
||||
func (s *JWT) extractRoleAndAdmin(claims map[string]interface{}) (org.RoleType, bool) {
|
||||
|
||||
@@ -7,12 +7,13 @@ import (
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/models/roletype"
|
||||
"github.com/grafana/grafana/pkg/services/authn"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func stringPtr(s string) *string {
|
||||
@@ -87,8 +88,13 @@ func TestAuthenticateJWT(t *testing.T) {
|
||||
func TestJWTTest(t *testing.T) {
|
||||
jwtService := &models.FakeJWTService{}
|
||||
jwtHeaderName := "X-Forwarded-User"
|
||||
validFormatToken := "sample.token.valid"
|
||||
// #nosec G101 -- This is dummy/test token
|
||||
validFormatToken := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.XbPfbIHMI6arZ3Y922BhjWgQzWXcXNrz0ogtVhfEd2o"
|
||||
invalidFormatToken := "sampletokeninvalid"
|
||||
// #nosec G101 -- This is dummy/test token
|
||||
missingSubToken := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiSm9obiBEb2UiLCJpYXQiOjE1MTYyMzkwMjJ9.8nYFUX869Y1mnDDDU4yL11aANgVRuifoxrE8BHZY1iE"
|
||||
// #nosec G101 -- This is dummy/test token
|
||||
emptySubToken := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiSm9obiBEb2UiLCJzdWIiOiIiLCJpYXQiOjE1MTYyMzkwMjJ9.tnwtOHK58d47dO4DHW4b9MzeToxa1kGiko5Oo887Rqc"
|
||||
|
||||
type testCase struct {
|
||||
desc string
|
||||
@@ -144,6 +150,20 @@ func TestJWTTest(t *testing.T) {
|
||||
token: validFormatToken,
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
desc: "token without a sub claim",
|
||||
reqHeaderName: "Authorization",
|
||||
cfgHeaderName: "Authorization",
|
||||
token: missingSubToken,
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
desc: "token with an empty sub claim",
|
||||
reqHeaderName: "Authorization",
|
||||
cfgHeaderName: "Authorization",
|
||||
token: emptySubToken,
|
||||
want: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
|
||||
Reference in New Issue
Block a user