From 1b37944f8b8eccc2afcfb0f603786209a3b7402d Mon Sep 17 00:00:00 2001 From: tobi <31960611+tsmethurst@users.noreply.github.com> Date: Mon, 3 Mar 2025 16:03:36 +0100 Subject: [feature] Refactor tokens, allow multiple app redirect_uris (#3849) * [feature] Refactor tokens, allow multiple app redirect_uris * move + tweak handlers a bit * return error for unset oauth2.ClientStore funcs * wrap UpdateToken with cache * panic handling * cheeky little time optimization * unlock on error --- internal/api/activitypub/users/user_test.go | 2 - internal/api/auth/auth_test.go | 2 - internal/api/auth/token_test.go | 101 +++++++++++++++++---- internal/api/client/accounts/account_test.go | 2 - internal/api/client/admin/admin_test.go | 2 - internal/api/client/bookmarks/bookmarks_test.go | 2 - internal/api/client/exports/exports_test.go | 2 - internal/api/client/favourites/favourites_test.go | 2 - internal/api/client/filters/v1/filter_test.go | 2 - internal/api/client/filters/v2/filter_test.go | 2 - .../api/client/followedtags/followedtags_test.go | 2 - .../client/followrequests/followrequest_test.go | 2 - internal/api/client/import/import_test.go | 2 - internal/api/client/instance/instance_test.go | 2 - internal/api/client/lists/lists_test.go | 2 - internal/api/client/media/mediacreate_test.go | 4 +- internal/api/client/media/mediaupdate_test.go | 4 +- internal/api/client/mutes/mutes_test.go | 2 - .../api/client/notifications/notifications_test.go | 2 - internal/api/client/polls/polls_test.go | 2 - internal/api/client/push/push_test.go | 2 - internal/api/client/reports/reports_test.go | 2 - internal/api/client/search/search_test.go | 2 - internal/api/client/statuses/status_test.go | 2 - internal/api/client/streaming/streaming_test.go | 2 - internal/api/client/tags/tags_test.go | 2 - internal/api/client/user/user_test.go | 2 - internal/api/fileserver/fileserver_test.go | 4 +- internal/api/model/application.go | 14 ++- internal/api/util/scopes.go | 26 +++++- internal/api/util/scopes_test.go | 10 ++ internal/api/wellknown/webfinger/webfinger_test.go | 4 +- .../api/wellknown/webfinger/webfingerget_test.go | 2 +- 33 files changed, 130 insertions(+), 87 deletions(-) (limited to 'internal/api') diff --git a/internal/api/activitypub/users/user_test.go b/internal/api/activitypub/users/user_test.go index d66fe8cf9..c57d9f8c4 100644 --- a/internal/api/activitypub/users/user_test.go +++ b/internal/api/activitypub/users/user_test.go @@ -50,7 +50,6 @@ type UserStandardTestSuite struct { // standard suite models testTokens map[string]*gtsmodel.Token - testClients map[string]*gtsmodel.Client testApplications map[string]*gtsmodel.Application testUsers map[string]*gtsmodel.User testAccounts map[string]*gtsmodel.Account @@ -67,7 +66,6 @@ type UserStandardTestSuite struct { func (suite *UserStandardTestSuite) SetupSuite() { suite.testTokens = testrig.NewTestTokens() - suite.testClients = testrig.NewTestClients() suite.testApplications = testrig.NewTestApplications() suite.testUsers = testrig.NewTestUsers() suite.testAccounts = testrig.NewTestAccounts() diff --git a/internal/api/auth/auth_test.go b/internal/api/auth/auth_test.go index cfbdec7ec..3bf3ec593 100644 --- a/internal/api/auth/auth_test.go +++ b/internal/api/auth/auth_test.go @@ -55,7 +55,6 @@ type AuthStandardTestSuite struct { // standard suite models testTokens map[string]*gtsmodel.Token - testClients map[string]*gtsmodel.Client testApplications map[string]*gtsmodel.Application testUsers map[string]*gtsmodel.User testAccounts map[string]*gtsmodel.Account @@ -71,7 +70,6 @@ const ( func (suite *AuthStandardTestSuite) SetupSuite() { suite.testTokens = testrig.NewTestTokens() - suite.testClients = testrig.NewTestClients() suite.testApplications = testrig.NewTestApplications() suite.testUsers = testrig.NewTestUsers() suite.testAccounts = testrig.NewTestAccounts() diff --git a/internal/api/auth/token_test.go b/internal/api/auth/token_test.go index 1c53b5b2e..1a12fe37e 100644 --- a/internal/api/auth/token_test.go +++ b/internal/api/auth/token_test.go @@ -20,7 +20,7 @@ package auth_test import ( "context" "encoding/json" - "io/ioutil" + "io" "net/http" "testing" "time" @@ -47,21 +47,21 @@ func (suite *TokenTestSuite) TestPOSTTokenEmptyForm() { result := recorder.Result() defer result.Body.Close() - b, err := ioutil.ReadAll(result.Body) + b, err := io.ReadAll(result.Body) suite.NoError(err) suite.Equal(`{"error":"invalid_request","error_description":"Bad Request: grant_type was not set in the token request form, but must be set to authorization_code or client_credentials: client_id was not set in the token request form: client_secret was not set in the token request form: redirect_uri was not set in the token request form"}`, string(b)) } func (suite *TokenTestSuite) TestRetrieveClientCredentialsOK() { - testClient := suite.testClients["local_account_1"] + testApp := suite.testApplications["application_1"] requestBody, w, err := testrig.CreateMultipartFormData( nil, map[string][]string{ "grant_type": {"client_credentials"}, - "client_id": {testClient.ID}, - "client_secret": {testClient.Secret}, + "client_id": {testApp.ClientID}, + "client_secret": {testApp.ClientSecret}, "redirect_uri": {"http://localhost:8080"}, }) if err != nil { @@ -79,7 +79,7 @@ func (suite *TokenTestSuite) TestRetrieveClientCredentialsOK() { result := recorder.Result() defer result.Body.Close() - b, err := ioutil.ReadAll(result.Body) + b, err := io.ReadAll(result.Body) suite.NoError(err) t := &apimodel.Token{} @@ -98,16 +98,81 @@ func (suite *TokenTestSuite) TestRetrieveClientCredentialsOK() { suite.NotNil(dbToken) } +func (suite *TokenTestSuite) TestRetrieveClientCredentialsBadScope() { + testApp := suite.testApplications["application_1"] + + requestBody, w, err := testrig.CreateMultipartFormData( + nil, + map[string][]string{ + "grant_type": {"client_credentials"}, + "client_id": {testApp.ClientID}, + "client_secret": {testApp.ClientSecret}, + "redirect_uri": {"http://localhost:8080"}, + "scope": {"admin"}, + }) + if err != nil { + panic(err) + } + bodyBytes := requestBody.Bytes() + + ctx, recorder := suite.newContext(http.MethodPost, "oauth/token", bodyBytes, w.FormDataContentType()) + ctx.Request.Header.Set("accept", "application/json") + + suite.authModule.TokenPOSTHandler(ctx) + + suite.Equal(http.StatusForbidden, recorder.Code) + + result := recorder.Result() + defer result.Body.Close() + + b, err := io.ReadAll(result.Body) + suite.NoError(err) + + suite.Equal(`{"error":"invalid_scope","error_description":"Forbidden: requested scope admin was not covered by client scope: If you arrived at this error during a sign in/oauth flow, please try clearing your session cookies and signing in again; if problems persist, make sure you're using the correct credentials"}`, string(b)) +} + +func (suite *TokenTestSuite) TestRetrieveClientCredentialsDifferentRedirectURI() { + testApp := suite.testApplications["application_1"] + + requestBody, w, err := testrig.CreateMultipartFormData( + nil, + map[string][]string{ + "grant_type": {"client_credentials"}, + "client_id": {testApp.ClientID}, + "client_secret": {testApp.ClientSecret}, + "redirect_uri": {"http://somewhere.else.example.org"}, + }) + if err != nil { + panic(err) + } + bodyBytes := requestBody.Bytes() + + ctx, recorder := suite.newContext(http.MethodPost, "oauth/token", bodyBytes, w.FormDataContentType()) + ctx.Request.Header.Set("accept", "application/json") + + suite.authModule.TokenPOSTHandler(ctx) + + suite.Equal(http.StatusForbidden, recorder.Code) + + result := recorder.Result() + defer result.Body.Close() + + b, err := io.ReadAll(result.Body) + suite.NoError(err) + + suite.Equal(`{"error":"invalid redirect uri","error_description":"Forbidden: requested redirect URI http://somewhere.else.example.org was not covered by client redirect URIs: If you arrived at this error during a sign in/oauth flow, please try clearing your session cookies and signing in again; if problems persist, make sure you're using the correct credentials"}`, string(b)) +} + func (suite *TokenTestSuite) TestRetrieveAuthorizationCodeOK() { - testClient := suite.testClients["local_account_1"] + testApp := suite.testApplications["application_1"] testUserAuthorizationToken := suite.testTokens["local_account_1_user_authorization_token"] requestBody, w, err := testrig.CreateMultipartFormData( nil, map[string][]string{ "grant_type": {"authorization_code"}, - "client_id": {testClient.ID}, - "client_secret": {testClient.Secret}, + "client_id": {testApp.ClientID}, + "client_secret": {testApp.ClientSecret}, "redirect_uri": {"http://localhost:8080"}, "code": {testUserAuthorizationToken.Code}, }) @@ -126,7 +191,7 @@ func (suite *TokenTestSuite) TestRetrieveAuthorizationCodeOK() { result := recorder.Result() defer result.Body.Close() - b, err := ioutil.ReadAll(result.Body) + b, err := io.ReadAll(result.Body) suite.NoError(err) t := &apimodel.Token{} @@ -145,14 +210,14 @@ func (suite *TokenTestSuite) TestRetrieveAuthorizationCodeOK() { } func (suite *TokenTestSuite) TestRetrieveAuthorizationCodeNoCode() { - testClient := suite.testClients["local_account_1"] + testApp := suite.testApplications["application_1"] requestBody, w, err := testrig.CreateMultipartFormData( nil, map[string][]string{ "grant_type": {"authorization_code"}, - "client_id": {testClient.ID}, - "client_secret": {testClient.Secret}, + "client_id": {testApp.ClientID}, + "client_secret": {testApp.ClientSecret}, "redirect_uri": {"http://localhost:8080"}, }) if err != nil { @@ -170,21 +235,21 @@ func (suite *TokenTestSuite) TestRetrieveAuthorizationCodeNoCode() { result := recorder.Result() defer result.Body.Close() - b, err := ioutil.ReadAll(result.Body) + b, err := io.ReadAll(result.Body) suite.NoError(err) suite.Equal(`{"error":"invalid_request","error_description":"Bad Request: code was not set in the token request form, but must be set since grant_type is authorization_code"}`, string(b)) } func (suite *TokenTestSuite) TestRetrieveAuthorizationCodeWrongGrantType() { - testClient := suite.testClients["local_account_1"] + testApplication := suite.testApplications["application_1"] requestBody, w, err := testrig.CreateMultipartFormData( nil, map[string][]string{ "grant_type": {"client_credentials"}, - "client_id": {testClient.ID}, - "client_secret": {testClient.Secret}, + "client_id": {testApplication.ClientID}, + "client_secret": {testApplication.ClientSecret}, "redirect_uri": {"http://localhost:8080"}, "code": {"peepeepoopoo"}, }) @@ -203,7 +268,7 @@ func (suite *TokenTestSuite) TestRetrieveAuthorizationCodeWrongGrantType() { result := recorder.Result() defer result.Body.Close() - b, err := ioutil.ReadAll(result.Body) + b, err := io.ReadAll(result.Body) suite.NoError(err) suite.Equal(`{"error":"invalid_request","error_description":"Bad Request: a code was provided in the token request form, but grant_type was not set to authorization_code"}`, string(b)) diff --git a/internal/api/client/accounts/account_test.go b/internal/api/client/accounts/account_test.go index e700ade78..3daa71c91 100644 --- a/internal/api/client/accounts/account_test.go +++ b/internal/api/client/accounts/account_test.go @@ -56,7 +56,6 @@ type AccountStandardTestSuite struct { // standard suite models testTokens map[string]*gtsmodel.Token - testClients map[string]*gtsmodel.Client testApplications map[string]*gtsmodel.Application testUsers map[string]*gtsmodel.User testAccounts map[string]*gtsmodel.Account @@ -69,7 +68,6 @@ type AccountStandardTestSuite struct { func (suite *AccountStandardTestSuite) SetupSuite() { suite.testTokens = testrig.NewTestTokens() - suite.testClients = testrig.NewTestClients() suite.testApplications = testrig.NewTestApplications() suite.testUsers = testrig.NewTestUsers() suite.testAccounts = testrig.NewTestAccounts() diff --git a/internal/api/client/admin/admin_test.go b/internal/api/client/admin/admin_test.go index f44d48d78..6bc777119 100644 --- a/internal/api/client/admin/admin_test.go +++ b/internal/api/client/admin/admin_test.go @@ -56,7 +56,6 @@ type AdminStandardTestSuite struct { // standard suite models testTokens map[string]*gtsmodel.Token - testClients map[string]*gtsmodel.Client testApplications map[string]*gtsmodel.Application testUsers map[string]*gtsmodel.User testAccounts map[string]*gtsmodel.Account @@ -72,7 +71,6 @@ type AdminStandardTestSuite struct { func (suite *AdminStandardTestSuite) SetupSuite() { suite.testTokens = testrig.NewTestTokens() - suite.testClients = testrig.NewTestClients() suite.testApplications = testrig.NewTestApplications() suite.testUsers = testrig.NewTestUsers() suite.testAccounts = testrig.NewTestAccounts() diff --git a/internal/api/client/bookmarks/bookmarks_test.go b/internal/api/client/bookmarks/bookmarks_test.go index a11597f7c..3608078b9 100644 --- a/internal/api/client/bookmarks/bookmarks_test.go +++ b/internal/api/client/bookmarks/bookmarks_test.go @@ -61,7 +61,6 @@ type BookmarkTestSuite struct { // standard suite models testTokens map[string]*gtsmodel.Token - testClients map[string]*gtsmodel.Client testApplications map[string]*gtsmodel.Application testUsers map[string]*gtsmodel.User testAccounts map[string]*gtsmodel.Account @@ -77,7 +76,6 @@ type BookmarkTestSuite struct { func (suite *BookmarkTestSuite) SetupSuite() { suite.testTokens = testrig.NewTestTokens() - suite.testClients = testrig.NewTestClients() suite.testApplications = testrig.NewTestApplications() suite.testUsers = testrig.NewTestUsers() suite.testAccounts = testrig.NewTestAccounts() diff --git a/internal/api/client/exports/exports_test.go b/internal/api/client/exports/exports_test.go index 55d873348..6fbeb57d0 100644 --- a/internal/api/client/exports/exports_test.go +++ b/internal/api/client/exports/exports_test.go @@ -44,7 +44,6 @@ type ExportsTestSuite struct { // standard suite models testTokens map[string]*gtsmodel.Token - testClients map[string]*gtsmodel.Client testApplications map[string]*gtsmodel.Application testUsers map[string]*gtsmodel.User testAccounts map[string]*gtsmodel.Account @@ -55,7 +54,6 @@ type ExportsTestSuite struct { func (suite *ExportsTestSuite) SetupSuite() { suite.testTokens = testrig.NewTestTokens() - suite.testClients = testrig.NewTestClients() suite.testApplications = testrig.NewTestApplications() suite.testUsers = testrig.NewTestUsers() suite.testAccounts = testrig.NewTestAccounts() diff --git a/internal/api/client/favourites/favourites_test.go b/internal/api/client/favourites/favourites_test.go index 7cfa205e3..7c65e4b97 100644 --- a/internal/api/client/favourites/favourites_test.go +++ b/internal/api/client/favourites/favourites_test.go @@ -48,7 +48,6 @@ type FavouritesStandardTestSuite struct { // standard suite models testTokens map[string]*gtsmodel.Token - testClients map[string]*gtsmodel.Client testApplications map[string]*gtsmodel.Application testUsers map[string]*gtsmodel.User testAccounts map[string]*gtsmodel.Account @@ -62,7 +61,6 @@ type FavouritesStandardTestSuite struct { func (suite *FavouritesStandardTestSuite) SetupSuite() { suite.testTokens = testrig.NewTestTokens() - suite.testClients = testrig.NewTestClients() suite.testApplications = testrig.NewTestApplications() suite.testUsers = testrig.NewTestUsers() suite.testAccounts = testrig.NewTestAccounts() diff --git a/internal/api/client/filters/v1/filter_test.go b/internal/api/client/filters/v1/filter_test.go index 558f3d959..e0bcf8731 100644 --- a/internal/api/client/filters/v1/filter_test.go +++ b/internal/api/client/filters/v1/filter_test.go @@ -53,7 +53,6 @@ type FiltersTestSuite struct { // standard suite models testTokens map[string]*gtsmodel.Token - testClients map[string]*gtsmodel.Client testApplications map[string]*gtsmodel.Application testUsers map[string]*gtsmodel.User testAccounts map[string]*gtsmodel.Account @@ -68,7 +67,6 @@ type FiltersTestSuite struct { func (suite *FiltersTestSuite) SetupSuite() { suite.testTokens = testrig.NewTestTokens() - suite.testClients = testrig.NewTestClients() suite.testApplications = testrig.NewTestApplications() suite.testUsers = testrig.NewTestUsers() suite.testAccounts = testrig.NewTestAccounts() diff --git a/internal/api/client/filters/v2/filter_test.go b/internal/api/client/filters/v2/filter_test.go index 8301c67ad..af212ac88 100644 --- a/internal/api/client/filters/v2/filter_test.go +++ b/internal/api/client/filters/v2/filter_test.go @@ -53,7 +53,6 @@ type FiltersTestSuite struct { // standard suite models testTokens map[string]*gtsmodel.Token - testClients map[string]*gtsmodel.Client testApplications map[string]*gtsmodel.Application testUsers map[string]*gtsmodel.User testAccounts map[string]*gtsmodel.Account @@ -68,7 +67,6 @@ type FiltersTestSuite struct { func (suite *FiltersTestSuite) SetupSuite() { suite.testTokens = testrig.NewTestTokens() - suite.testClients = testrig.NewTestClients() suite.testApplications = testrig.NewTestApplications() suite.testUsers = testrig.NewTestUsers() suite.testAccounts = testrig.NewTestAccounts() diff --git a/internal/api/client/followedtags/followedtags_test.go b/internal/api/client/followedtags/followedtags_test.go index 816e1d0cc..e7c83ca68 100644 --- a/internal/api/client/followedtags/followedtags_test.go +++ b/internal/api/client/followedtags/followedtags_test.go @@ -48,7 +48,6 @@ type FollowedTagsTestSuite struct { // standard suite models testTokens map[string]*gtsmodel.Token - testClients map[string]*gtsmodel.Client testApplications map[string]*gtsmodel.Application testUsers map[string]*gtsmodel.User testAccounts map[string]*gtsmodel.Account @@ -60,7 +59,6 @@ type FollowedTagsTestSuite struct { func (suite *FollowedTagsTestSuite) SetupSuite() { suite.testTokens = testrig.NewTestTokens() - suite.testClients = testrig.NewTestClients() suite.testApplications = testrig.NewTestApplications() suite.testUsers = testrig.NewTestUsers() suite.testAccounts = testrig.NewTestAccounts() diff --git a/internal/api/client/followrequests/followrequest_test.go b/internal/api/client/followrequests/followrequest_test.go index 787d47c84..fbaf9a560 100644 --- a/internal/api/client/followrequests/followrequest_test.go +++ b/internal/api/client/followrequests/followrequest_test.go @@ -53,7 +53,6 @@ type FollowRequestStandardTestSuite struct { // standard suite models testTokens map[string]*gtsmodel.Token - testClients map[string]*gtsmodel.Client testApplications map[string]*gtsmodel.Application testUsers map[string]*gtsmodel.User testAccounts map[string]*gtsmodel.Account @@ -66,7 +65,6 @@ type FollowRequestStandardTestSuite struct { func (suite *FollowRequestStandardTestSuite) SetupSuite() { suite.testTokens = testrig.NewTestTokens() - suite.testClients = testrig.NewTestClients() suite.testApplications = testrig.NewTestApplications() suite.testUsers = testrig.NewTestUsers() suite.testAccounts = testrig.NewTestAccounts() diff --git a/internal/api/client/import/import_test.go b/internal/api/client/import/import_test.go index 56497d27d..1edb54b64 100644 --- a/internal/api/client/import/import_test.go +++ b/internal/api/client/import/import_test.go @@ -43,7 +43,6 @@ type ImportTestSuite struct { // standard suite models testTokens map[string]*gtsmodel.Token - testClients map[string]*gtsmodel.Client testApplications map[string]*gtsmodel.Application testUsers map[string]*gtsmodel.User testAccounts map[string]*gtsmodel.Account @@ -54,7 +53,6 @@ type ImportTestSuite struct { func (suite *ImportTestSuite) SetupSuite() { suite.testTokens = testrig.NewTestTokens() - suite.testClients = testrig.NewTestClients() suite.testApplications = testrig.NewTestApplications() suite.testUsers = testrig.NewTestUsers() suite.testAccounts = testrig.NewTestAccounts() diff --git a/internal/api/client/instance/instance_test.go b/internal/api/client/instance/instance_test.go index f0427369b..965d09609 100644 --- a/internal/api/client/instance/instance_test.go +++ b/internal/api/client/instance/instance_test.go @@ -55,7 +55,6 @@ type InstanceStandardTestSuite struct { // standard suite models testTokens map[string]*gtsmodel.Token - testClients map[string]*gtsmodel.Client testApplications map[string]*gtsmodel.Application testUsers map[string]*gtsmodel.User testAccounts map[string]*gtsmodel.Account @@ -68,7 +67,6 @@ type InstanceStandardTestSuite struct { func (suite *InstanceStandardTestSuite) SetupSuite() { suite.testTokens = testrig.NewTestTokens() - suite.testClients = testrig.NewTestClients() suite.testApplications = testrig.NewTestApplications() suite.testUsers = testrig.NewTestUsers() suite.testAccounts = testrig.NewTestAccounts() diff --git a/internal/api/client/lists/lists_test.go b/internal/api/client/lists/lists_test.go index 5fd2304c7..65242db25 100644 --- a/internal/api/client/lists/lists_test.go +++ b/internal/api/client/lists/lists_test.go @@ -47,7 +47,6 @@ type ListsStandardTestSuite struct { // standard suite models testTokens map[string]*gtsmodel.Token - testClients map[string]*gtsmodel.Client testApplications map[string]*gtsmodel.Application testUsers map[string]*gtsmodel.User testAccounts map[string]*gtsmodel.Account @@ -64,7 +63,6 @@ type ListsStandardTestSuite struct { func (suite *ListsStandardTestSuite) SetupSuite() { suite.testTokens = testrig.NewTestTokens() - suite.testClients = testrig.NewTestClients() suite.testApplications = testrig.NewTestApplications() suite.testUsers = testrig.NewTestUsers() suite.testAccounts = testrig.NewTestAccounts() diff --git a/internal/api/client/media/mediacreate_test.go b/internal/api/client/media/mediacreate_test.go index d26f2bb7a..fabff595b 100644 --- a/internal/api/client/media/mediacreate_test.go +++ b/internal/api/client/media/mediacreate_test.go @@ -62,7 +62,6 @@ type MediaCreateTestSuite struct { // standard suite models testTokens map[string]*gtsmodel.Token - testClients map[string]*gtsmodel.Client testApplications map[string]*gtsmodel.Application testUsers map[string]*gtsmodel.User testAccounts map[string]*gtsmodel.Account @@ -101,7 +100,7 @@ func (suite *MediaCreateTestSuite) SetupTest() { ) suite.mediaManager = testrig.NewTestMediaManager(&suite.state) - suite.oauthServer = testrig.NewTestOauthServer(suite.db) + suite.oauthServer = testrig.NewTestOauthServer(&suite.state) suite.federator = testrig.NewTestFederator(&suite.state, testrig.NewTestTransportController(&suite.state, testrig.NewMockHTTPClient(nil, "../../../../testrig/media")), suite.mediaManager) suite.emailSender = testrig.NewEmailSender("../../../../web/template/", nil) suite.processor = testrig.NewTestProcessor( @@ -117,7 +116,6 @@ func (suite *MediaCreateTestSuite) SetupTest() { // setup test data suite.testTokens = testrig.NewTestTokens() - suite.testClients = testrig.NewTestClients() suite.testApplications = testrig.NewTestApplications() suite.testUsers = testrig.NewTestUsers() suite.testAccounts = testrig.NewTestAccounts() diff --git a/internal/api/client/media/mediaupdate_test.go b/internal/api/client/media/mediaupdate_test.go index dd115f465..8e033f367 100644 --- a/internal/api/client/media/mediaupdate_test.go +++ b/internal/api/client/media/mediaupdate_test.go @@ -60,7 +60,6 @@ type MediaUpdateTestSuite struct { // standard suite models testTokens map[string]*gtsmodel.Token - testClients map[string]*gtsmodel.Client testApplications map[string]*gtsmodel.Application testUsers map[string]*gtsmodel.User testAccounts map[string]*gtsmodel.Account @@ -99,7 +98,7 @@ func (suite *MediaUpdateTestSuite) SetupTest() { ) suite.mediaManager = testrig.NewTestMediaManager(&suite.state) - suite.oauthServer = testrig.NewTestOauthServer(suite.db) + suite.oauthServer = testrig.NewTestOauthServer(&suite.state) suite.federator = testrig.NewTestFederator(&suite.state, testrig.NewTestTransportController(&suite.state, testrig.NewMockHTTPClient(nil, "../../../../testrig/media")), suite.mediaManager) suite.emailSender = testrig.NewEmailSender("../../../../web/template/", nil) suite.processor = testrig.NewTestProcessor( @@ -115,7 +114,6 @@ func (suite *MediaUpdateTestSuite) SetupTest() { // setup test data suite.testTokens = testrig.NewTestTokens() - suite.testClients = testrig.NewTestClients() suite.testApplications = testrig.NewTestApplications() suite.testUsers = testrig.NewTestUsers() suite.testAccounts = testrig.NewTestAccounts() diff --git a/internal/api/client/mutes/mutes_test.go b/internal/api/client/mutes/mutes_test.go index 3f5686cfb..fdfca4414 100644 --- a/internal/api/client/mutes/mutes_test.go +++ b/internal/api/client/mutes/mutes_test.go @@ -56,7 +56,6 @@ type MutesTestSuite struct { // standard suite models testTokens map[string]*gtsmodel.Token - testClients map[string]*gtsmodel.Client testApplications map[string]*gtsmodel.Application testUsers map[string]*gtsmodel.User testAccounts map[string]*gtsmodel.Account @@ -67,7 +66,6 @@ type MutesTestSuite struct { func (suite *MutesTestSuite) SetupSuite() { suite.testTokens = testrig.NewTestTokens() - suite.testClients = testrig.NewTestClients() suite.testApplications = testrig.NewTestApplications() suite.testUsers = testrig.NewTestUsers() suite.testAccounts = testrig.NewTestAccounts() diff --git a/internal/api/client/notifications/notifications_test.go b/internal/api/client/notifications/notifications_test.go index 5794c0e12..b84e7d768 100644 --- a/internal/api/client/notifications/notifications_test.go +++ b/internal/api/client/notifications/notifications_test.go @@ -48,7 +48,6 @@ type NotificationsTestSuite struct { // standard suite models testTokens map[string]*gtsmodel.Token - testClients map[string]*gtsmodel.Client testApplications map[string]*gtsmodel.Application testUsers map[string]*gtsmodel.User testAccounts map[string]*gtsmodel.Account @@ -63,7 +62,6 @@ type NotificationsTestSuite struct { func (suite *NotificationsTestSuite) SetupSuite() { suite.testTokens = testrig.NewTestTokens() - suite.testClients = testrig.NewTestClients() suite.testApplications = testrig.NewTestApplications() suite.testUsers = testrig.NewTestUsers() suite.testAccounts = testrig.NewTestAccounts() diff --git a/internal/api/client/polls/polls_test.go b/internal/api/client/polls/polls_test.go index 8c2bc8ba1..5df5cf88d 100644 --- a/internal/api/client/polls/polls_test.go +++ b/internal/api/client/polls/polls_test.go @@ -48,7 +48,6 @@ type PollsStandardTestSuite struct { // standard suite models testTokens map[string]*gtsmodel.Token - testClients map[string]*gtsmodel.Client testApplications map[string]*gtsmodel.Application testUsers map[string]*gtsmodel.User testAccounts map[string]*gtsmodel.Account @@ -61,7 +60,6 @@ type PollsStandardTestSuite struct { func (suite *PollsStandardTestSuite) SetupSuite() { suite.testTokens = testrig.NewTestTokens() - suite.testClients = testrig.NewTestClients() suite.testApplications = testrig.NewTestApplications() suite.testUsers = testrig.NewTestUsers() suite.testAccounts = testrig.NewTestAccounts() diff --git a/internal/api/client/push/push_test.go b/internal/api/client/push/push_test.go index 0d85192ff..6a3754546 100644 --- a/internal/api/client/push/push_test.go +++ b/internal/api/client/push/push_test.go @@ -47,7 +47,6 @@ type PushTestSuite struct { // standard suite models testTokens map[string]*gtsmodel.Token - testClients map[string]*gtsmodel.Client testApplications map[string]*gtsmodel.Application testUsers map[string]*gtsmodel.User testAccounts map[string]*gtsmodel.Account @@ -59,7 +58,6 @@ type PushTestSuite struct { func (suite *PushTestSuite) SetupSuite() { suite.testTokens = testrig.NewTestTokens() - suite.testClients = testrig.NewTestClients() suite.testApplications = testrig.NewTestApplications() suite.testUsers = testrig.NewTestUsers() suite.testAccounts = testrig.NewTestAccounts() diff --git a/internal/api/client/reports/reports_test.go b/internal/api/client/reports/reports_test.go index 89240a4b1..da39c78e1 100644 --- a/internal/api/client/reports/reports_test.go +++ b/internal/api/client/reports/reports_test.go @@ -47,7 +47,6 @@ type ReportsStandardTestSuite struct { // standard suite models testTokens map[string]*gtsmodel.Token - testClients map[string]*gtsmodel.Client testApplications map[string]*gtsmodel.Application testUsers map[string]*gtsmodel.User testAccounts map[string]*gtsmodel.Account @@ -60,7 +59,6 @@ type ReportsStandardTestSuite struct { func (suite *ReportsStandardTestSuite) SetupSuite() { suite.testTokens = testrig.NewTestTokens() - suite.testClients = testrig.NewTestClients() suite.testApplications = testrig.NewTestApplications() suite.testUsers = testrig.NewTestUsers() suite.testAccounts = testrig.NewTestAccounts() diff --git a/internal/api/client/search/search_test.go b/internal/api/client/search/search_test.go index 219966c7c..9eb7f08fe 100644 --- a/internal/api/client/search/search_test.go +++ b/internal/api/client/search/search_test.go @@ -55,7 +55,6 @@ type SearchStandardTestSuite struct { // standard suite models testTokens map[string]*gtsmodel.Token - testClients map[string]*gtsmodel.Client testApplications map[string]*gtsmodel.Application testUsers map[string]*gtsmodel.User testAccounts map[string]*gtsmodel.Account @@ -66,7 +65,6 @@ type SearchStandardTestSuite struct { func (suite *SearchStandardTestSuite) SetupSuite() { suite.testTokens = testrig.NewTestTokens() - suite.testClients = testrig.NewTestClients() suite.testApplications = testrig.NewTestApplications() suite.testUsers = testrig.NewTestUsers() suite.testAccounts = testrig.NewTestAccounts() diff --git a/internal/api/client/statuses/status_test.go b/internal/api/client/statuses/status_test.go index c5f2838e8..2b916125e 100644 --- a/internal/api/client/statuses/status_test.go +++ b/internal/api/client/statuses/status_test.go @@ -55,7 +55,6 @@ type StatusStandardTestSuite struct { // standard suite models testTokens map[string]*gtsmodel.Token - testClients map[string]*gtsmodel.Client testApplications map[string]*gtsmodel.Application testUsers map[string]*gtsmodel.User testAccounts map[string]*gtsmodel.Account @@ -176,7 +175,6 @@ func (suite *StatusStandardTestSuite) determinateStatus(rawMap map[string]any) { func (suite *StatusStandardTestSuite) SetupSuite() { suite.testTokens = testrig.NewTestTokens() - suite.testClients = testrig.NewTestClients() suite.testApplications = testrig.NewTestApplications() suite.testUsers = testrig.NewTestUsers() suite.testAccounts = testrig.NewTestAccounts() diff --git a/internal/api/client/streaming/streaming_test.go b/internal/api/client/streaming/streaming_test.go index 00ad2de03..4cc5dc1b2 100644 --- a/internal/api/client/streaming/streaming_test.go +++ b/internal/api/client/streaming/streaming_test.go @@ -61,7 +61,6 @@ type StreamingTestSuite struct { // standard suite models testTokens map[string]*gtsmodel.Token - testClients map[string]*gtsmodel.Client testApplications map[string]*gtsmodel.Application testUsers map[string]*gtsmodel.User testAccounts map[string]*gtsmodel.Account @@ -75,7 +74,6 @@ type StreamingTestSuite struct { func (suite *StreamingTestSuite) SetupSuite() { suite.testTokens = testrig.NewTestTokens() - suite.testClients = testrig.NewTestClients() suite.testApplications = testrig.NewTestApplications() suite.testUsers = testrig.NewTestUsers() suite.testAccounts = testrig.NewTestAccounts() diff --git a/internal/api/client/tags/tags_test.go b/internal/api/client/tags/tags_test.go index c24574d47..4718d5f34 100644 --- a/internal/api/client/tags/tags_test.go +++ b/internal/api/client/tags/tags_test.go @@ -56,7 +56,6 @@ type TagsTestSuite struct { // standard suite models testTokens map[string]*gtsmodel.Token - testClients map[string]*gtsmodel.Client testApplications map[string]*gtsmodel.Application testUsers map[string]*gtsmodel.User testAccounts map[string]*gtsmodel.Account @@ -68,7 +67,6 @@ type TagsTestSuite struct { func (suite *TagsTestSuite) SetupSuite() { suite.testTokens = testrig.NewTestTokens() - suite.testClients = testrig.NewTestClients() suite.testApplications = testrig.NewTestApplications() suite.testUsers = testrig.NewTestUsers() suite.testAccounts = testrig.NewTestAccounts() diff --git a/internal/api/client/user/user_test.go b/internal/api/client/user/user_test.go index 8cf359cd8..8f54c82a0 100644 --- a/internal/api/client/user/user_test.go +++ b/internal/api/client/user/user_test.go @@ -50,7 +50,6 @@ type UserStandardTestSuite struct { state state.State testTokens map[string]*gtsmodel.Token - testClients map[string]*gtsmodel.Client testApplications map[string]*gtsmodel.Application testUsers map[string]*gtsmodel.User testAccounts map[string]*gtsmodel.Account @@ -66,7 +65,6 @@ func (suite *UserStandardTestSuite) SetupTest() { testrig.InitTestLog() suite.testTokens = testrig.NewTestTokens() - suite.testClients = testrig.NewTestClients() suite.testApplications = testrig.NewTestApplications() suite.testUsers = testrig.NewTestUsers() suite.testAccounts = testrig.NewTestAccounts() diff --git a/internal/api/fileserver/fileserver_test.go b/internal/api/fileserver/fileserver_test.go index 9b0580e92..9ba647ff3 100644 --- a/internal/api/fileserver/fileserver_test.go +++ b/internal/api/fileserver/fileserver_test.go @@ -51,7 +51,6 @@ type FileserverTestSuite struct { // standard suite models testTokens map[string]*gtsmodel.Token - testClients map[string]*gtsmodel.Client testApplications map[string]*gtsmodel.Application testUsers map[string]*gtsmodel.User testAccounts map[string]*gtsmodel.Account @@ -100,7 +99,7 @@ func (suite *FileserverTestSuite) SetupSuite() { ) suite.mediaManager = testrig.NewTestMediaManager(&suite.state) - suite.oauthServer = testrig.NewTestOauthServer(suite.db) + suite.oauthServer = testrig.NewTestOauthServer(&suite.state) suite.emailSender = testrig.NewEmailSender("../../../web/template/", nil) suite.fileServer = fileserver.New(suite.processor) @@ -118,7 +117,6 @@ func (suite *FileserverTestSuite) SetupTest() { testrig.StandardStorageSetup(suite.storage, "../../../testrig/media") suite.testTokens = testrig.NewTestTokens() - suite.testClients = testrig.NewTestClients() suite.testApplications = testrig.NewTestApplications() suite.testUsers = testrig.NewTestUsers() suite.testAccounts = testrig.NewTestAccounts() diff --git a/internal/api/model/application.go b/internal/api/model/application.go index 0770772b7..720674ad5 100644 --- a/internal/api/model/application.go +++ b/internal/api/model/application.go @@ -33,12 +33,17 @@ type Application struct { // Post-authorization redirect URI for the application (OAuth2). // example: https://example.org/callback?some=query RedirectURI string `json:"redirect_uri,omitempty"` + // Post-authorization redirect URIs for the application (OAuth2). + // example: [https://example.org/callback?some=query] + RedirectURIs []string `json:"redirect_uris,omitempty"` // Client ID associated with this application. ClientID string `json:"client_id,omitempty"` // Client secret associated with this application. ClientSecret string `json:"client_secret,omitempty"` // Push API key for this application. VapidKey string `json:"vapid_key,omitempty"` + // OAuth scopes for this application. + Scopes []string `json:"scopes,omitempty"` } // ApplicationCreateRequest models app create parameters. @@ -50,14 +55,15 @@ type ApplicationCreateRequest struct { // in: formData // required: true ClientName string `form:"client_name" json:"client_name" xml:"client_name" binding:"required"` - // Where the user should be redirected after authorization. + // Single redirect URI or newline-separated list of redirect URIs (optional). // // To display the authorization code to the user instead of redirecting to a web page, use `urn:ietf:wg:oauth:2.0:oob` in this parameter. // + // If no redirect URIs are provided, defaults to `urn:ietf:wg:oauth:2.0:oob`. + // // in: formData - // required: true - RedirectURIs string `form:"redirect_uris" json:"redirect_uris" xml:"redirect_uris" binding:"required"` - // Space separated list of scopes. + RedirectURIs string `form:"redirect_uris" json:"redirect_uris" xml:"redirect_uris"` + // Space separated list of scopes (optional). // // If no scopes are provided, defaults to `read`. // diff --git a/internal/api/util/scopes.go b/internal/api/util/scopes.go index d02d3cc0d..8161de500 100644 --- a/internal/api/util/scopes.go +++ b/internal/api/util/scopes.go @@ -93,11 +93,29 @@ const ( // scope permits the wanted scope. func (has Scope) Permits(wanted Scope) bool { if has == wanted { - // Exact match. + // Exact match on either a + // top-level or granular scope. return true } - // Check if we have a parent scope of what's wanted, - // eg., we have scope "admin", we want "admin:read". - return strings.HasPrefix(string(wanted), string(has)) + // Ensure we have a + // known top-level scope. + switch has { + + case ScopeProfile, + ScopePush, + ScopeRead, + ScopeWrite, + ScopeAdmin, + ScopeAdminRead, + ScopeAdminWrite: + // Check if top-level includes wanted, + // eg., have "admin", want "admin:read". + return strings.HasPrefix(string(wanted), string(has)+":") + + default: + // Unknown top-level scope, + // can't permit anything. + return false + } } diff --git a/internal/api/util/scopes_test.go b/internal/api/util/scopes_test.go index bd533585b..72f6b57aa 100644 --- a/internal/api/util/scopes_test.go +++ b/internal/api/util/scopes_test.go @@ -89,6 +89,16 @@ func TestScopes(t *testing.T) { WantsScope: util.ScopeWrite, Expect: false, }, + { + HasScope: util.ScopeProfile, + WantsScope: util.ScopePush, + Expect: false, + }, + { + HasScope: util.Scope("p"), + WantsScope: util.ScopePush, + Expect: false, + }, } { res := test.HasScope.Permits(test.WantsScope) if res != test.Expect { diff --git a/internal/api/wellknown/webfinger/webfinger_test.go b/internal/api/wellknown/webfinger/webfinger_test.go index 234c1ad16..d6521aff0 100644 --- a/internal/api/wellknown/webfinger/webfinger_test.go +++ b/internal/api/wellknown/webfinger/webfinger_test.go @@ -50,7 +50,6 @@ type WebfingerStandardTestSuite struct { // standard suite models testTokens map[string]*gtsmodel.Token - testClients map[string]*gtsmodel.Client testApplications map[string]*gtsmodel.Application testUsers map[string]*gtsmodel.User testAccounts map[string]*gtsmodel.Account @@ -63,7 +62,6 @@ type WebfingerStandardTestSuite struct { func (suite *WebfingerStandardTestSuite) SetupSuite() { suite.testTokens = testrig.NewTestTokens() - suite.testClients = testrig.NewTestClients() suite.testApplications = testrig.NewTestApplications() suite.testUsers = testrig.NewTestUsers() suite.testAccounts = testrig.NewTestAccounts() @@ -102,7 +100,7 @@ func (suite *WebfingerStandardTestSuite) SetupTest() { suite.mediaManager, ) suite.webfingerModule = webfinger.New(suite.processor) - suite.oauthServer = testrig.NewTestOauthServer(suite.db) + suite.oauthServer = testrig.NewTestOauthServer(&suite.state) testrig.StandardDBSetup(suite.db, suite.testAccounts) testrig.StandardStorageSetup(suite.storage, "../../../../testrig/media") } diff --git a/internal/api/wellknown/webfinger/webfingerget_test.go b/internal/api/wellknown/webfinger/webfingerget_test.go index 4bb6f323d..1707584a5 100644 --- a/internal/api/wellknown/webfinger/webfingerget_test.go +++ b/internal/api/wellknown/webfinger/webfingerget_test.go @@ -94,7 +94,7 @@ func (suite *WebfingerGetTestSuite) funkifyAccountDomain(host string, accountDom subscriptions.New(&suite.state, suite.federator.TransportController(), suite.tc), suite.tc, suite.federator, - testrig.NewTestOauthServer(suite.db), + testrig.NewTestOauthServer(&suite.state), testrig.NewTestMediaManager(&suite.state), &suite.state, suite.emailSender, -- cgit v1.2.3