From 8b7c227619ee3525da4611e6b8581518df0fa1fd Mon Sep 17 00:00:00 2001 From: Laura Hausmann Date: Tue, 30 Jan 2024 19:50:00 +0100 Subject: [PATCH] Validate scopes on /api/v1/apps --- .../Mastodon/MastodonAuthController.cs | 12 ++++++++++++ .../Core/Helpers/MastodonOauthHelpers.cs | 19 ++++++++++++++++--- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/Iceshrimp.Backend/Controllers/Mastodon/MastodonAuthController.cs b/Iceshrimp.Backend/Controllers/Mastodon/MastodonAuthController.cs index f6786c63..db17e27d 100644 --- a/Iceshrimp.Backend/Controllers/Mastodon/MastodonAuthController.cs +++ b/Iceshrimp.Backend/Controllers/Mastodon/MastodonAuthController.cs @@ -45,6 +45,18 @@ public class MastodonAuthController(DatabaseContext db) : Controller { if (request.RedirectUris.Any(p => !MastodonOauthHelpers.ValidateRedirectUri(p))) throw GracefulException.BadRequest("redirect_uris parameter contains invalid protocols"); + if (!MastodonOauthHelpers.ValidateScopes(request.Scopes)) + throw GracefulException.BadRequest("Invalid scopes parameter"); + + if (request.Website != null) + try { + var uri = new Uri(request.Website); + if (!uri.IsAbsoluteUri || uri.Scheme is "http" or "https") throw new Exception(); + } + catch { + throw GracefulException.BadRequest("Invalid website URL"); + } + var app = new OauthApp { Id = IdHelpers.GenerateSlowflakeId(), ClientId = CryptographyHelpers.GenerateRandomString(32), diff --git a/Iceshrimp.Backend/Core/Helpers/MastodonOauthHelpers.cs b/Iceshrimp.Backend/Core/Helpers/MastodonOauthHelpers.cs index be4063f5..e6e245c2 100644 --- a/Iceshrimp.Backend/Core/Helpers/MastodonOauthHelpers.cs +++ b/Iceshrimp.Backend/Core/Helpers/MastodonOauthHelpers.cs @@ -40,6 +40,15 @@ public static class MastodonOauthHelpers { "write:mutes" ]; + private static readonly List ScopeGroups = [ + "read", + "write", + "follow", + "push" + ]; + + private static readonly List ForbiddenSchemes = ["javascript", "file", "data", "mailto", "tel"]; + public static IEnumerable ExpandScopes(IEnumerable scopes) { var res = new List(); foreach (var scope in scopes) { @@ -49,15 +58,19 @@ public static class MastodonOauthHelpers { res.AddRange(WriteScopes); if (scope == "follow") res.AddRange(FollowScopes); - else { + else res.Add(scope); - } } return res.Distinct(); } - private static readonly List ForbiddenSchemes = ["javascript", "file", "data", "mailto", "tel"]; + public static bool ValidateScopes(List scopes) { + if (scopes.Distinct().Count() < scopes.Count) return false; + + var validScopes = ScopeGroups.Concat(ReadScopes).Concat(WriteScopes).Concat(FollowScopes); + return !scopes.Except(validScopes).Any(); + } public static bool ValidateRedirectUri(string uri) { if (uri == "urn:ietf:wg:oauth:2.0:oob") return true;