feat(api): add authentication middleware and request context
This commit is contained in:
22
src/IncidentOps.Api/Auth/ClaimsPrincipalExtensions.cs
Normal file
22
src/IncidentOps.Api/Auth/ClaimsPrincipalExtensions.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using System.Security.Claims;
|
||||
using IncidentOps.Domain.Enums;
|
||||
|
||||
namespace IncidentOps.Api.Auth;
|
||||
|
||||
public static class ClaimsPrincipalExtensions
|
||||
{
|
||||
public static RequestContext GetRequestContext(this ClaimsPrincipal principal)
|
||||
{
|
||||
var userId = Guid.Parse(principal.FindFirstValue("sub") ?? throw new InvalidOperationException("Missing sub claim"));
|
||||
var orgId = Guid.Parse(principal.FindFirstValue("org_id") ?? throw new InvalidOperationException("Missing org_id claim"));
|
||||
var roleStr = principal.FindFirstValue("org_role") ?? throw new InvalidOperationException("Missing org_role claim");
|
||||
var role = Enum.Parse<OrgRole>(roleStr, ignoreCase: true);
|
||||
|
||||
return new RequestContext
|
||||
{
|
||||
UserId = userId,
|
||||
OrgId = orgId,
|
||||
Role = role
|
||||
};
|
||||
}
|
||||
}
|
||||
10
src/IncidentOps.Api/Auth/RequestContext.cs
Normal file
10
src/IncidentOps.Api/Auth/RequestContext.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
using IncidentOps.Domain.Enums;
|
||||
|
||||
namespace IncidentOps.Api.Auth;
|
||||
|
||||
public class RequestContext
|
||||
{
|
||||
public Guid UserId { get; set; }
|
||||
public Guid OrgId { get; set; }
|
||||
public OrgRole Role { get; set; }
|
||||
}
|
||||
38
src/IncidentOps.Api/Auth/RoleRequirement.cs
Normal file
38
src/IncidentOps.Api/Auth/RoleRequirement.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using IncidentOps.Domain.Enums;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
|
||||
namespace IncidentOps.Api.Auth;
|
||||
|
||||
public class RoleRequirement : IAuthorizationRequirement
|
||||
{
|
||||
public OrgRole MinimumRole { get; }
|
||||
|
||||
public RoleRequirement(OrgRole minimumRole)
|
||||
{
|
||||
MinimumRole = minimumRole;
|
||||
}
|
||||
}
|
||||
|
||||
public class RoleRequirementHandler : AuthorizationHandler<RoleRequirement>
|
||||
{
|
||||
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, RoleRequirement requirement)
|
||||
{
|
||||
var roleClaim = context.User.FindFirst("org_role")?.Value;
|
||||
if (roleClaim == null)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
if (!Enum.TryParse<OrgRole>(roleClaim, ignoreCase: true, out var userRole))
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
if (userRole >= requirement.MinimumRole)
|
||||
{
|
||||
context.Succeed(requirement);
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user