mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
OAuth: Add optional strict parsing of role_attribute_path (#28021)
* OAuth: Add strict role mapping By default the user is assigned the role Viewer if role_attribute_path doesn't return a role, which is not always desirable. This commit adds a strict mode, which deny the user access if a role isn't returned. Fix #26626 * Update docs/sources/auth/generic-oauth.md Co-authored-by: Emil Tullstedt <emil.tullstedt@grafana.com> * Update docs/sources/auth/generic-oauth.md * Update .gitignore file with WAN * Removed WAN from .gitignore Co-authored-by: Emil Tullstedt <emil.tullstedt@grafana.com> Co-authored-by: achatterjee-grafana <70489351+achatterjee-grafana@users.noreply.github.com> Co-authored-by: achatterjee-grafana <aparajita.chatterjee@grafana.com>
This commit is contained in:
@@ -26,6 +26,7 @@ type SocialGenericOAuth struct {
|
||||
loginAttributePath string
|
||||
nameAttributePath string
|
||||
roleAttributePath string
|
||||
roleAttributeStrict bool
|
||||
idTokenAttributeName string
|
||||
teamIds []int
|
||||
}
|
||||
@@ -166,6 +167,10 @@ func (s *SocialGenericOAuth) UserInfo(client *http.Client, token *oauth2.Token)
|
||||
userInfo.Login = userInfo.Email
|
||||
}
|
||||
|
||||
if s.roleAttributeStrict && !models.RoleType(userInfo.Role).IsValid() {
|
||||
return nil, errors.New("invalid role")
|
||||
}
|
||||
|
||||
if !s.IsTeamMember(client) {
|
||||
return nil, errors.New("user not a member of one of the required teams")
|
||||
}
|
||||
|
||||
@@ -14,9 +14,10 @@ import (
|
||||
|
||||
type SocialOkta struct {
|
||||
*SocialBase
|
||||
apiUrl string
|
||||
allowedGroups []string
|
||||
roleAttributePath string
|
||||
apiUrl string
|
||||
allowedGroups []string
|
||||
roleAttributePath string
|
||||
roleAttributeStrict bool
|
||||
}
|
||||
|
||||
type OktaUserInfoJson struct {
|
||||
@@ -81,6 +82,9 @@ func (s *SocialOkta) UserInfo(client *http.Client, token *oauth2.Token) (*BasicU
|
||||
if err != nil {
|
||||
s.log.Error("Failed to extract role", "error", err)
|
||||
}
|
||||
if s.roleAttributeStrict && !models.RoleType(role).IsValid() {
|
||||
return nil, errors.New("invalid role")
|
||||
}
|
||||
|
||||
groups := s.GetGroups(&data)
|
||||
if !s.IsGroupMember(groups) {
|
||||
|
||||
@@ -86,24 +86,25 @@ func NewOAuthService() {
|
||||
for _, name := range allOauthes {
|
||||
sec := setting.Raw.Section("auth." + name)
|
||||
info := &setting.OAuthInfo{
|
||||
ClientId: sec.Key("client_id").String(),
|
||||
ClientSecret: sec.Key("client_secret").String(),
|
||||
Scopes: util.SplitString(sec.Key("scopes").String()),
|
||||
AuthUrl: sec.Key("auth_url").String(),
|
||||
TokenUrl: sec.Key("token_url").String(),
|
||||
ApiUrl: sec.Key("api_url").String(),
|
||||
Enabled: sec.Key("enabled").MustBool(),
|
||||
EmailAttributeName: sec.Key("email_attribute_name").String(),
|
||||
EmailAttributePath: sec.Key("email_attribute_path").String(),
|
||||
RoleAttributePath: sec.Key("role_attribute_path").String(),
|
||||
AllowedDomains: util.SplitString(sec.Key("allowed_domains").String()),
|
||||
HostedDomain: sec.Key("hosted_domain").String(),
|
||||
AllowSignup: sec.Key("allow_sign_up").MustBool(),
|
||||
Name: sec.Key("name").MustString(name),
|
||||
TlsClientCert: sec.Key("tls_client_cert").String(),
|
||||
TlsClientKey: sec.Key("tls_client_key").String(),
|
||||
TlsClientCa: sec.Key("tls_client_ca").String(),
|
||||
TlsSkipVerify: sec.Key("tls_skip_verify_insecure").MustBool(),
|
||||
ClientId: sec.Key("client_id").String(),
|
||||
ClientSecret: sec.Key("client_secret").String(),
|
||||
Scopes: util.SplitString(sec.Key("scopes").String()),
|
||||
AuthUrl: sec.Key("auth_url").String(),
|
||||
TokenUrl: sec.Key("token_url").String(),
|
||||
ApiUrl: sec.Key("api_url").String(),
|
||||
Enabled: sec.Key("enabled").MustBool(),
|
||||
EmailAttributeName: sec.Key("email_attribute_name").String(),
|
||||
EmailAttributePath: sec.Key("email_attribute_path").String(),
|
||||
RoleAttributePath: sec.Key("role_attribute_path").String(),
|
||||
RoleAttributeStrict: sec.Key("role_attribute_strict").MustBool(),
|
||||
AllowedDomains: util.SplitString(sec.Key("allowed_domains").String()),
|
||||
HostedDomain: sec.Key("hosted_domain").String(),
|
||||
AllowSignup: sec.Key("allow_sign_up").MustBool(),
|
||||
Name: sec.Key("name").MustString(name),
|
||||
TlsClientCert: sec.Key("tls_client_cert").String(),
|
||||
TlsClientKey: sec.Key("tls_client_key").String(),
|
||||
TlsClientCa: sec.Key("tls_client_ca").String(),
|
||||
TlsSkipVerify: sec.Key("tls_skip_verify_insecure").MustBool(),
|
||||
}
|
||||
|
||||
if !info.Enabled {
|
||||
@@ -167,10 +168,11 @@ func NewOAuthService() {
|
||||
// Okta
|
||||
if name == "okta" {
|
||||
SocialMap["okta"] = &SocialOkta{
|
||||
SocialBase: newSocialBase(name, &config, info),
|
||||
apiUrl: info.ApiUrl,
|
||||
allowedGroups: util.SplitString(sec.Key("allowed_groups").String()),
|
||||
roleAttributePath: info.RoleAttributePath,
|
||||
SocialBase: newSocialBase(name, &config, info),
|
||||
apiUrl: info.ApiUrl,
|
||||
allowedGroups: util.SplitString(sec.Key("allowed_groups").String()),
|
||||
roleAttributePath: info.RoleAttributePath,
|
||||
roleAttributeStrict: info.RoleAttributeStrict,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,6 +185,7 @@ func NewOAuthService() {
|
||||
emailAttributePath: info.EmailAttributePath,
|
||||
nameAttributePath: sec.Key("name_attribute_path").String(),
|
||||
roleAttributePath: info.RoleAttributePath,
|
||||
roleAttributeStrict: info.RoleAttributeStrict,
|
||||
loginAttributePath: sec.Key("login_attribute_path").String(),
|
||||
idTokenAttributeName: sec.Key("id_token_attribute_name").String(),
|
||||
teamIds: sec.Key("team_ids").Ints(","),
|
||||
|
||||
@@ -8,6 +8,7 @@ type OAuthInfo struct {
|
||||
EmailAttributeName string
|
||||
EmailAttributePath string
|
||||
RoleAttributePath string
|
||||
RoleAttributeStrict bool
|
||||
AllowedDomains []string
|
||||
HostedDomain string
|
||||
ApiUrl string
|
||||
|
||||
Reference in New Issue
Block a user