[GITEA] oauth2: use link_account page when email/username is missing (#1757)

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/1757
Co-authored-by: Antonin Delpeuch <antonin@delpeuch.eu>
Co-committed-by: Antonin Delpeuch <antonin@delpeuch.eu>
(cherry picked from commit 0f6e0f9035)
(cherry picked from commit 779168a572)
(cherry picked from commit 29a2457321)
This commit is contained in:
Antonin Delpeuch 2023-11-19 11:50:05 +00:00 committed by Earl Warren
parent d3b352c854
commit a1edc2314d
No known key found for this signature in database
GPG key ID: 0579CB2928A78A00
2 changed files with 39 additions and 8 deletions

View file

@ -951,10 +951,16 @@ func SignInOAuthCallback(ctx *context.Context) {
return return
} else if !setting.Service.AllowOnlyInternalRegistration && setting.OAuth2Client.EnableAutoRegistration { } else if !setting.Service.AllowOnlyInternalRegistration && setting.OAuth2Client.EnableAutoRegistration {
// create new user with details from oauth2 provider // create new user with details from oauth2 provider
var missingFields []string
if gothUser.UserID == "" { if gothUser.UserID == "" {
missingFields = append(missingFields, "sub") log.Error("OAuth2 Provider %s returned empty or missing field: UserID", authSource.Name)
if authSource.IsOAuth2() && authSource.Cfg.(*oauth2.Source).Provider == "openidConnect" {
log.Error("You may need to change the 'OPENID_CONNECT_SCOPES' setting to request all required fields")
}
err = fmt.Errorf("OAuth2 Provider %s returned empty or missing field: UserID", authSource.Name)
ctx.ServerError("CreateUser", err)
return
} }
var missingFields []string
if gothUser.Email == "" { if gothUser.Email == "" {
missingFields = append(missingFields, "email") missingFields = append(missingFields, "email")
} }
@ -962,12 +968,10 @@ func SignInOAuthCallback(ctx *context.Context) {
missingFields = append(missingFields, "nickname") missingFields = append(missingFields, "nickname")
} }
if len(missingFields) > 0 { if len(missingFields) > 0 {
log.Error("OAuth2 Provider %s returned empty or missing fields: %s", authSource.Name, missingFields) // we don't have enough information to create an account automatically,
if authSource.IsOAuth2() && authSource.Cfg.(*oauth2.Source).Provider == "openidConnect" { // so we prompt the user for the remaining bits
log.Error("You may need to change the 'OPENID_CONNECT_SCOPES' setting to request all required fields") log.Trace("OAuth2 Provider %s returned empty or missing fields: %s, prompting the user for them", authSource.Name, missingFields)
} showLinkingLogin(ctx, gothUser)
err = fmt.Errorf("OAuth2 Provider %s returned empty or missing fields: %s", authSource.Name, missingFields)
ctx.ServerError("CreateUser", err)
return return
} }
u = &user_model.User{ u = &user_model.User{

View file

@ -469,3 +469,30 @@ func TestSignInOAuthCallbackSignIn(t *testing.T) {
userAfterLogin := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: userGitLab.ID}) userAfterLogin := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: userGitLab.ID})
assert.Greater(t, userAfterLogin.LastLoginUnix, userGitLab.LastLoginUnix) assert.Greater(t, userAfterLogin.LastLoginUnix, userGitLab.LastLoginUnix)
} }
func TestSignUpViaOAuthWithMissingFields(t *testing.T) {
defer tests.PrepareTestEnv(t)()
// enable auto-creation of accounts via OAuth2
enableAutoRegistration := setting.OAuth2Client.EnableAutoRegistration
setting.OAuth2Client.EnableAutoRegistration = true
defer func() {
setting.OAuth2Client.EnableAutoRegistration = enableAutoRegistration
}()
// OAuth2 authentication source GitLab
gitlabName := "gitlab"
addAuthSource(t, authSourcePayloadGitLabCustom(gitlabName))
userGitLabUserID := "5678"
// The Goth User returned by the oauth2 integration is missing
// an email address, so we won't be able to automatically create a local account for it.
defer mockCompleteUserAuth(func(res http.ResponseWriter, req *http.Request) (goth.User, error) {
return goth.User{
Provider: gitlabName,
UserID: userGitLabUserID,
}, nil
})()
req := NewRequest(t, "GET", fmt.Sprintf("/user/oauth2/%s/callback?code=XYZ&state=XYZ", gitlabName))
resp := MakeRequest(t, req, http.StatusSeeOther)
assert.Equal(t, test.RedirectURL(resp), "/user/link_account")
}