Oauth: Display friendly error message when role_attribute_strict=true and no valid role found (#57818)
* Oauth: change error type to a struct that unwraps into a social error * Oauth: Handle empty role in error and fix unwrap * Oauth: provide more informatio in error * Oauth: return InvalidBasicRoleError * Oauth: Fix tests * Login: Remove casing * Oath: Change to warning logs
This commit is contained in:
+1
-1
@@ -353,7 +353,7 @@ func (hs *HTTPServer) trySetEncryptedCookie(ctx *models.ReqContext, cookieName s
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (hs *HTTPServer) redirectWithError(ctx *models.ReqContext, err error, v ...interface{}) {
|
func (hs *HTTPServer) redirectWithError(ctx *models.ReqContext, err error, v ...interface{}) {
|
||||||
ctx.Logger.Error(err.Error(), v...)
|
ctx.Logger.Warn(err.Error(), v...)
|
||||||
if err := hs.trySetEncryptedCookie(ctx, loginErrorCookieName, getLoginExternalError(err), 60); err != nil {
|
if err := hs.trySetEncryptedCookie(ctx, loginErrorCookieName, getLoginExternalError(err), 60); err != nil {
|
||||||
hs.log.Error("Failed to set encrypted cookie", "err", err)
|
hs.log.Error("Failed to set encrypted cookie", "err", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ func (s *SocialAzureAD) UserInfo(client *http.Client, token *oauth2.Token) (*Bas
|
|||||||
|
|
||||||
role, grafanaAdmin := s.extractRoleAndAdmin(&claims)
|
role, grafanaAdmin := s.extractRoleAndAdmin(&claims)
|
||||||
if s.roleAttributeStrict && !role.IsValid() {
|
if s.roleAttributeStrict && !role.IsValid() {
|
||||||
return nil, ErrInvalidBasicRole
|
return nil, &InvalidBasicRoleError{idP: "Azure", assignedRole: string(role)}
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Debug("AzureAD OAuth: extracted role", "email", email, "role", role)
|
logger.Debug("AzureAD OAuth: extracted role", "email", email, "role", role)
|
||||||
|
|||||||
@@ -1,9 +1,30 @@
|
|||||||
package social
|
package social
|
||||||
|
|
||||||
import "errors"
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrIDTokenNotFound = errors.New("id_token not found")
|
ErrIDTokenNotFound = errors.New("id_token not found")
|
||||||
ErrInvalidBasicRole = errors.New("user does not have a valid basic role")
|
ErrEmailNotFound = errors.New("error getting user info: no email found in access token")
|
||||||
ErrEmailNotFound = errors.New("error getting user info: no email found in access token")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type InvalidBasicRoleError struct {
|
||||||
|
idP string
|
||||||
|
assignedRole string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *InvalidBasicRoleError) Error() string {
|
||||||
|
withFallback := func(v, fallback string) string {
|
||||||
|
if v == "" {
|
||||||
|
return fallback
|
||||||
|
}
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("Integration requires a valid org role assigned in %s. Assigned role: %s", withFallback(e.idP, "idP"), withFallback(e.assignedRole, "\" \""))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *InvalidBasicRoleError) Unwrap() error {
|
||||||
|
return &Error{e.Error()}
|
||||||
|
}
|
||||||
|
|||||||
@@ -169,7 +169,7 @@ func (s *SocialGenericOAuth) UserInfo(client *http.Client, token *oauth2.Token)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if s.roleAttributeStrict && !userInfo.Role.IsValid() {
|
if s.roleAttributeStrict && !userInfo.Role.IsValid() {
|
||||||
return nil, ErrInvalidBasicRole
|
return nil, &InvalidBasicRoleError{assignedRole: string(userInfo.Role)}
|
||||||
}
|
}
|
||||||
|
|
||||||
if userInfo.Email == "" {
|
if userInfo.Email == "" {
|
||||||
|
|||||||
@@ -203,7 +203,7 @@ func (s *SocialGithub) UserInfo(client *http.Client, token *oauth2.Token) (*Basi
|
|||||||
|
|
||||||
role, grafanaAdmin := s.extractRoleAndAdmin(response.Body, teams, true)
|
role, grafanaAdmin := s.extractRoleAndAdmin(response.Body, teams, true)
|
||||||
if s.roleAttributeStrict && !role.IsValid() {
|
if s.roleAttributeStrict && !role.IsValid() {
|
||||||
return nil, ErrInvalidBasicRole
|
return nil, &InvalidBasicRoleError{idP: "Github", assignedRole: string(role)}
|
||||||
}
|
}
|
||||||
|
|
||||||
var isGrafanaAdmin *bool = nil
|
var isGrafanaAdmin *bool = nil
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ func (s *SocialGitlab) UserInfo(client *http.Client, _ *oauth2.Token) (*BasicUse
|
|||||||
|
|
||||||
role, grafanaAdmin := s.extractRoleAndAdmin(response.Body, groups, true)
|
role, grafanaAdmin := s.extractRoleAndAdmin(response.Body, groups, true)
|
||||||
if s.roleAttributeStrict && !role.IsValid() {
|
if s.roleAttributeStrict && !role.IsValid() {
|
||||||
return nil, ErrInvalidBasicRole
|
return nil, &InvalidBasicRoleError{idP: "Gitlab", assignedRole: string(role)}
|
||||||
}
|
}
|
||||||
|
|
||||||
var isGrafanaAdmin *bool = nil
|
var isGrafanaAdmin *bool = nil
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ func TestSocialGitlab_UserInfo(t *testing.T) {
|
|||||||
UserRespBody: editorUserRespBody,
|
UserRespBody: editorUserRespBody,
|
||||||
GroupsRespBody: "[" + strings.Join([]string{}, ",") + "]",
|
GroupsRespBody: "[" + strings.Join([]string{}, ",") + "]",
|
||||||
RoleAttributePath: gitlabAttrPath,
|
RoleAttributePath: gitlabAttrPath,
|
||||||
ExpectedError: ErrInvalidBasicRole,
|
ExpectedError: &InvalidBasicRoleError{idP: "Gitlab"},
|
||||||
},
|
},
|
||||||
{ // Edge case, no match, no strict mode and no fallback => User has an empty role
|
{ // Edge case, no match, no strict mode and no fallback => User has an empty role
|
||||||
Name: "Fallback with no default will create a user with an empty role",
|
Name: "Fallback with no default will create a user with an empty role",
|
||||||
@@ -117,7 +117,7 @@ func TestSocialGitlab_UserInfo(t *testing.T) {
|
|||||||
UserRespBody: editorUserRespBody,
|
UserRespBody: editorUserRespBody,
|
||||||
GroupsRespBody: "[" + strings.Join([]string{editorGroup}, ",") + "]",
|
GroupsRespBody: "[" + strings.Join([]string{editorGroup}, ",") + "]",
|
||||||
RoleAttributePath: "",
|
RoleAttributePath: "",
|
||||||
ExpectedError: ErrInvalidBasicRole,
|
ExpectedError: &InvalidBasicRoleError{idP: "Gitlab"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ func (s *SocialOkta) UserInfo(client *http.Client, token *oauth2.Token) (*BasicU
|
|||||||
|
|
||||||
role, grafanaAdmin := s.extractRoleAndAdmin(data.rawJSON, groups, true)
|
role, grafanaAdmin := s.extractRoleAndAdmin(data.rawJSON, groups, true)
|
||||||
if s.roleAttributeStrict && !role.IsValid() {
|
if s.roleAttributeStrict && !role.IsValid() {
|
||||||
return nil, ErrInvalidBasicRole
|
return nil, &InvalidBasicRoleError{idP: "Okta", assignedRole: string(role)}
|
||||||
}
|
}
|
||||||
|
|
||||||
var isGrafanaAdmin *bool = nil
|
var isGrafanaAdmin *bool = nil
|
||||||
|
|||||||
Reference in New Issue
Block a user