diff --git a/tests/integration/api_token_test.go b/tests/integration/api_token_test.go index 9d9a44b5d4..0899d0abfa 100644 --- a/tests/integration/api_token_test.go +++ b/tests/integration/api_token_test.go @@ -4,8 +4,10 @@ package integration import ( + "encoding/base64" "fmt" "net/http" + "net/url" "testing" auth_model "forgejo.org/models/auth" @@ -13,9 +15,11 @@ import ( user_model "forgejo.org/models/user" "forgejo.org/modules/log" api "forgejo.org/modules/structs" + "forgejo.org/modules/test" "forgejo.org/tests" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) // TestAPICreateAndDeleteToken tests that token that was just created can be deleted @@ -580,3 +584,80 @@ func deleteAPIAccessToken(t *testing.T, accessToken api.AccessToken, user *user_ unittest.AssertNotExistsBean(t, &auth_model.AccessToken{ID: accessToken.ID}) } + +func TestAPITokenCreation(t *testing.T) { + defer tests.PrepareTestEnv(t)() + + session := loginUser(t, "user4") + t.Run("Via API token", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteUser) + + req := NewRequestWithJSON(t, "POST", "/api/v1/users/user4/tokens", map[string]any{ + "name": "new-new-token", + "scopes": []auth_model.AccessTokenScope{auth_model.AccessTokenScopeWriteUser}, + }) + req.Request.Header.Set("Authorization", "basic "+base64.StdEncoding.EncodeToString([]byte("user4:"+token))) + + resp := MakeRequest(t, req, http.StatusUnauthorized) + + respMsg := map[string]any{} + DecodeJSON(t, resp, &respMsg) + + assert.EqualValues(t, "auth method not allowed", respMsg["message"]) + }) + + t.Run("Via OAuth2", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + req := NewRequestWithValues(t, "POST", "/login/oauth/grant", map[string]string{ + "_csrf": GetCSRF(t, session, "/login/oauth/authorize?client_id=ce5a1322-42a7-11ed-b878-0242ac120002&redirect_uri=b&response_type=code&code_challenge_method=plain&code_challenge=CODE&state=thestate"), + "client_id": "ce5a1322-42a7-11ed-b878-0242ac120002", + "redirect_uri": "b", + "state": "thestate", + "granted": "true", + }) + resp := session.MakeRequest(t, req, http.StatusSeeOther) + + u, err := url.Parse(test.RedirectURL(resp)) + require.NoError(t, err) + + req = NewRequestWithValues(t, "POST", "/login/oauth/access_token", map[string]string{ + "client_id": "ce5a1322-42a7-11ed-b878-0242ac120002", + "code": u.Query().Get("code"), + "code_verifier": "CODE", + "grant_type": "authorization_code", + "redirect_uri": "b", + }) + resp = MakeRequest(t, req, http.StatusOK) + + var respBody map[string]any + DecodeJSON(t, resp, &respBody) + + req = NewRequestWithJSON(t, "POST", "/api/v1/users/user4/tokens", map[string]any{ + "name": "new-new-token", + "scopes": []auth_model.AccessTokenScope{auth_model.AccessTokenScopeWriteUser}, + }) + req.Request.Header.Set("Authorization", "basic "+base64.StdEncoding.EncodeToString([]byte("user4:"+respBody["access_token"].(string)))) + + resp = MakeRequest(t, req, http.StatusUnauthorized) + + respMsg := map[string]any{} + DecodeJSON(t, resp, &respMsg) + + assert.EqualValues(t, "auth method not allowed", respMsg["message"]) + }) + + t.Run("Via password", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + req := NewRequestWithJSON(t, "POST", "/api/v1/users/user4/tokens", map[string]any{ + "name": "new-new-token", + "scopes": []auth_model.AccessTokenScope{auth_model.AccessTokenScopeWriteUser}, + }) + req.Request.Header.Set("Authorization", "basic "+base64.StdEncoding.EncodeToString([]byte("user4:"+userPassword))) + + MakeRequest(t, req, http.StatusCreated) + }) +}