This commit is contained in:
Aniket Patil 2026-04-21 12:16:50 +05:30 committed by GitHub
commit 20240b2746
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 58 additions and 1 deletions

View file

@ -599,3 +599,22 @@ Disabling certificate verification might make sense if:
If either of those two applies, then you can disable OIDC provider certificate verification by setting
`oidc.tls.insecure.skip.verify` to `"true"` in the `argocd-cm` ConfigMap.
### Configurable groups claim
By default, Argo CD reads user group information from the `groups` claim in the OIDC UserInfo endpoint response.
Some identity providers return group membership using a different claim name such as `roles`, `memberof`, or other custom attributes.
You can configure a custom claim name using the `groupsClaim` field:
```yaml
oidc.config: |
name: example
issuer: https://example.com
clientID: example-client-id
clientSecret: example-secret
enableUserInfoGroups: true
userInfoPath: /userinfo
groupsClaim: roles
```

View file

@ -908,7 +908,11 @@ func (a *ClientApp) SetGroupsFromUserInfo(ctx context.Context, claims jwt.Claims
if groupClaims["sub"] != userInfo["sub"] {
return groupClaims, errors.New("subject of claims from user info endpoint didn't match subject of idToken, see https://openid.net/specs/openid-connect-core-1_0.html#UserInfo")
}
groupClaims["groups"] = userInfo["groups"]
groupsClaim := a.settings.UserInfoGroupsClaim()
if userInfo[groupsClaim] == nil {
log.Warnf("groups claim '%s' not found in UserInfo response, user will have no groups", groupsClaim)
}
groupClaims["groups"] = userInfo[groupsClaim]
}
return groupClaims, nil

View file

@ -198,6 +198,7 @@ func (o *oidcConfig) toExported() *OIDCConfig {
RootCA: o.RootCA,
EnablePKCEAuthentication: o.EnablePKCEAuthentication,
DomainHint: o.DomainHint,
GroupsClaim: o.GroupsClaim,
}
}
@ -218,6 +219,7 @@ type OIDCConfig struct {
DomainHint string `json:"domainHint,omitempty"`
Azure *AzureOIDCConfig `json:"azure,omitempty"`
RefreshTokenThreshold string `json:"refreshTokenThreshold,omitempty"`
GroupsClaim string `json:"groupsClaim,omitempty"`
}
type AzureOIDCConfig struct {
@ -2502,6 +2504,14 @@ func (mgr *SettingsManager) GetAllowedNodeLabels() []string {
return labelKeys
}
func (a *ArgoCDSettings) UserInfoGroupsClaim() string {
cfg := a.OIDCConfig()
if cfg != nil && cfg.GroupsClaim != "" {
return strings.TrimSpace(cfg.GroupsClaim)
}
return "groups"
}
// IsInClusterEnabled returns false if in-cluster is explicitly disabled in argocd-cm configmap, true otherwise
func (mgr *SettingsManager) IsInClusterEnabled() (bool, error) {
argoCDCM, err := mgr.getConfigMap()

View file

@ -2351,6 +2351,30 @@ func TestSettingsManager_GetAllowedNodeLabels(t *testing.T) {
}
}
func TestUserInfoGroupsClaim(t *testing.T) {
t.Run("should return default 'groups' when config is empty", func(t *testing.T) {
settings := &ArgoCDSettings{
OIDCConfigRAW: "",
}
result := settings.UserInfoGroupsClaim()
assert.Equal(t, "groups", result)
})
t.Run("should return default 'groups' when groupsClaim not present", func(t *testing.T) {
settings := &ArgoCDSettings{
OIDCConfigRAW: `{
"name": "test",
"issuer": "https://example.com",
"clientID": "test-client"
}`,
}
result := settings.UserInfoGroupsClaim()
assert.Equal(t, "groups", result)
})
}
func TestSecretsInformerExcludesClusterSecrets(t *testing.T) {
cm := &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{