Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Anon Endpoints #215

Merged
merged 11 commits into from
Jul 17, 2024
Prev Previous commit
Next Next commit
Return 401 when authentication fails.
  • Loading branch information
TheTedder committed Jul 11, 2024
commit 0278ef9cb6ef7a40f913bd6c0d2b19a890a4bb5d
4 changes: 2 additions & 2 deletions LeaderboardBackend/Authorization/MiddlewareResultHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
64 changes: 23 additions & 41 deletions LeaderboardBackend/Authorization/UserTypeAuthorizationHandler.cs
Original file line number Diff line number Diff line change
@@ -1,28 +1,20 @@
using System.Diagnostics.CodeAnalysis;
using LeaderboardBackend.Models.Entities;
using LeaderboardBackend.Result;
using LeaderboardBackend.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;

namespace LeaderboardBackend.Authorization;

public class UserTypeAuthorizationHandler : AuthorizationHandler<UserTypeRequirement>
public class UserTypeAuthorizationHandler(
IOptions<JwtConfig> config,
IUserService userService
) : AuthorizationHandler<UserTypeRequirement>
{
private readonly IAuthService _authService;
private readonly TokenValidationParameters _jwtValidationParams;
private readonly IUserService _userService;

public UserTypeAuthorizationHandler(
IAuthService authService,
IOptions<JwtConfig> 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,
Expand All @@ -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
Expand Down