diff --git a/connector/oidc/oidc.go b/connector/oidc/oidc.go index 7d0cacb056..1ea0c1fc1a 100644 --- a/connector/oidc/oidc.go +++ b/connector/oidc/oidc.go @@ -23,7 +23,12 @@ import ( // Config holds configuration options for OpenID Connect logins. type Config struct { - Issuer string `json:"issuer"` + Issuer string `json:"issuer"` + // Some offspec providers like Azure, Oracle IDCS have oidc discovery url + // different from issuer url which causes issuerValidation to fail + // IssuerAlias provides a way to override the Issuer url + // from the .well-known/openid-configuration issuer + IssuerAlias string `json:"issuerAlias"` ClientID string `json:"clientID"` ClientSecret string `json:"clientSecret"` RedirectURI string `json:"redirectURI"` @@ -226,7 +231,9 @@ func (c *Config) Open(id string, logger *slog.Logger) (conn connector.Connector, bgctx, cancel := context.WithCancel(context.Background()) ctx := context.WithValue(bgctx, oauth2.HTTPClient, httpClient) - + if c.IssuerAlias != "" { + ctx = oidc.InsecureIssuerURLContext(ctx, c.IssuerAlias) + } provider, err := getProvider(ctx, c.Issuer, c.ProviderDiscoveryOverrides) if err != nil { cancel() @@ -540,6 +547,13 @@ func (c *oidcConnector) createIdentity(ctx context.Context, identity connector.I continue } groups = append(groups, s) + } else if groupMap, ok := v.(map[string]interface{}); ok { + if s, ok := groupMap["name"].(string); ok { + if c.groupsFilter != nil && !c.groupsFilter.MatchString(s) { + continue + } + groups = append(groups, s) + } } else { return identity, fmt.Errorf("malformed \"%v\" claim", groupsKey) } diff --git a/connector/oidc/oidc_test.go b/connector/oidc/oidc_test.go index 66b35c3fef..e31d4e0b94 100644 --- a/connector/oidc/oidc_test.go +++ b/connector/oidc/oidc_test.go @@ -292,6 +292,38 @@ func TestHandleCallback(t *testing.T) { "email_verified": true, }, }, + { + name: "singularGroupResponseAsMap", + userIDKey: "", // not configured + userNameKey: "", // not configured + expectUserID: "subvalue", + expectUserName: "namevalue", + expectGroups: []string{"group1"}, + expectedEmailField: "emailvalue", + token: map[string]interface{}{ + "sub": "subvalue", + "name": "namevalue", + "groups": []map[string]string{{"name": "group1"}}, + "email": "emailvalue", + "email_verified": true, + }, + }, + { + name: "multipleGroupResponseAsMap", + userIDKey: "", // not configured + userNameKey: "", // not configured + expectUserID: "subvalue", + expectUserName: "namevalue", + expectGroups: []string{"group1", "group2"}, + expectedEmailField: "emailvalue", + token: map[string]interface{}{ + "sub": "subvalue", + "name": "namevalue", + "groups": []map[string]string{{"name": "group1"}, {"name": "group2"}}, + "email": "emailvalue", + "email_verified": true, + }, + }, { name: "newGroupFromClaims", userIDKey: "", // not configured @@ -382,6 +414,23 @@ func TestHandleCallback(t *testing.T) { "email_verified": true, }, }, + { + name: "filterGroupClaimsMap", + userIDKey: "", // not configured + userNameKey: "", // not configured + groupsRegex: `^.*\d$`, + expectUserID: "subvalue", + expectUserName: "namevalue", + expectGroups: []string{"group1", "group2"}, + expectedEmailField: "emailvalue", + token: map[string]interface{}{ + "sub": "subvalue", + "name": "namevalue", + "groups": []map[string]string{{"name": "group1"}, {"name": "group2"}, {"name": "groupA"}, {"name": "groupB"}}, + "email": "emailvalue", + "email_verified": true, + }, + }, } for _, tc := range tests {