diff --git a/pkg/login/social/azuread_oauth.go b/pkg/login/social/azuread_oauth.go index e392eadc874..7545e10a733 100644 --- a/pkg/login/social/azuread_oauth.go +++ b/pkg/login/social/azuread_oauth.go @@ -22,6 +22,10 @@ import ( "github.com/grafana/grafana/pkg/util" ) +var ( + errAzureADMissingGroups = &Error{"either the user does not have any group membership or the groups claim is missing from the token."} +) + const azureADProviderName = "azuread" var _ SocialConnector = (*SocialAzureAD)(nil) @@ -130,6 +134,11 @@ func (s *SocialAzureAD) UserInfo(ctx context.Context, client *http.Client, token } s.log.Debug("AzureAD OAuth: extracted groups", "email", email, "groups", fmt.Sprintf("%v", groups)) if !s.isGroupMember(groups) { + if len(groups) == 0 { + // either they do not have a group or misconfiguration + return nil, errAzureADMissingGroups + } + // user is not a member of any of the allowed groups return nil, errMissingGroupMembership } @@ -275,6 +284,7 @@ type getAzureGroupResponse struct { // extractGroups retrieves groups from the claims. // Note: If user groups exceeds 200 no groups will be found in claims and URL to target the Graph API will be // given instead. +// // See https://docs.microsoft.com/en-us/azure/active-directory/develop/id-tokens#groups-overage-claim func (s *SocialAzureAD) extractGroups(ctx context.Context, client *http.Client, claims *azureClaims, token *oauth2.Token) ([]string, error) { if !s.forceUseGraphAPI { @@ -318,10 +328,10 @@ func (s *SocialAzureAD) extractGroups(ctx context.Context, client *http.Client, if res.StatusCode != http.StatusOK { if res.StatusCode == http.StatusForbidden { - s.log.Warn("AzureAD OAuh: Token need GroupMember.Read.All permission to fetch all groups") + s.log.Warn("AzureAD OAuth: Token need GroupMember.Read.All permission to fetch all groups") } else { body, _ := io.ReadAll(res.Body) - s.log.Warn("AzureAD OAuh: could not fetch user groups", "code", res.StatusCode, "body", string(body)) + s.log.Warn("AzureAD OAuth: could not fetch user groups", "code", res.StatusCode, "body", string(body)) } return []string{}, nil } diff --git a/pkg/login/social/azuread_oauth_test.go b/pkg/login/social/azuread_oauth_test.go index 96be15224fa..dada74594d2 100644 --- a/pkg/login/social/azuread_oauth_test.go +++ b/pkg/login/social/azuread_oauth_test.go @@ -529,6 +529,30 @@ func TestSocialAzureAD_UserInfo(t *testing.T) { Groups: []string{"foo"}, }, }, + { + name: "Error if user does not have groups but allowed groups", + fields: fields{ + providerCfg: map[string]any{ + "name": "azuread", + "client_id": "client-id-example", + "allow_assign_grafana_admin": "false", + "allowed_groups": "foo, bar", + }, + cfg: &setting.Cfg{ + AutoAssignOrgRole: "Viewer", + }, + }, + claims: &azureClaims{ + Email: "me@example.com", + PreferredUsername: "", + Roles: []string{}, + Groups: []string{""}, + Name: "My Name", + ID: "1234", + }, + want: nil, + wantErr: true, + }, { name: "Fetch groups when ClaimsNames and ClaimsSources is set", fields: fields{