mirror of
				https://codeberg.org/forgejo/forgejo.git
				synced 2025-11-04 08:21:11 +00:00 
			
		
		
		
	[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 commit0f6e0f9035) (cherry picked from commit779168a572) (cherry picked from commit29a2457321) (cherry picked from commita1edc2314d)
This commit is contained in:
		
					parent
					
						
							
								d6af2094df
							
						
					
				
			
			
				commit
				
					
						cd01594610
					
				
			
		
					 2 changed files with 39 additions and 8 deletions
				
			
		| 
						 | 
					@ -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{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue