diff --git a/custom/conf/app.example.ini b/custom/conf/app.example.ini index 64667e4..2b0e090 100644 --- a/custom/conf/app.example.ini +++ b/custom/conf/app.example.ini @@ -1735,8 +1735,9 @@ LEVEL = Info ;; userid = use the userid / sub attribute ;; nickname = use the nickname attribute ;; preferred_username = use the preferred_username attribute +;; employee_id = use the employee_id attribute (requires the provider to return this custom claim) ;; email = use the username part of the email attribute -;; Note: `nickname`, `preferred_username` and `email` options will normalize input strings using the following criteria: +;; Note: `nickname`, `preferred_username`, `employee_id` and `email` options will normalize input strings using the following criteria: ;; - diacritics are removed ;; - the characters in the set ['ยด`] are removed ;; - the characters in the set [\s~+] are replaced with "-" diff --git a/modules/setting/oauth2.go b/modules/setting/oauth2.go index f43a374..e143cb6 100644 --- a/modules/setting/oauth2.go +++ b/modules/setting/oauth2.go @@ -20,11 +20,12 @@ const ( OAuth2UsernameNickname OAuth2UsernameType = "nickname" // use nickname field OAuth2UsernameEmail OAuth2UsernameType = "email" // use email field OAuth2UsernamePreferredUsername OAuth2UsernameType = "preferred_username" // use preferred_username field + OAuth2UsernameEmployeeID OAuth2UsernameType = "employee_id" // use employee_id field ) func (username OAuth2UsernameType) isValid() bool { switch username { - case OAuth2UsernameUserid, OAuth2UsernameNickname, OAuth2UsernameEmail, OAuth2UsernamePreferredUsername: + case OAuth2UsernameUserid, OAuth2UsernameNickname, OAuth2UsernameEmail, OAuth2UsernamePreferredUsername, OAuth2UsernameEmployeeID: return true } return false diff --git a/modules/setting/oauth2_test.go b/modules/setting/oauth2_test.go index fccff21..3ad0f49 100644 --- a/modules/setting/oauth2_test.go +++ b/modules/setting/oauth2_test.go @@ -88,3 +88,11 @@ ENABLE_OPENID_CONNECT_PKCE = true loadOAuth2ClientFrom(cfg) assert.True(t, OAuth2Client.EnableOpenIDConnectPKCE) } + +func TestOAuth2ClientEmployeeIDUsername(t *testing.T) { + cfg, _ := NewConfigProviderFromData(`[oauth2_client] +USERNAME = employee_id +`) + loadOAuth2ClientFrom(cfg) + assert.Equal(t, OAuth2UsernameEmployeeID, OAuth2Client.Username) +} diff --git a/routers/web/auth/auth.go b/routers/web/auth/auth.go index f808734..edde656 100644 --- a/routers/web/auth/auth.go +++ b/routers/web/auth/auth.go @@ -450,6 +450,11 @@ func extractUserNameFromOAuth2(gothUser *goth.User) (string, error) { return user_model.NormalizeUserName(preferredUsername) } return "", nil + case setting.OAuth2UsernameEmployeeID: + if employeeID, ok := gothUser.RawData["employee_id"].(string); ok { + return user_model.NormalizeUserName(employeeID) + } + return "", nil case setting.OAuth2UsernameNickname: return user_model.NormalizeUserName(gothUser.NickName) default: // OAuth2UsernameUserid diff --git a/routers/web/auth/auth_test.go b/routers/web/auth/auth_test.go index 5d2b909..73880bd 100644 --- a/routers/web/auth/auth_test.go +++ b/routers/web/auth/auth_test.go @@ -184,6 +184,20 @@ func TestWebAuthOAuth2(t *testing.T) { }) } +func TestExtractUserNameFromOAuth2EmployeeID(t *testing.T) { + defer test.MockVariableValue(&setting.OAuth2Client.Username, setting.OAuth2UsernameEmployeeID)() + + username, err := extractUserNameFromOAuth2(&goth.User{ + RawData: map[string]any{"employee_id": "RC001"}, + }) + require.NoError(t, err) + assert.Equal(t, "RC001", username) + + username, err = extractUserNameFromOAuth2(&goth.User{RawData: map[string]any{}}) + require.NoError(t, err) + assert.Empty(t, username) +} + func TestOpenIDRequireTwoFactor(t *testing.T) { require.NoError(t, unittest.PrepareTestDatabase()) mockOpt := contexttest.MockContextOption{SessionStore: session.NewMockMemStore("dummy-sid-openid")} diff --git a/routers/web/auth/oauth.go b/routers/web/auth/oauth.go index 72b9c4f..ca6136b 100644 --- a/routers/web/auth/oauth.go +++ b/routers/web/auth/oauth.go @@ -160,6 +160,8 @@ func SignInOAuthCallback(ctx *context.Context) { missingFields = append(missingFields, "nickname") case setting.OAuth2UsernamePreferredUsername: missingFields = append(missingFields, "preferred_username") + case setting.OAuth2UsernameEmployeeID: + missingFields = append(missingFields, "employee_id") } // else: "UserID" and "Email" have been handled above separately } if len(missingFields) > 0 {