From 0278ef9cb6ef7a40f913bd6c0d2b19a890a4bb5d Mon Sep 17 00:00:00 2001 From: Ted Wollman <25165500+TheTedder@users.noreply.github.com> Date: Wed, 10 Jul 2024 22:08:34 -0400 Subject: [PATCH] Return 401 when authentication fails. --- .../Authorization/MiddlewareResultHandler.cs | 4 +- .../UserTypeAuthorizationHandler.cs | 64 +++++++------------ 2 files changed, 25 insertions(+), 43 deletions(-) diff --git a/LeaderboardBackend/Authorization/MiddlewareResultHandler.cs b/LeaderboardBackend/Authorization/MiddlewareResultHandler.cs index e1242655..1d5ff711 100644 --- a/LeaderboardBackend/Authorization/MiddlewareResultHandler.cs +++ b/LeaderboardBackend/Authorization/MiddlewareResultHandler.cs @@ -15,9 +15,9 @@ public async Task HandleAsync( PolicyAuthorizationResult policyAuthorizationResult ) { - if (policyAuthorizationResult.Forbidden) + if (policyAuthorizationResult.AuthorizationFailure?.FailureReasons.Any(fr => fr.Handler is UserTypeAuthorizationHandler) ?? false) { - httpContext.Response.StatusCode = (int)HttpStatusCode.NotFound; + httpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized; return; } diff --git a/LeaderboardBackend/Authorization/UserTypeAuthorizationHandler.cs b/LeaderboardBackend/Authorization/UserTypeAuthorizationHandler.cs index d6cc5628..d7f524ba 100644 --- a/LeaderboardBackend/Authorization/UserTypeAuthorizationHandler.cs +++ b/LeaderboardBackend/Authorization/UserTypeAuthorizationHandler.cs @@ -1,5 +1,6 @@ using System.Diagnostics.CodeAnalysis; using LeaderboardBackend.Models.Entities; +using LeaderboardBackend.Result; using LeaderboardBackend.Services; using Microsoft.AspNetCore.Authorization; using Microsoft.Extensions.Options; @@ -7,22 +8,13 @@ namespace LeaderboardBackend.Authorization; -public class UserTypeAuthorizationHandler : AuthorizationHandler +public class UserTypeAuthorizationHandler( + IOptions config, + IUserService userService + ) : AuthorizationHandler { - private readonly IAuthService _authService; - private readonly TokenValidationParameters _jwtValidationParams; - private readonly IUserService _userService; - - public UserTypeAuthorizationHandler( - IAuthService authService, - IOptions config, - IUserService userService - ) - { - _authService = authService; - _jwtValidationParams = Jwt.ValidationParameters.GetInstance(config.Value); - _userService = userService; - } + private readonly TokenValidationParameters _jwtValidationParams = Jwt.ValidationParameters.GetInstance(config.Value); + private readonly IUserService _userService = userService; protected override async Task HandleRequirementAsync( AuthorizationHandlerContext context, @@ -34,37 +26,27 @@ UserTypeRequirement requirement return; } - Guid? userId = _authService.GetUserIdFromClaims(context.User); + GetUserResult res = await _userService.GetUserFromClaims(context.User); - if (userId is null) + res.Switch(user => { - context.Fail(); - return; - } - - User? user = _userService.GetUserById(userId.Value).Result; - - if (user is null || !Handle(user, requirement)) - { - // FIXME: Work out how to fail as a ForbiddenResult. - context.Fail(); - return; - } - - context.Succeed(requirement); - - return; + if (Handle(user, requirement)) + { + context.Succeed(requirement); + } + else + { + context.Fail(); + } + }, badCredentials => context.Fail(new(this, "Bad Credentials")), notFound => context.Fail(new(this, "User Not Found"))); } - private bool Handle(User user, UserTypeRequirement requirement) + private static bool Handle(User user, UserTypeRequirement requirement) => requirement.Type switch { - return requirement.Type switch - { - UserTypes.ADMINISTRATOR => user.IsAdmin, - UserTypes.USER => true, - _ => false, - }; - } + UserTypes.ADMINISTRATOR => user.IsAdmin, + UserTypes.USER => true, + _ => false, + }; private static bool TryGetJwtFromHttpContext( AuthorizationHandlerContext context, [NotNullWhen(true)] out string? token