From 9ec9139f69421516c5786edde517ce2cbaf271a8 Mon Sep 17 00:00:00 2001 From: martinshoob Date: Mon, 11 Aug 2025 19:47:12 +0200 Subject: [PATCH] Enhance AdminOnly authorization policy Refactor the AdminOnly authorization policy to handle cases where a user profile is not found. Instead of throwing a NotFoundException, it now throws a ForbiddenException, ensuring a more appropriate response for unauthorized access attempts. Also introduces PolicyConstants for policy names. --- .../AuthorizationPolicies/AdminOnlyRequirement.cs | 12 +++++++++++- .../AuthorizationPolicies/PolicyConstants.cs | 7 +++++++ DrinkRateAPI/Controllers/UserProfileController.cs | 3 ++- DrinkRateAPI/Program.cs | 3 ++- 4 files changed, 22 insertions(+), 3 deletions(-) create mode 100644 DrinkRateAPI/AuthorizationPolicies/PolicyConstants.cs diff --git a/DrinkRateAPI/AuthorizationPolicies/AdminOnlyRequirement.cs b/DrinkRateAPI/AuthorizationPolicies/AdminOnlyRequirement.cs index f850568..c6d18a2 100644 --- a/DrinkRateAPI/AuthorizationPolicies/AdminOnlyRequirement.cs +++ b/DrinkRateAPI/AuthorizationPolicies/AdminOnlyRequirement.cs @@ -1,4 +1,5 @@ using DrinkRateAPI.DbEntities; +using DrinkRateAPI.Exceptions; using DrinkRateAPI.Services; namespace DrinkRateAPI.AuthorizationPolicies; @@ -26,7 +27,16 @@ public class AdminOnlyHandler : AuthorizationHandler AuthorizationHandlerContext context, AdminOnlyRequirement requirement) { - var userProfile = await _applicationUserService.UserProfileByApplicationUserAsync(context.User); + DbUserProfile userProfile; + + try + { + userProfile = await _applicationUserService.UserProfileByApplicationUserAsync(context.User); + } + catch (NotFoundException _) + { + throw new ForbiddenException(); + } if (_userProfileService.IsUserProfileAdmin(userProfile)) { diff --git a/DrinkRateAPI/AuthorizationPolicies/PolicyConstants.cs b/DrinkRateAPI/AuthorizationPolicies/PolicyConstants.cs new file mode 100644 index 0000000..fc37305 --- /dev/null +++ b/DrinkRateAPI/AuthorizationPolicies/PolicyConstants.cs @@ -0,0 +1,7 @@ +namespace DrinkRateAPI.AuthorizationPolicies; + +public static class PolicyConstants +{ + public const string AdminOnly = "AdminOnly"; + +} \ No newline at end of file diff --git a/DrinkRateAPI/Controllers/UserProfileController.cs b/DrinkRateAPI/Controllers/UserProfileController.cs index 7c4cfa0..6b3a064 100644 --- a/DrinkRateAPI/Controllers/UserProfileController.cs +++ b/DrinkRateAPI/Controllers/UserProfileController.cs @@ -1,5 +1,6 @@ using System.Security.Claims; using DrinkRateAPI.ApiModels.UserProfile; +using DrinkRateAPI.AuthorizationPolicies; using DrinkRateAPI.Services; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; @@ -28,7 +29,7 @@ public class UserProfileController : ControllerBase } [HttpPut("{userId}/adminStatus")] - [Authorize(Policy = "AdminOnly")] + [Authorize(Policy = PolicyConstants.AdminOnly)] [Produces("application/json")] public async Task PutUserAdminStatus(string userId, [FromBody] UserProfileAdminStatusPut body) { diff --git a/DrinkRateAPI/Program.cs b/DrinkRateAPI/Program.cs index 9da7e7d..c6f0c33 100644 --- a/DrinkRateAPI/Program.cs +++ b/DrinkRateAPI/Program.cs @@ -15,7 +15,7 @@ builder.Services.AddControllers(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddAuthorizationBuilder() - .AddPolicy("AdminOnly", policy => + .AddPolicy(PolicyConstants.AdminOnly, policy => policy.Requirements.Add(new AdminOnlyRequirement())); builder.Services.AddIdentityApiEndpoints() .AddEntityFrameworkStores(); @@ -58,6 +58,7 @@ builder.Services.AddSwaggerGen(c => builder.Services.AddDbContext(); builder.Services.AddScoped(); builder.Services.AddScoped(); +builder.Services.AddScoped(); var app = builder.Build();