Skip to content

Commit c043b9f

Browse files
committed
Improved token validation
1 parent e7fa0f4 commit c043b9f

File tree

4 files changed

+39
-8
lines changed

4 files changed

+39
-8
lines changed

src/Exceptionless.Web/Controllers/Base/ExceptionlessApiController.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,9 @@ protected bool ShouldApplySystemFilter(AppFilter sf, string? filter)
181181

182182
protected ObjectResult Permission(PermissionResult permission)
183183
{
184+
if (permission.StatusCode is StatusCodes.Status422UnprocessableEntity)
185+
return (ObjectResult)ValidationProblem(ModelState);
186+
184187
if (String.IsNullOrEmpty(permission.Message))
185188
return Problem(statusCode: permission.StatusCode);
186189

src/Exceptionless.Web/Controllers/Base/PermissionResult.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
namespace Exceptionless.Web.Controllers;
1+
namespace Exceptionless.Web.Controllers;
22

33
public record PermissionResult
44
{
@@ -56,4 +56,13 @@ public static PermissionResult DenyWithPlanLimitReached(string message, string?
5656
StatusCode = StatusCodes.Status426UpgradeRequired
5757
};
5858
}
59+
60+
public static PermissionResult DenyWithValidationProblem()
61+
{
62+
return new PermissionResult
63+
{
64+
Allowed = false,
65+
StatusCode = StatusCodes.Status422UnprocessableEntity
66+
};
67+
}
5968
}

src/Exceptionless.Web/Controllers/TokenController.cs

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
using Foundatio.Repositories;
1111
using Microsoft.AspNetCore.Authorization;
1212
using Microsoft.AspNetCore.Mvc;
13+
using Microsoft.AspNetCore.Mvc.ModelBinding;
1314

1415
namespace Exceptionless.App.Controllers.API;
1516

@@ -279,26 +280,41 @@ protected override async Task<PermissionResult> CanAddAsync(Token value)
279280
}
280281

281282
if (!AuthorizationRoles.AllScopes.Contains(lowerCaseScoped))
282-
return PermissionResult.DenyWithMessage("Invalid token scope requested.");
283+
{
284+
ModelState.AddModelError<Token>(m => m.Scopes, "Invalid token scope requested.");
285+
return PermissionResult.DenyWithValidationProblem();
286+
}
283287
}
284288

285289
if (value.Scopes.Count == 0)
286290
value.Scopes.Add(AuthorizationRoles.Client);
287291

288292
if (value.Scopes.Contains(AuthorizationRoles.Client) && !hasUserRole)
289-
return PermissionResult.Deny;
293+
{
294+
ModelState.AddModelError<Token>(m => m.Scopes, "Invalid token scope requested.");
295+
return PermissionResult.DenyWithValidationProblem();
296+
}
290297

291298
if (value.Scopes.Contains(AuthorizationRoles.User) && !hasUserRole)
292-
return PermissionResult.Deny;
299+
{
300+
ModelState.AddModelError<Token>(m => m.Scopes, "Invalid token scope requested.");
301+
return PermissionResult.DenyWithValidationProblem();
302+
}
293303

294304
if (value.Scopes.Contains(AuthorizationRoles.GlobalAdmin) && !hasGlobalAdminRole)
295-
return PermissionResult.Deny;
305+
{
306+
ModelState.AddModelError<Token>(m => m.Scopes, "Invalid token scope requested.");
307+
return PermissionResult.DenyWithValidationProblem();
308+
}
296309

297310
if (!String.IsNullOrEmpty(value.ProjectId))
298311
{
299312
var project = await GetProjectAsync(value.ProjectId);
300313
if (project is null)
301-
return PermissionResult.Deny;
314+
{
315+
ModelState.AddModelError<Token>(m => m.ProjectId, "Please specify a valid project id.");
316+
return PermissionResult.DenyWithValidationProblem();
317+
}
302318

303319
value.OrganizationId = project.OrganizationId;
304320
value.DefaultProjectId = null;
@@ -308,7 +324,10 @@ protected override async Task<PermissionResult> CanAddAsync(Token value)
308324
{
309325
var project = await GetProjectAsync(value.DefaultProjectId);
310326
if (project is null)
311-
return PermissionResult.Deny;
327+
{
328+
ModelState.AddModelError<Token>(m => m.DefaultProjectId, "Please specify a valid default project id.");
329+
return PermissionResult.DenyWithValidationProblem();
330+
}
312331
}
313332

314333
return await base.CanAddAsync(value);

tests/Exceptionless.Tests/Controllers/TokenControllerTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ public async Task ShouldPreventAddingUserScopeToTokenWithoutElevatedRole()
201201
ProjectId = SampleDataService.TEST_PROJECT_ID,
202202
Scopes = [AuthorizationRoles.Client, AuthorizationRoles.User, AuthorizationRoles.GlobalAdmin]
203203
})
204-
.StatusCodeShouldBeBadRequest() // NOTE: This status code could be better.
204+
.StatusCodeShouldBeUnprocessableEntity()
205205
);
206206

207207
Assert.NotNull(problemDetails);

0 commit comments

Comments
 (0)