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:
Karl Persson 2022-10-31 09:11:31 +01:00 committed by GitHub
parent 89d917b196
commit 052d1426f9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 33 additions and 12 deletions

View File

@ -353,7 +353,7 @@ func (hs *HTTPServer) trySetEncryptedCookie(ctx *models.ReqContext, cookieName s
}
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 {
hs.log.Error("Failed to set encrypted cookie", "err", err)
}

View File

@ -72,7 +72,7 @@ func (s *SocialAzureAD) UserInfo(client *http.Client, token *oauth2.Token) (*Bas
role, grafanaAdmin := s.extractRoleAndAdmin(&claims)
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)

View File

@ -1,9 +1,30 @@
package social
import "errors"
import (
"errors"
"fmt"
)
var (
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")
ErrIDTokenNotFound = errors.New("id_token not found")
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()}
}

View File

@ -169,7 +169,7 @@ func (s *SocialGenericOAuth) UserInfo(client *http.Client, token *oauth2.Token)
}
if s.roleAttributeStrict && !userInfo.Role.IsValid() {
return nil, ErrInvalidBasicRole
return nil, &InvalidBasicRoleError{assignedRole: string(userInfo.Role)}
}
if userInfo.Email == "" {

View File

@ -203,7 +203,7 @@ func (s *SocialGithub) UserInfo(client *http.Client, token *oauth2.Token) (*Basi
role, grafanaAdmin := s.extractRoleAndAdmin(response.Body, teams, true)
if s.roleAttributeStrict && !role.IsValid() {
return nil, ErrInvalidBasicRole
return nil, &InvalidBasicRoleError{idP: "Github", assignedRole: string(role)}
}
var isGrafanaAdmin *bool = nil

View File

@ -115,7 +115,7 @@ func (s *SocialGitlab) UserInfo(client *http.Client, _ *oauth2.Token) (*BasicUse
role, grafanaAdmin := s.extractRoleAndAdmin(response.Body, groups, true)
if s.roleAttributeStrict && !role.IsValid() {
return nil, ErrInvalidBasicRole
return nil, &InvalidBasicRoleError{idP: "Gitlab", assignedRole: string(role)}
}
var isGrafanaAdmin *bool = nil

View File

@ -99,7 +99,7 @@ func TestSocialGitlab_UserInfo(t *testing.T) {
UserRespBody: editorUserRespBody,
GroupsRespBody: "[" + strings.Join([]string{}, ",") + "]",
RoleAttributePath: gitlabAttrPath,
ExpectedError: ErrInvalidBasicRole,
ExpectedError: &InvalidBasicRoleError{idP: "Gitlab"},
},
{ // 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",
@ -117,7 +117,7 @@ func TestSocialGitlab_UserInfo(t *testing.T) {
UserRespBody: editorUserRespBody,
GroupsRespBody: "[" + strings.Join([]string{editorGroup}, ",") + "]",
RoleAttributePath: "",
ExpectedError: ErrInvalidBasicRole,
ExpectedError: &InvalidBasicRoleError{idP: "Gitlab"},
},
}

View File

@ -82,7 +82,7 @@ func (s *SocialOkta) UserInfo(client *http.Client, token *oauth2.Token) (*BasicU
role, grafanaAdmin := s.extractRoleAndAdmin(data.rawJSON, groups, true)
if s.roleAttributeStrict && !role.IsValid() {
return nil, ErrInvalidBasicRole
return nil, &InvalidBasicRoleError{idP: "Okta", assignedRole: string(role)}
}
var isGrafanaAdmin *bool = nil