mirror of
https://github.com/go-gitea/gitea.git
synced 2026-05-03 05:19:14 +00:00
Redirect to the only OAuth2 provider when no other login methods and fix various problems (#36901)
Fixes: #36846 1. When there is only on OAuth2 login method, automatically direct to it 2. Fix legacy problems in code, including: * Rename template filename and fix TODO comments * Fix legacy variable names * Add missing SSPI variable for template * Fix unnecessary layout, remove garbage styles * Only do AppUrl(ROOT_URL) check when it is needed (avoid unnecessary warnings to end users) --------- Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
@@ -218,18 +218,50 @@ func performAutoLogin(ctx *context.Context) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func prepareSignInPageData(ctx *context.Context) {
|
||||
func performAutoLoginOAuth2(ctx *context.Context, data *preparedSignInData) bool {
|
||||
// If only 1 OAuth provider is present and other login methods are disabled, redirect to the OAuth provider.
|
||||
onlySingleOAuth2 := len(data.oauth2Providers) == 1 &&
|
||||
!setting.Service.EnablePasswordSignInForm &&
|
||||
!setting.Service.EnableOpenIDSignIn &&
|
||||
!setting.Service.EnablePasskeyAuth &&
|
||||
!data.enableSSPI
|
||||
|
||||
if !onlySingleOAuth2 {
|
||||
return false
|
||||
}
|
||||
|
||||
skipToOAuthURL := setting.AppSubURL + "/user/oauth2/" + url.QueryEscape(data.oauth2Providers[0].DisplayName())
|
||||
if redirectTo := ctx.FormString("redirect_to"); redirectTo != "" {
|
||||
skipToOAuthURL += "?redirect_to=" + url.QueryEscape(redirectTo)
|
||||
}
|
||||
ctx.Redirect(skipToOAuthURL)
|
||||
return true
|
||||
}
|
||||
|
||||
type preparedSignInData struct {
|
||||
oauth2Providers []oauth2.Provider
|
||||
enableSSPI bool
|
||||
}
|
||||
|
||||
func prepareSignInPageData(ctx *context.Context) (ret preparedSignInData) {
|
||||
var err error
|
||||
ret.enableSSPI = auth.IsSSPIEnabled(ctx)
|
||||
ret.oauth2Providers, err = oauth2.GetOAuth2Providers(ctx, optional.Some(true))
|
||||
if err != nil {
|
||||
log.Error("Failed to get OAuth2 providers: %v", err)
|
||||
}
|
||||
ctx.Data["Title"] = ctx.Tr("sign_in")
|
||||
ctx.Data["OAuth2Providers"], _ = oauth2.GetOAuth2Providers(ctx, optional.Some(true))
|
||||
ctx.Data["OAuth2Providers"] = ret.oauth2Providers
|
||||
ctx.Data["Title"] = ctx.Tr("sign_in")
|
||||
ctx.Data["SignInLink"] = setting.AppSubURL + "/user/login"
|
||||
ctx.Data["PageIsSignIn"] = true
|
||||
ctx.Data["PageIsLogin"] = true
|
||||
ctx.Data["EnableSSPI"] = auth.IsSSPIEnabled(ctx)
|
||||
ctx.Data["EnableSSPI"] = ret.enableSSPI
|
||||
|
||||
prepareCommonAuthPageData(ctx, CommonAuthOptions{
|
||||
EnableCaptcha: setting.Service.EnableCaptcha && setting.Service.RequireCaptchaForLogin,
|
||||
})
|
||||
return ret
|
||||
}
|
||||
|
||||
// SignIn render sign in page
|
||||
@@ -241,7 +273,10 @@ func SignIn(ctx *context.Context) {
|
||||
redirectAfterAuth(ctx)
|
||||
return
|
||||
}
|
||||
prepareSignInPageData(ctx)
|
||||
data := prepareSignInPageData(ctx)
|
||||
if performAutoLoginOAuth2(ctx, &data) {
|
||||
return
|
||||
}
|
||||
ctx.HTML(http.StatusOK, tplSignIn)
|
||||
}
|
||||
|
||||
@@ -471,6 +506,7 @@ func prepareSignUpPageData(ctx *context.Context) bool {
|
||||
ctx.Data["Title"] = ctx.Tr("sign_up")
|
||||
ctx.Data["SignUpLink"] = setting.AppSubURL + "/user/sign_up"
|
||||
ctx.Data["PageIsSignUp"] = true
|
||||
ctx.Data["EnableSSPI"] = auth.IsSSPIEnabled(ctx)
|
||||
|
||||
hasUsers, err := user_model.HasUsers(ctx)
|
||||
if err != nil {
|
||||
|
||||
@@ -96,6 +96,37 @@ func TestWebAuthOAuth2(t *testing.T) {
|
||||
assert.Contains(t, ctx.Flash.ErrorMsg, "auth.oauth.signin.error.general")
|
||||
})
|
||||
|
||||
t.Run("RedirectSingleProvider", func(t *testing.T) {
|
||||
enablePassword := &setting.Service.EnablePasswordSignInForm
|
||||
enableOpenID := &setting.Service.EnableOpenIDSignIn
|
||||
enablePasskey := &setting.Service.EnablePasskeyAuth
|
||||
defer test.MockVariableValue(enablePassword, false)()
|
||||
defer test.MockVariableValue(enableOpenID, false)()
|
||||
defer test.MockVariableValue(enablePasskey, false)()
|
||||
|
||||
testSignIn := func(t *testing.T, link string, expectedCode int, expectedRedirect string) {
|
||||
ctx, resp := contexttest.MockContext(t, link)
|
||||
SignIn(ctx)
|
||||
assert.Equal(t, expectedCode, resp.Code)
|
||||
if expectedCode == http.StatusSeeOther {
|
||||
assert.Equal(t, expectedRedirect, test.RedirectURL(resp))
|
||||
}
|
||||
}
|
||||
testSignIn(t, "/user/login", http.StatusSeeOther, "/user/oauth2/dummy-auth-source")
|
||||
testSignIn(t, "/user/login?redirect_to=/", http.StatusSeeOther, "/user/oauth2/dummy-auth-source?redirect_to=%2F")
|
||||
|
||||
*enablePassword, *enableOpenID, *enablePasskey = true, false, false
|
||||
testSignIn(t, "/user/login", http.StatusOK, "")
|
||||
*enablePassword, *enableOpenID, *enablePasskey = false, true, false
|
||||
testSignIn(t, "/user/login", http.StatusOK, "")
|
||||
*enablePassword, *enableOpenID, *enablePasskey = false, false, true
|
||||
testSignIn(t, "/user/login", http.StatusOK, "")
|
||||
|
||||
*enablePassword, *enableOpenID, *enablePasskey = false, false, false
|
||||
addOAuth2Source(t, "dummy-auth-source-2", oauth2.Source{})
|
||||
testSignIn(t, "/user/login", http.StatusOK, "")
|
||||
})
|
||||
|
||||
t.Run("OIDCLogout", func(t *testing.T) {
|
||||
var mockServer *httptest.Server
|
||||
mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
Reference in New Issue
Block a user