From e80d6c85714af9874602d3ca10a26beab0c51c87 Mon Sep 17 00:00:00 2001 From: Sabith KS Date: Fri, 17 Oct 2025 21:54:34 -0700 Subject: [PATCH] [4384] Fix the groups coming as JSON string Signed-off-by: sabith --- connector/oauth/oauth.go | 18 +++++++++++++++--- connector/oauth/oauth_test.go | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/connector/oauth/oauth.go b/connector/oauth/oauth.go index 413a813a..1fefe31b 100644 --- a/connector/oauth/oauth.go +++ b/connector/oauth/oauth.go @@ -191,8 +191,12 @@ func (c *oauthConnector) HandleCallback(s connector.Scopes, r *http.Request) (id if s.Groups { groups := map[string]struct{}{} - c.addGroupsFromMap(groups, userInfoResult) - c.addGroupsFromToken(groups, token.AccessToken) + if err := c.addGroupsFromMap(groups, userInfoResult); err != nil { + c.logger.Warn("OAuth Connector: failed to add groups from userinfo", "error", err) + } + if err := c.addGroupsFromToken(groups, token.AccessToken); err != nil { + c.logger.Warn("OAuth Connector: failed to add groups from token", "error", err) + } for groupName := range groups { identity.Groups = append(identity.Groups, groupName) @@ -214,7 +218,15 @@ func (c *oauthConnector) HandleCallback(s connector.Scopes, r *http.Request) (id func (c *oauthConnector) addGroupsFromMap(groups map[string]struct{}, result map[string]interface{}) error { groupsClaim, ok := result[c.groupsKey].([]interface{}) if !ok { - return errors.New("cannot convert to slice") + // sometimes the groups claim is a slice encoded as a JSON string + groupsStr, ok := result[c.groupsKey].(string) + if !ok { + return fmt.Errorf("%T claim is not a list or JSON-encoded list", result[c.groupsKey]) + } + err := json.Unmarshal([]byte(groupsStr), &groupsClaim) + if err != nil { + return fmt.Errorf("failed to decode groups claim: %v", err) + } } for _, group := range groupsClaim { diff --git a/connector/oauth/oauth_test.go b/connector/oauth/oauth_test.go index 2f6b0b95..e2b59278 100644 --- a/connector/oauth/oauth_test.go +++ b/connector/oauth/oauth_test.go @@ -100,6 +100,39 @@ func TestHandleCallBackForGroupsInUserInfo(t *testing.T) { assert.Equal(t, identity.EmailVerified, false) } +func TestHandleCallBackForGroupsInUserInfoIsString(t *testing.T) { + tokenClaims := map[string]interface{}{} + + userInfoClaims := map[string]interface{}{ + "name": "test-name", + "user_id_key": "test-user-id", + "user_name_key": "test-username", + "preferred_username": "test-preferred-username", + "mail": "mod_mail", + "has_verified_email": false, + "groups_key": `["admin-group", "user-group"]`, + } + + testServer := testSetup(t, tokenClaims, userInfoClaims) + defer testServer.Close() + + conn := newConnector(t, testServer.URL) + req := newRequestWithAuthCode(t, testServer.URL, "TestHandleCallBackForGroupsInUserInfo") + + identity, err := conn.HandleCallback(connector.Scopes{Groups: true}, req) + assert.Equal(t, err, nil) + + sort.Strings(identity.Groups) + assert.Equal(t, len(identity.Groups), 2) + assert.Equal(t, identity.Groups[0], "admin-group") + assert.Equal(t, identity.Groups[1], "user-group") + assert.Equal(t, identity.UserID, "test-user-id") + assert.Equal(t, identity.Username, "test-username") + assert.Equal(t, identity.PreferredUsername, "test-preferred-username") + assert.Equal(t, identity.Email, "mod_mail") + assert.Equal(t, identity.EmailVerified, false) +} + func TestHandleCallBackForGroupMapsInUserInfo(t *testing.T) { tokenClaims := map[string]interface{}{}