Repository: dexidp/dex
Pull request #2483 (2022-04-21 03:18:25)

Add numeric user ID support for oauth connector
Signed-off-by: Shuanglei Tao <tsl0922@gmail.com>

<!--
Thank you for sending a pull request! Here are some tips for contributors:

1. Fill the description template below.
2. Sign a DCO (if you haven't already signed it).
3. Include appropriate tests (if necessary). Make sure that all CI checks passed.
4. If the Pull Request is a work in progress, make use of GitHub's "Draft PR" feature and mark it as such.
-->

#### Overview

<!-- Describe your changes briefly here. -->

#### What this PR does / why we need it

Add numeric user ID support for oauth connector

#### Special notes for your reviewer

#### Does this PR introduce a user-facing change?



```release-note
Add numeric user ID support for oauth connector
```



Patch:
diff --git a/connector/oauth/oauth.go b/connector/oauth/oauth.go
index e37932ad..237d075e 100644
--- a/connector/oauth/oauth.go
+++ b/connector/oauth/oauth.go
@@ -209,12 +209,18 @@ func (c *oauthConnector) HandleCallback(s connector.Scopes, r *http.Request) (id
 		return identity, fmt.Errorf("OAuth Connector: failed to parse userinfo: %v", err)
 	}
 
-	userID, found := userInfoResult[c.userIDKey].(string)
+	userID, found := userInfoResult[c.userIDKey]
 	if !found {
 		return identity, fmt.Errorf("OAuth Connector: not found %v claim", c.userIDKey)
 	}
 
-	identity.UserID = userID
+	switch userID.(type) {
+	case float64, int64, string:
+		identity.UserID = fmt.Sprintf("%v", userID)
+	default:
+		return identity, fmt.Errorf("OAuth Connector: %v claim should be string or number, got %T", c.userIDKey, userID)
+	}
+
 	identity.Username, _ = userInfoResult[c.userNameKey].(string)
 	identity.PreferredUsername, _ = userInfoResult[c.preferredUsernameKey].(string)
 	identity.Email, _ = userInfoResult[c.emailKey].(string)


Test patch:
diff --git a/connector/oauth/oauth_test.go b/connector/oauth/oauth_test.go
index 082a3aa5..3a5ec6bf 100644
--- a/connector/oauth/oauth_test.go
+++ b/connector/oauth/oauth_test.go
@@ -84,7 +84,7 @@ func TestHandleCallBackForGroupsInUserInfo(t *testing.T) {
 	defer testServer.Close()
 
 	conn := newConnector(t, testServer.URL)
-	req := newRequestWithAuthCode(t, testServer.URL, "some-code")
+	req := newRequestWithAuthCode(t, testServer.URL, "TestHandleCallBackForGroupsInUserInfo")
 
 	identity, err := conn.HandleCallback(connector.Scopes{Groups: true}, req)
 	assert.Equal(t, err, nil)
@@ -120,7 +120,7 @@ func TestHandleCallBackForGroupMapsInUserInfo(t *testing.T) {
 	defer testServer.Close()
 
 	conn := newConnector(t, testServer.URL)
-	req := newRequestWithAuthCode(t, testServer.URL, "some-code")
+	req := newRequestWithAuthCode(t, testServer.URL, "TestHandleCallBackForGroupMapsInUserInfo")
 
 	identity, err := conn.HandleCallback(connector.Scopes{Groups: true}, req)
 	assert.Equal(t, err, nil)
@@ -154,7 +154,7 @@ func TestHandleCallBackForGroupsInToken(t *testing.T) {
 	defer testServer.Close()
 
 	conn := newConnector(t, testServer.URL)
-	req := newRequestWithAuthCode(t, testServer.URL, "some-code")
+	req := newRequestWithAuthCode(t, testServer.URL, "TestHandleCallBackForGroupsInToken")
 
 	identity, err := conn.HandleCallback(connector.Scopes{Groups: true}, req)
 	assert.Equal(t, err, nil)
@@ -168,6 +168,34 @@ func TestHandleCallBackForGroupsInToken(t *testing.T) {
 	assert.Equal(t, identity.EmailVerified, false)
 }
 
+func TestHandleCallbackForNumericUserID(t *testing.T) {
+	tokenClaims := map[string]interface{}{}
+
+	userInfoClaims := map[string]interface{}{
+		"name":               "test-name",
+		"user_id_key":        1000,
+		"user_name_key":      "test-username",
+		"preferred_username": "test-preferred-username",
+		"mail":               "mod_mail",
+		"has_verified_email": false,
+	}
+
+	testServer := testSetup(t, tokenClaims, userInfoClaims)
+	defer testServer.Close()
+
+	conn := newConnector(t, testServer.URL)
+	req := newRequestWithAuthCode(t, testServer.URL, "TestHandleCallbackForNumericUserID")
+
+	identity, err := conn.HandleCallback(connector.Scopes{Groups: true}, req)
+	assert.Equal(t, err, nil)
+
+	assert.Equal(t, identity.UserID, "1000")
+	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 testSetup(t *testing.T, tokenClaims map[string]interface{}, userInfoClaims map[string]interface{}) *httptest.Server {
 	key, err := rsa.GenerateKey(rand.Reader, 1024)
 	if err != nil {