From a783667c57cd6f6988e8fb94f3e9d9c2bdc3be61 Mon Sep 17 00:00:00 2001
From: Scott Lemmon <slemmon@aurora.tech>
Date: Fri, 7 Aug 2020 15:06:14 -0700
Subject: [PATCH] Add groupsClaimMapping to the OIDC connector

The groupsClaimMapping setting allows one to specify which claim to pull
group information from the OIDC provider.  Previously it assumed group
information was always in the "groups" claim, but that isn't the case
for many OIDC providers (such as AWS Cognito using the "cognito:groups"
claim instead)

Signed-off-by: Scott Lemmon <slemmon@aurora.tech>
Signed-off-by: Rui Yang <ruiya@vmware.com>
---
 Documentation/connectors/oidc.md |  4 ++++
 connector/oidc/oidc.go           | 15 +++++++++++++--
 2 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/Documentation/connectors/oidc.md b/Documentation/connectors/oidc.md
index 4df28915..c6fbf2a3 100644
--- a/Documentation/connectors/oidc.md
+++ b/Documentation/connectors/oidc.md
@@ -73,6 +73,10 @@ connectors:
     # This can be overridden with the below option
     # insecureEnableGroups: true
 
+    # If an OIDC provider uses a different claim name than the standard "groups" claim to provide group information
+    # the claim to use can be specified
+    # groupsClaimMapping: "cognito:groups"
+
     # When enabled, the OpenID Connector will query the UserInfo endpoint for additional claims. UserInfo claims
     # take priority over claims returned by the IDToken. This option should be used when the IDToken doesn't contain
     # all the claims requested.
diff --git a/connector/oidc/oidc.go b/connector/oidc/oidc.go
index d1faba7b..fd7396df 100644
--- a/connector/oidc/oidc.go
+++ b/connector/oidc/oidc.go
@@ -44,6 +44,9 @@ type Config struct {
 	// InsecureEnableGroups enables groups claims. This is disabled by default until https://github.com/dexidp/dex/issues/1065 is resolved
 	InsecureEnableGroups bool `json:"insecureEnableGroups"`
 
+	// GroupsClaimMapping sets the name of the claim which contains the users groups. InsecureEnableGroups must be enabled to use this setting
+	GroupsClaimMapping string `json:"groupsClaimMapping"` // defaults to "groups"
+
 	// GetUserInfo uses the userinfo endpoint to get additional claims for
 	// the token. This is especially useful where upstreams return "thin"
 	// id tokens
@@ -132,6 +135,11 @@ func (c *Config) Open(id string, logger log.Logger) (conn connector.Connector, e
 		c.PromptType = "consent"
 	}
 
+	// GroupsClaimMapping should be "groups" by default, if not set
+	if c.GroupsClaimMapping == "" {
+		c.GroupsClaimMapping = "groups"
+	}
+
 	clientID := c.ClientID
 	return &oidcConnector{
 		provider:    provider,
@@ -151,6 +159,7 @@ func (c *Config) Open(id string, logger log.Logger) (conn connector.Connector, e
 		hostedDomains:             c.HostedDomains,
 		insecureSkipEmailVerified: c.InsecureSkipEmailVerified,
 		insecureEnableGroups:      c.InsecureEnableGroups,
+		groupsClaimMapping:        c.GroupsClaimMapping,
 		getUserInfo:               c.GetUserInfo,
 		userIDKey:                 c.UserIDKey,
 		userNameKey:               c.UserNameKey,
@@ -175,6 +184,7 @@ type oidcConnector struct {
 	hostedDomains             []string
 	insecureSkipEmailVerified bool
 	insecureEnableGroups      bool
+	groupsClaimMapping        string
 	getUserInfo               bool
 	userIDKey                 string
 	userNameKey               string
@@ -357,13 +367,14 @@ func (c *oidcConnector) createIdentity(ctx context.Context, identity connector.I
 	}
 
 	if c.insecureEnableGroups {
-		vs, ok := claims["groups"].([]interface{})
+
+		vs, ok := claims[c.groupsClaimMapping].([]interface{})
 		if ok {
 			for _, v := range vs {
 				if s, ok := v.(string); ok {
 					identity.Groups = append(identity.Groups, s)
 				} else {
-					return identity, errors.New("malformed \"groups\" claim")
+					return identity, fmt.Errorf("malformed \"%v\" claim", c.groupsClaimMapping)
 				}
 			}
 		}
-- 
GitLab