mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2026-04-21 17:16:56 -04:00
Some checks are pending
/ release (push) Waiting to run
testing-integration / test-unit (push) Waiting to run
testing-integration / test-sqlite (push) Waiting to run
testing-integration / test-mariadb (v10.6) (push) Waiting to run
testing-integration / test-mariadb (v11.8) (push) Waiting to run
testing / backend-checks (push) Waiting to run
testing / frontend-checks (push) Waiting to run
testing / test-unit (push) Blocked by required conditions
testing / test-e2e (push) Blocked by required conditions
testing / test-remote-cacher (redis) (push) Blocked by required conditions
testing / test-remote-cacher (valkey) (push) Blocked by required conditions
testing / test-remote-cacher (garnet) (push) Blocked by required conditions
testing / test-remote-cacher (redict) (push) Blocked by required conditions
testing / test-mysql (push) Blocked by required conditions
testing / test-pgsql (push) Blocked by required conditions
testing / test-sqlite (push) Blocked by required conditions
testing / security-check (push) Blocked by required conditions
Replace the anti-CSRF token with a [cross origin protection by Go](https://go.dev/doc/go1.25#nethttppkgnethttp) that uses a stateless way of verifying if a request was cross origin or not. This allows is to remove al lot of code and replace it with a few lines of code and we no longer have to hand roll this protection. The new protection uses indicators by the browser itself that indicate if the request is cross-origin, thus we no longer have to take care of ensuring the generated CSRF token is passed back to the server any request by the the browser will have send this indicator. Resolves forgejo/forgejo#3538 Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/9830 Reviewed-by: oliverpool <oliverpool@noreply.codeberg.org> Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org> Co-authored-by: Gusted <postmaster@gusted.xyz> Co-committed-by: Gusted <postmaster@gusted.xyz>
101 lines
3.2 KiB
Go
101 lines
3.2 KiB
Go
// Copyright 2014 The Gogs Authors. All rights reserved.
|
|
// Copyright 2019 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package auth
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"regexp"
|
|
"strings"
|
|
|
|
user_model "forgejo.org/models/user"
|
|
"forgejo.org/modules/auth/webauthn"
|
|
"forgejo.org/modules/log"
|
|
"forgejo.org/modules/optional"
|
|
"forgejo.org/modules/session"
|
|
"forgejo.org/modules/setting"
|
|
"forgejo.org/modules/web/middleware"
|
|
user_service "forgejo.org/services/user"
|
|
)
|
|
|
|
// Init should be called exactly once when the application starts to allow plugins
|
|
// to allocate necessary resources
|
|
func Init() {
|
|
webauthn.Init()
|
|
}
|
|
|
|
// isAttachmentDownload check if request is a file download (GET) with URL to an attachment
|
|
func isAttachmentDownload(req *http.Request) bool {
|
|
return strings.HasPrefix(req.URL.Path, "/attachments/") && req.Method == "GET"
|
|
}
|
|
|
|
// isContainerPath checks if the request targets the container endpoint
|
|
func isContainerPath(req *http.Request) bool {
|
|
return strings.HasPrefix(req.URL.Path, "/v2/")
|
|
}
|
|
|
|
var (
|
|
gitRawOrAttachPathRe = regexp.MustCompile(`^/[a-zA-Z0-9_.-]+/[a-zA-Z0-9_.-]+/(?:(?:git-(?:(?:upload)|(?:receive))-pack$)|(?:info/refs$)|(?:HEAD$)|(?:objects/)|(?:raw/)|(?:releases/download/)|(?:attachments/))`)
|
|
lfsPathRe = regexp.MustCompile(`^/[a-zA-Z0-9_.-]+/[a-zA-Z0-9_.-]+/info/lfs/`)
|
|
archivePathRe = regexp.MustCompile(`^/[a-zA-Z0-9_.-]+/[a-zA-Z0-9_.-]+/archive/`)
|
|
)
|
|
|
|
func isGitRawOrAttachPath(req *http.Request) bool {
|
|
return gitRawOrAttachPathRe.MatchString(req.URL.Path)
|
|
}
|
|
|
|
func isGitRawOrAttachOrLFSPath(req *http.Request) bool {
|
|
if isGitRawOrAttachPath(req) {
|
|
return true
|
|
}
|
|
if setting.LFS.StartServer {
|
|
return lfsPathRe.MatchString(req.URL.Path)
|
|
}
|
|
return false
|
|
}
|
|
|
|
func isArchivePath(req *http.Request) bool {
|
|
return archivePathRe.MatchString(req.URL.Path)
|
|
}
|
|
|
|
// handleSignIn clears existing session variables and stores new ones for the specified user object
|
|
func handleSignIn(resp http.ResponseWriter, req *http.Request, sess SessionStore, user *user_model.User) {
|
|
// We need to regenerate the session...
|
|
newSess, err := session.RegenerateSession(resp, req)
|
|
if err != nil {
|
|
log.Error(fmt.Sprintf("Error regenerating session: %v", err))
|
|
} else {
|
|
sess = newSess
|
|
}
|
|
|
|
_ = sess.Delete("openid_verified_uri")
|
|
_ = sess.Delete("openid_signin_remember")
|
|
_ = sess.Delete("openid_determined_email")
|
|
_ = sess.Delete("openid_determined_username")
|
|
_ = sess.Delete("twofaUid")
|
|
_ = sess.Delete("twofaRemember")
|
|
_ = sess.Delete("twofaOpenID")
|
|
_ = sess.Delete("webauthnAssertion")
|
|
_ = sess.Delete("linkAccount")
|
|
err = sess.Set("uid", user.ID)
|
|
if err != nil {
|
|
log.Error(fmt.Sprintf("Error setting session: %v", err))
|
|
}
|
|
|
|
// Language setting of the user overwrites the one previously set
|
|
// If the user does not have a locale set, we save the current one.
|
|
if len(user.Language) == 0 {
|
|
lc := middleware.Locale(resp, req)
|
|
opts := &user_service.UpdateOptions{
|
|
Language: optional.Some(lc.Language()),
|
|
}
|
|
if err := user_service.UpdateUser(req.Context(), user, opts); err != nil {
|
|
log.Error(fmt.Sprintf("Error updating user language [user: %d, locale: %s]", user.ID, user.Language))
|
|
return
|
|
}
|
|
}
|
|
|
|
middleware.SetLocaleCookie(resp, user.Language, 0)
|
|
}
|