mirror of https://github.com/grafana/grafana.git
				
				
				
			AzureAD OAuth: Add optional strict parsing of role_attribute_path for Azure AD (#42157)
* AzureAD OAuth: Add optional strict parsing of role_attribute_path for Azure AD Fix casting issues modify unit tests Unit test fix Add proper test args * Return empty role when using strict attribute mode * Raise error on empty role * Fix UT for latest case
This commit is contained in:
		
							parent
							
								
									ea7d5a6185
								
							
						
					
					
						commit
						6c468daabc
					
				|  | @ -508,6 +508,7 @@ auth_url = https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/authorize | |||
| token_url = https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/token | ||||
| allowed_domains = | ||||
| allowed_groups = | ||||
| role_attribute_strict = false | ||||
| 
 | ||||
| #################################### Okta OAuth ####################### | ||||
| [auth.okta] | ||||
|  |  | |||
|  | @ -493,6 +493,7 @@ | |||
| ;token_url = https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/token | ||||
| ;allowed_domains = | ||||
| ;allowed_groups = | ||||
| ;role_attribute_strict = false | ||||
| 
 | ||||
| #################################### Okta OAuth ####################### | ||||
| [auth.okta] | ||||
|  |  | |||
|  | @ -109,6 +109,7 @@ auth_url = https://login.microsoftonline.com/TENANT_ID/oauth2/v2.0/authorize | |||
| token_url = https://login.microsoftonline.com/TENANT_ID/oauth2/v2.0/token | ||||
| allowed_domains = | ||||
| allowed_groups = | ||||
| role_attribute_strict = false | ||||
| ``` | ||||
| 
 | ||||
| You can also use these environment variables to configure **client_id** and **client_secret**: | ||||
|  |  | |||
|  | @ -19,6 +19,7 @@ type SocialAzureAD struct { | |||
| 	*SocialBase | ||||
| 	allowedGroups       []string | ||||
| 	autoAssignOrgRole   string | ||||
| 	roleAttributeStrict bool | ||||
| } | ||||
| 
 | ||||
| type azureClaims struct { | ||||
|  | @ -69,7 +70,10 @@ func (s *SocialAzureAD) UserInfo(client *http.Client, token *oauth2.Token) (*Bas | |||
| 		return nil, errors.New("error getting user info: no email found in access token") | ||||
| 	} | ||||
| 
 | ||||
| 	role := extractRole(claims, s.autoAssignOrgRole) | ||||
| 	role := extractRole(claims, s.autoAssignOrgRole, s.roleAttributeStrict) | ||||
| 	if role == "" { | ||||
| 		return nil, errors.New("user does not have a valid role") | ||||
| 	} | ||||
| 	logger.Debug("AzureAD OAuth: extracted role", "email", email, "role", role) | ||||
| 
 | ||||
| 	groups, err := extractGroups(client, claims, token) | ||||
|  | @ -118,7 +122,7 @@ func extractEmail(claims azureClaims) string { | |||
| 	return claims.Email | ||||
| } | ||||
| 
 | ||||
| func extractRole(claims azureClaims, autoAssignRole string) models.RoleType { | ||||
| func extractRole(claims azureClaims, autoAssignRole string, strictMode bool) models.RoleType { | ||||
| 	if len(claims.Roles) == 0 { | ||||
| 		return models.RoleType(autoAssignRole) | ||||
| 	} | ||||
|  | @ -135,6 +139,10 @@ func extractRole(claims azureClaims, autoAssignRole string) models.RoleType { | |||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if strictMode { | ||||
| 		return models.RoleType("") | ||||
| 	} | ||||
| 
 | ||||
| 	return models.ROLE_VIEWER | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -21,6 +21,7 @@ func TestSocialAzureAD_UserInfo(t *testing.T) { | |||
| 		SocialBase          *SocialBase | ||||
| 		allowedGroups       []string | ||||
| 		autoAssignOrgRole   string | ||||
| 		roleAttributeStrict bool | ||||
| 	} | ||||
| 	type args struct { | ||||
| 		client *http.Client | ||||
|  | @ -279,6 +280,22 @@ func TestSocialAzureAD_UserInfo(t *testing.T) { | |||
| 			}, | ||||
| 			wantErr: false, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name: "Fetch empty role when strict attribute role is true and no match", | ||||
| 			fields: fields{ | ||||
| 				roleAttributeStrict: true, | ||||
| 			}, | ||||
| 			claims: &azureClaims{ | ||||
| 				Email:             "me@example.com", | ||||
| 				PreferredUsername: "", | ||||
| 				Roles:             []string{"foo"}, | ||||
| 				Groups:            []string{}, | ||||
| 				Name:              "My Name", | ||||
| 				ID:                "1234", | ||||
| 			}, | ||||
| 			want:    nil, | ||||
| 			wantErr: true, | ||||
| 		}, | ||||
| 	} | ||||
| 	for _, tt := range tests { | ||||
| 		t.Run(tt.name, func(t *testing.T) { | ||||
|  | @ -286,6 +303,7 @@ func TestSocialAzureAD_UserInfo(t *testing.T) { | |||
| 				SocialBase:          tt.fields.SocialBase, | ||||
| 				allowedGroups:       tt.fields.allowedGroups, | ||||
| 				autoAssignOrgRole:   tt.fields.autoAssignOrgRole, | ||||
| 				roleAttributeStrict: tt.fields.roleAttributeStrict, | ||||
| 			} | ||||
| 
 | ||||
| 			key := []byte("secret") | ||||
|  |  | |||
|  | @ -152,6 +152,7 @@ func ProvideService(cfg *setting.Cfg) *SocialService { | |||
| 				SocialBase:          newSocialBase(name, &config, info), | ||||
| 				allowedGroups:       util.SplitString(sec.Key("allowed_groups").String()), | ||||
| 				autoAssignOrgRole:   cfg.AutoAssignOrgRole, | ||||
| 				roleAttributeStrict: info.RoleAttributeStrict, | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue