refactor: api token scope check (#38862)

"ApiTokenScope" already means "IsApiToken=true".

All "IsApiToken" should be removed.

---------

Signed-off-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
wxiaoguang
2026-08-11 09:37:44 +02:00
committed by GitHub
parent 7e3eeca779
commit b3f547ac16
12 changed files with 19 additions and 47 deletions
+3 -3
View File
@@ -40,9 +40,9 @@ import (
func reqPackageAccess(accessMode perm.AccessMode) func(ctx *context.Context) {
return func(ctx *context.Context) {
if ctx.Data["IsApiToken"] == true {
scope, ok := ctx.Data["ApiTokenScope"].(auth_model.AccessTokenScope)
if ok { // it's a personal access token but not oauth2 token
scope, hasApiTokenScope := ctx.Data["ApiTokenScope"].(auth_model.AccessTokenScope)
if hasApiTokenScope {
{ // request authenticated by a scoped token; enforce package scope restrictions
scopeMatched := false
var err error
switch accessMode {
-1
View File
@@ -52,7 +52,6 @@ func (a *Auth) Verify(req *http.Request, w http.ResponseWriter, store auth.DataS
}
if packageMeta.Scope != "" {
store.GetData()["IsApiToken"] = true
store.GetData()["ApiTokenScope"] = packageMeta.Scope
}
+1 -1
View File
@@ -330,7 +330,7 @@ func tokenRequiresScopes(requiredScopeCategories ...auth_model.AccessTokenScopeC
// Need OAuth2 token to be present.
scope, scopeExists := ctx.Data["ApiTokenScope"].(auth_model.AccessTokenScope)
if ctx.Data["IsApiToken"] != true || !scopeExists {
if !scopeExists {
return
}
+2 -3
View File
@@ -23,12 +23,11 @@ func canAccessReleaseDraft(ctx *context.APIContext) bool {
if !ctx.IsSigned || !ctx.Repo.Permission.CanWrite(unit.TypeReleases) {
return false
}
if ctx.Data["IsApiToken"] != true {
scope, hasApiTokenScope := ctx.Data["ApiTokenScope"].(auth_model.AccessTokenScope)
if !hasApiTokenScope {
// not API token request, the request is from a user session with write access
return true
}
// the request is from an access token with scope
scope := ctx.Data["ApiTokenScope"].(auth_model.AccessTokenScope) //nolint:forcetypeassert // must exist
requiredScopes := auth_model.GetRequiredScopes(auth_model.Write, auth_model.AccessTokenScopeCategoryRepository)
allow, _ := scope.HasScope(requiredScopes...) // err (invalid token) can be safely ignored
return allow
+2 -6
View File
@@ -127,12 +127,8 @@ func CreateAccessToken(ctx *context.APIContext) {
t.Scope = scope
// a token-authenticated request must not mint a token with a broader scope than its own
if ctx.Data["IsApiToken"] == true {
apiTokenScope, ok := ctx.Data["ApiTokenScope"].(auth_model.AccessTokenScope)
if !ok {
ctx.APIError(http.StatusForbidden, "the authenticating token has no scope")
return
}
apiTokenScope, hasApiTokenScope := ctx.Data["ApiTokenScope"].(auth_model.AccessTokenScope)
if hasApiTokenScope {
hasScope, err := apiTokenScope.CanCreateChildScope(scope)
if err != nil {
ctx.APIErrorInternal(err)
+2 -5
View File
@@ -127,13 +127,10 @@ func goGetDefaultBranch(ctx *context.Context, repo *repo_model.Repository) strin
// always may; a token request may only when its scope grants repository read, so a PAT that was never
// scoped for repositories cannot disclose the branch even if its owner can read the repo.
func goGetTokenCanReadRepo(ctx *context.Context) bool {
if ctx.Data["IsApiToken"] != true {
scope, hasApiTokenScope := ctx.Data["ApiTokenScope"].(auth_model.AccessTokenScope)
if !hasApiTokenScope {
return true
}
scope, ok := ctx.Data["ApiTokenScope"].(auth_model.AccessTokenScope)
if !ok {
return false
}
has, err := scope.HasScope(auth_model.AccessTokenScopeReadRepository)
return err == nil && has
}
+1 -1
View File
@@ -163,7 +163,7 @@ func httpBase(ctx *context.Context, optGitService ...string) *serviceHandler {
return nil
}
if ctx.IsBasicAuth && ctx.Data["IsApiToken"] != true && !ctx.Doer.IsGiteaActions() {
if ctx.IsBasicAuth && ctx.Data["ApiTokenScope"] == nil && !ctx.Doer.IsGiteaActions() {
_, err = auth_model.GetTwoFactorByUID(ctx, ctx.Doer.ID)
if err == nil {
// TODO: This response should be changed to "invalid credentials" for security reasons once the expectation behind it (creating an app token to authenticate) is properly documented
+2 -6
View File
@@ -82,12 +82,8 @@ func ApplicationsPost(ctx *context.Context) {
// a token-authenticated request must not mint a token with a broader scope than its own, nor
// drop the public-only restriction. Web routes accept basic-auth PATs/OAuth tokens too, so this
// must mirror the REST API guard in routers/api/v1/user/app.go.
if ctx.Data["IsApiToken"] == true {
apiTokenScope, ok := ctx.Data["ApiTokenScope"].(auth_model.AccessTokenScope)
if !ok {
ctx.HTTPError(http.StatusForbidden, "the authenticating token has no scope")
return
}
apiTokenScope, hasApiTokenScope := ctx.Data["ApiTokenScope"].(auth_model.AccessTokenScope)
if hasApiTokenScope {
hasScope, err := apiTokenScope.CanCreateChildScope(t.Scope)
if err != nil {
ctx.ServerError("CanCreateChildScope", err)