Revert "feat: remove API authentication methods that uses the URL query (#7924)" (#8633)

This reverts commit b2a3966e64.

weblate etc. are using this method and need to be updated before the change is enforced.

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/8633
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
Co-authored-by: Earl Warren <contact@earl-warren.org>
Co-committed-by: Earl Warren <contact@earl-warren.org>
This commit is contained in:
Earl Warren 2025-07-24 17:19:24 +02:00 committed by Earl Warren
parent 87a7bf2436
commit bfa9c89e6f
8 changed files with 64 additions and 0 deletions

View file

@ -35,6 +35,7 @@ var (
PasswordHashAlgo string
PasswordCheckPwn bool
SuccessfulTokensCacheSize int
DisableQueryAuthToken bool
CSRFCookieName = "_csrf"
CSRFCookieHTTPOnly = true
)
@ -159,4 +160,14 @@ func loadSecurityFrom(rootCfg ConfigProvider) {
PasswordComplexity = append(PasswordComplexity, name)
}
}
sectionHasDisableQueryAuthToken := sec.HasKey("DISABLE_QUERY_AUTH_TOKEN")
// TODO: default value should be true in future releases
DisableQueryAuthToken = sec.Key("DISABLE_QUERY_AUTH_TOKEN").MustBool(false)
// warn if the setting is set to false explicitly
if sectionHasDisableQueryAuthToken && !DisableQueryAuthToken {
log.Warn("Enabling Query API Auth tokens is not recommended. DISABLE_QUERY_AUTH_TOKEN will default to true in gitea 1.23 and will be removed in gitea 1.24.")
}
}

View file

@ -30,6 +30,7 @@ func Middlewares() (stack []any) {
return append(stack,
context.APIContexter(),
checkDeprecatedAuthMethods,
// Get user from session if logged in.
apiAuth(buildAuthGroup()),
verifyAuthWithOptions(&common.VerifyOptions{
@ -126,6 +127,13 @@ func verifyAuthWithOptions(options *common.VerifyOptions) func(ctx *context.APIC
}
}
// check for and warn against deprecated authentication options
func checkDeprecatedAuthMethods(ctx *context.APIContext) {
if ctx.FormString("token") != "" || ctx.FormString("access_token") != "" {
ctx.Resp.Header().Set("Warning", "token and access_token API authentication is deprecated and will be removed in gitea 1.23. Please use AuthorizationHeaderToken instead. Existing queries will continue to work but without authorization.")
}
}
func securityHeaders() func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {

View file

@ -22,6 +22,8 @@
//
// Security:
// - BasicAuth :
// - Token :
// - AccessToken :
// - AuthorizationHeaderToken :
// - SudoParam :
// - SudoHeader :
@ -30,6 +32,16 @@
// SecurityDefinitions:
// BasicAuth:
// type: basic
// Token:
// type: apiKey
// name: token
// in: query
// description: This authentication option is deprecated for removal in Forgejo v13.0.0. Please use AuthorizationHeaderToken instead.
// AccessToken:
// type: apiKey
// name: access_token
// in: query
// description: This authentication option is deprecated for removal in Forgejo v13.0.0. Please use AuthorizationHeaderToken instead.
// AuthorizationHeaderToken:
// type: apiKey
// name: Authorization

View file

@ -122,6 +122,18 @@ func (o *OAuth2) Name() string {
// representing whether the token exists or not
func parseToken(req *http.Request) (string, bool) {
_ = req.ParseForm()
if !setting.DisableQueryAuthToken {
// Check token.
if token := req.Form.Get("token"); token != "" {
return token, true
}
// Check access token.
if token := req.Form.Get("access_token"); token != "" {
return token, true
}
} else if req.Form.Get("token") != "" || req.Form.Get("access_token") != "" {
log.Warn("API token sent in query string but DISABLE_QUERY_AUTH_TOKEN=true")
}
// check header token
if auHead := req.Header.Get("Authorization"); auHead != "" {

View file

@ -30084,6 +30084,12 @@
}
},
"securityDefinitions": {
"AccessToken": {
"description": "This authentication option is deprecated for removal in Forgejo v13.0.0. Please use AuthorizationHeaderToken instead.",
"type": "apiKey",
"name": "access_token",
"in": "query"
},
"AuthorizationHeaderToken": {
"description": "API tokens must be prepended with \"token\" followed by a space.",
"type": "apiKey",
@ -30110,12 +30116,24 @@
"type": "apiKey",
"name": "X-FORGEJO-OTP",
"in": "header"
},
"Token": {
"description": "This authentication option is deprecated for removal in Forgejo v13.0.0. Please use AuthorizationHeaderToken instead.",
"type": "apiKey",
"name": "token",
"in": "query"
}
},
"security": [
{
"BasicAuth": []
},
{
"Token": []
},
{
"AccessToken": []
},
{
"AuthorizationHeaderToken": []
},

View file

@ -92,6 +92,7 @@ DISABLE_GIT_HOOKS = false
INSTALL_LOCK = true
SECRET_KEY = 9pCviYTWSb
INTERNAL_TOKEN = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE0OTU1NTE2MTh9.hhSVGOANkaKk3vfCd2jDOIww4pUk0xtg9JRde5UogyQ
DISABLE_QUERY_AUTH_TOKEN = true
[lfs]
PATH = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-mysql/data/lfs

View file

@ -97,6 +97,7 @@ DISABLE_GIT_HOOKS = false
INSTALL_LOCK = true
SECRET_KEY = 9pCviYTWSb
INTERNAL_TOKEN = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE0OTU1NTE2MTh9.hhSVGOANkaKk3vfCd2jDOIww4pUk0xtg9JRde5UogyQ
DISABLE_QUERY_AUTH_TOKEN = true
[lfs]
MINIO_BASE_PATH = lfs/

View file

@ -94,6 +94,7 @@ DISABLE_GIT_HOOKS = false
INSTALL_LOCK = true
SECRET_KEY = 9pCviYTWSb
INTERNAL_TOKEN = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE0OTI3OTU5ODN9.OQkH5UmzID2XBdwQ9TAI6Jj2t1X-wElVTjbE7aoN4I8
DISABLE_QUERY_AUTH_TOKEN = true
[oauth2]
JWT_SECRET = KZb_QLUd4fYVyxetjxC4eZkrBgWM2SndOOWDNtgUUko