mirror of
https://codeberg.org/davrot/forgejo.git
synced 2025-05-28 03:00:03 +02:00
Support scoped access tokens (#20908)
This PR adds the support for scopes of access tokens, mimicking the design of GitHub OAuth scopes. The changes of the core logic are in `models/auth` that `AccessToken` struct will have a `Scope` field. The normalized (no duplication of scope), comma-separated scope string will be stored in `access_token` table in the database. In `services/auth`, the scope will be stored in context, which will be used by `reqToken` middleware in API calls. Only OAuth2 tokens will have granular token scopes, while others like BasicAuth will default to scope `all`. A large amount of work happens in `routers/api/v1/api.go` and the corresponding `tests/integration` tests, that is adding necessary scopes to each of the API calls as they fit. - [x] Add `Scope` field to `AccessToken` - [x] Add access control to all API endpoints - [x] Update frontend & backend for when creating tokens - [x] Add a database migration for `scope` column (enable 'all' access to past tokens) I'm aiming to complete it before Gitea 1.19 release. Fixes #4300
This commit is contained in:
parent
db2286bbb6
commit
de484e86bc
79 changed files with 1221 additions and 449 deletions
|
@ -21,6 +21,7 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
"code.gitea.io/gitea/modules/graceful"
|
||||
"code.gitea.io/gitea/modules/json"
|
||||
|
@ -217,8 +218,8 @@ func emptyTestSession(t testing.TB) *TestSession {
|
|||
return &TestSession{jar: jar}
|
||||
}
|
||||
|
||||
func getUserToken(t testing.TB, userName string) string {
|
||||
return getTokenForLoggedInUser(t, loginUser(t, userName))
|
||||
func getUserToken(t testing.TB, userName string, scope ...auth.AccessTokenScope) string {
|
||||
return getTokenForLoggedInUser(t, loginUser(t, userName), scope...)
|
||||
}
|
||||
|
||||
func loginUser(t testing.TB, userName string) *TestSession {
|
||||
|
@ -256,7 +257,10 @@ func loginUserWithPassword(t testing.TB, userName, password string) *TestSession
|
|||
// token has to be unique this counter take care of
|
||||
var tokenCounter int64
|
||||
|
||||
func getTokenForLoggedInUser(t testing.TB, session *TestSession) string {
|
||||
// getTokenForLoggedInUser returns a token for a logged in user.
|
||||
// The scope is an optional list of snake_case strings like the frontend form fields,
|
||||
// but without the "scope_" prefix.
|
||||
func getTokenForLoggedInUser(t testing.TB, session *TestSession, scopes ...auth.AccessTokenScope) string {
|
||||
t.Helper()
|
||||
var token string
|
||||
req := NewRequest(t, "GET", "/user/settings/applications")
|
||||
|
@ -274,10 +278,13 @@ func getTokenForLoggedInUser(t testing.TB, session *TestSession) string {
|
|||
csrf = doc.GetCSRF()
|
||||
}
|
||||
assert.NotEmpty(t, csrf)
|
||||
req = NewRequestWithValues(t, "POST", "/user/settings/applications", map[string]string{
|
||||
"_csrf": csrf,
|
||||
"name": fmt.Sprintf("api-testing-token-%d", atomic.AddInt64(&tokenCounter, 1)),
|
||||
})
|
||||
urlValues := url.Values{}
|
||||
urlValues.Add("_csrf", csrf)
|
||||
urlValues.Add("name", fmt.Sprintf("api-testing-token-%d", atomic.AddInt64(&tokenCounter, 1)))
|
||||
for _, scope := range scopes {
|
||||
urlValues.Add("scope", string(scope))
|
||||
}
|
||||
req = NewRequestWithURLValues(t, "POST", "/user/settings/applications", urlValues)
|
||||
resp = session.MakeRequest(t, req, http.StatusSeeOther)
|
||||
|
||||
// Log the flash values on failure
|
||||
|
@ -317,6 +324,11 @@ func NewRequestWithValues(t testing.TB, method, urlStr string, values map[string
|
|||
for key, value := range values {
|
||||
urlValues[key] = []string{value}
|
||||
}
|
||||
return NewRequestWithURLValues(t, method, urlStr, urlValues)
|
||||
}
|
||||
|
||||
func NewRequestWithURLValues(t testing.TB, method, urlStr string, urlValues url.Values) *http.Request {
|
||||
t.Helper()
|
||||
req := NewRequestWithBody(t, method, urlStr, bytes.NewBufferString(urlValues.Encode()))
|
||||
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
||||
return req
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue