Skip to content

WIP: Rationalise Disable Basic Authentication and SSO #15186

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 19 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion cmd/web_graceful.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ import (
"net"
"net/http"
"net/http/fcgi"
"strings"

"code.gitea.io/gitea/modules/graceful"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
)

func runHTTP(network, listenAddr, name string, m http.Handler) error {
Expand Down Expand Up @@ -48,7 +50,12 @@ func runFCGI(network, listenAddr, name string, m http.Handler) error {
fcgiServer := graceful.NewServer(network, listenAddr, name)

err := fcgiServer.ListenAndServe(func(listener net.Listener) error {
return fcgi.Serve(listener, m)
return fcgi.Serve(listener, http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
if setting.AppSubURL != "" {
req.URL.Path = strings.TrimPrefix(req.URL.Path, setting.AppSubURL)
}
m.ServeHTTP(resp, req)
}))
})
if err != nil {
log.Fatal("Failed to start FCGI main server: %v", err)
Expand Down
2 changes: 1 addition & 1 deletion integrations/api_repo_lfs_locks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func TestAPILFSLocksNotLogin(t *testing.T) {
resp := MakeRequest(t, req, http.StatusUnauthorized)
var lfsLockError api.LFSLockError
DecodeJSON(t, resp, &lfsLockError)
assert.Equal(t, "Unauthorized", lfsLockError.Message)
assert.Equal(t, "You must have pull access to list locks", lfsLockError.Message)
}

func TestAPILFSLocksLogged(t *testing.T) {
Expand Down
7 changes: 5 additions & 2 deletions modules/context/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@ import (
"strings"

"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/auth/sso"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/web/middleware"
"code.gitea.io/gitea/services/auth"

"gitea.com/go-chi/session"
)
Expand Down Expand Up @@ -219,6 +220,7 @@ func (ctx *APIContext) CheckForOTP() {

// APIContexter returns apicontext as middleware
func APIContexter() func(http.Handler) http.Handler {
var rnd = templates.HTMLRenderer()
var csrfOpts = getCsrfOpts()

return func(next http.Handler) http.Handler {
Expand All @@ -228,6 +230,7 @@ func APIContexter() func(http.Handler) http.Handler {
var ctx = APIContext{
Context: &Context{
Resp: NewResponse(w),
Render: rnd,
Data: map[string]interface{}{},
Locale: locale,
Session: session.GetSession(req),
Expand All @@ -251,7 +254,7 @@ func APIContexter() func(http.Handler) http.Handler {
}

// Get user from session if logged in.
ctx.User, ctx.IsBasicAuth = sso.SignedInUser(ctx.Req, ctx.Resp, &ctx, ctx.Session)
ctx.User, ctx.IsBasicAuth = auth.SignedInUser(ctx.Req, ctx.Resp, &ctx, ctx.Session)
if ctx.User != nil {
ctx.IsSigned = true
ctx.Data["IsSigned"] = ctx.IsSigned
Expand Down
58 changes: 12 additions & 46 deletions modules/context/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,14 @@ import (
"time"

"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/auth/sso"
"code.gitea.io/gitea/modules/base"
mc "code.gitea.io/gitea/modules/cache"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/translation"
"code.gitea.io/gitea/modules/web/middleware"
"code.gitea.io/gitea/services/auth"

"gitea.com/go-chi/cache"
"gitea.com/go-chi/session"
Expand Down Expand Up @@ -617,50 +617,7 @@ func Contexter() func(next http.Handler) http.Handler {
ctx.csrf = Csrfer(csrfOpts, &ctx)

// Get flash.
flashCookie := ctx.GetCookie("macaron_flash")
vals, _ := url.ParseQuery(flashCookie)
if len(vals) > 0 {
f := &middleware.Flash{
DataStore: &ctx,
Values: vals,
ErrorMsg: vals.Get("error"),
SuccessMsg: vals.Get("success"),
InfoMsg: vals.Get("info"),
WarningMsg: vals.Get("warning"),
}
ctx.Data["Flash"] = f
}

f := &middleware.Flash{
DataStore: &ctx,
Values: url.Values{},
ErrorMsg: "",
WarningMsg: "",
InfoMsg: "",
SuccessMsg: "",
}
ctx.Resp.Before(func(resp ResponseWriter) {
if flash := f.Encode(); len(flash) > 0 {
middleware.SetCookie(resp, "macaron_flash", flash, 0,
setting.SessionConfig.CookiePath,
middleware.Domain(setting.SessionConfig.Domain),
middleware.HTTPOnly(true),
middleware.Secure(setting.SessionConfig.Secure),
middleware.SameSite(setting.SessionConfig.SameSite),
)
return
}

middleware.SetCookie(ctx.Resp, "macaron_flash", "", -1,
setting.SessionConfig.CookiePath,
middleware.Domain(setting.SessionConfig.Domain),
middleware.HTTPOnly(true),
middleware.Secure(setting.SessionConfig.Secure),
middleware.SameSite(setting.SessionConfig.SameSite),
)
})

ctx.Flash = f
setupFlash(&ctx)

// If request sends files, parse them here otherwise the Query() can't be parsed and the CsrfToken will be invalid.
if ctx.Req.Method == "POST" && strings.Contains(ctx.Req.Header.Get("Content-Type"), "multipart/form-data") {
Expand All @@ -671,7 +628,7 @@ func Contexter() func(next http.Handler) http.Handler {
}

// Get user from session if logged in.
ctx.User, ctx.IsBasicAuth = sso.SignedInUser(ctx.Req, ctx.Resp, &ctx, ctx.Session)
ctx.User, ctx.IsBasicAuth = auth.SignedInUser(ctx.Req, ctx.Resp, &ctx, ctx.Session)

if ctx.User != nil {
ctx.IsSigned = true
Expand All @@ -683,6 +640,9 @@ func Contexter() func(next http.Handler) http.Handler {
} else {
ctx.Data["SignedUserID"] = int64(0)
ctx.Data["SignedUserName"] = ""

// delete the session uid
_ = ctx.Session.Delete("uid")
}

ctx.Resp.Header().Set(`X-Frame-Options`, `SAMEORIGIN`)
Expand All @@ -692,6 +652,7 @@ func Contexter() func(next http.Handler) http.Handler {
log.Debug("Session ID: %s", ctx.Session.ID())
log.Debug("CSRF Token: %v", ctx.Data["CsrfToken"])

// FIXME: do we really always need these setting?
ctx.Data["IsLandingPageHome"] = setting.LandingPageURL == setting.LandingPageHome
ctx.Data["IsLandingPageExplore"] = setting.LandingPageURL == setting.LandingPageExplore
ctx.Data["IsLandingPageOrganizations"] = setting.LandingPageURL == setting.LandingPageOrganizations
Expand All @@ -707,6 +668,11 @@ func Contexter() func(next http.Handler) http.Handler {

ctx.Data["ManifestData"] = setting.ManifestData

ctx.Data["UnitWikiGlobalDisabled"] = models.UnitTypeWiki.UnitGlobalDisabled()
ctx.Data["UnitIssuesGlobalDisabled"] = models.UnitTypeIssues.UnitGlobalDisabled()
ctx.Data["UnitPullsGlobalDisabled"] = models.UnitTypePullRequests.UnitGlobalDisabled()
ctx.Data["UnitProjectsGlobalDisabled"] = models.UnitTypeProjects.UnitGlobalDisabled()

ctx.Data["i18n"] = locale
ctx.Data["Tr"] = i18n.Tr
ctx.Data["Lang"] = locale.Language()
Expand Down
70 changes: 70 additions & 0 deletions modules/context/flash.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// Copyright 2021 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package context

import (
"net/url"

"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/web/middleware"
)

func setupFlash(ctx *Context) {

// Get the temporary flash cookie from the request
flashCookie := ctx.GetCookie("macaron_flash")

// Parse its data
vals, _ := url.ParseQuery(flashCookie)
if len(vals) > 0 {
// If there is content then create a flash struct containing this data
f := &middleware.Flash{
DataStore: ctx,
Values: vals,
ErrorMsg: vals.Get("error"),
SuccessMsg: vals.Get("success"),
InfoMsg: vals.Get("info"),
WarningMsg: vals.Get("warning"),
}
// And stick it in the context datastore
ctx.Data["Flash"] = f
}

// Now create a new empty Flash struct for this response
f := &middleware.Flash{
DataStore: ctx,
Values: url.Values{},
ErrorMsg: "",
WarningMsg: "",
InfoMsg: "",
SuccessMsg: "",
}

// Add a handler to write/delete the cookie before the response is written
ctx.Resp.Before(func(resp ResponseWriter) {
if flash := f.Encode(); len(flash) > 0 {
// If our flash object contains data - then save it to the cookie
middleware.SetCookie(resp, "macaron_flash", flash, 0,
setting.SessionConfig.CookiePath,
middleware.Domain(setting.SessionConfig.Domain),
middleware.HTTPOnly(true),
middleware.Secure(setting.SessionConfig.Secure),
middleware.SameSite(setting.SessionConfig.SameSite),
)
return
}
// Otherwise delete the flash cookie
middleware.SetCookie(ctx.Resp, "macaron_flash", "", -1,
setting.SessionConfig.CookiePath,
middleware.Domain(setting.SessionConfig.Domain),
middleware.HTTPOnly(true),
middleware.Secure(setting.SessionConfig.Secure),
middleware.SameSite(setting.SessionConfig.SameSite),
)
})

// Save the new empty Flash as ctx.Flash
ctx.Flash = f
}
Loading