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