Initial commit
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Backend.Security.Authorization {
|
||||
public sealed class AuthorizedAttribute : TypeFilterAttribute {
|
||||
public AuthorizedAttribute(params string[] permission) : base(typeof(AuthorizedFilter)) {
|
||||
Arguments = new object[] { permission };
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
|
||||
namespace Backend.Security.Authorization {
|
||||
public class AuthorizedFilter : IAuthorizationFilter {
|
||||
private readonly string[] _permissions;
|
||||
|
||||
public AuthorizedFilter(params string[] permissions) {
|
||||
_permissions = permissions;
|
||||
}
|
||||
|
||||
public void OnAuthorization(AuthorizationFilterContext context) {
|
||||
if (EndpointHasAllowAnonymousFilter(context)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsAuthenticated(context)) {
|
||||
context.Result = new UnauthorizedResult();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ContainsRequiredRole(context)) {
|
||||
context.Result = new ForbidResult();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool EndpointHasAllowAnonymousFilter(AuthorizationFilterContext context) {
|
||||
return context.Filters.Any(item => item is IAllowAnonymousFilter);
|
||||
}
|
||||
|
||||
private bool IsAuthenticated(AuthorizationFilterContext context) {
|
||||
return context.HttpContext.User.Identity.IsAuthenticated;
|
||||
}
|
||||
|
||||
private bool ContainsRequiredRole(AuthorizationFilterContext context) {
|
||||
if (context.HttpContext.User.HasClaim(CustomClaimTypes.Permission, "*"))
|
||||
return true;
|
||||
|
||||
var perms = context.HttpContext.User.Claims
|
||||
.Where(c => c.Type == CustomClaimTypes.Permission)
|
||||
.Select(c => c.Value).ToArray();
|
||||
|
||||
if (context.RouteData.Values.ContainsKey("userId")) {
|
||||
var accessedUser = context.RouteData.Values["userId"] as string;
|
||||
|
||||
if (accessedUser == context.HttpContext.User.GetUserId()) {
|
||||
var selfPerms = _permissions.Where(p => p.StartsWith("self.")).ToArray();
|
||||
|
||||
if (!selfPerms.Any())
|
||||
return true;
|
||||
|
||||
if (CheckPermission(selfPerms, perms))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (CheckPermission(_permissions, perms.Where(p => !p.StartsWith("self.")).ToArray()))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
||||
bool CheckPermission(string[] permissions, string[] permission) {
|
||||
if (permissions.Length == 0)
|
||||
return true;
|
||||
|
||||
if (permission.Contains("*"))
|
||||
return true;
|
||||
|
||||
foreach (var perm in permissions) {
|
||||
if (permission.Contains(perm))
|
||||
return true;
|
||||
|
||||
string[] splice = perm.Split(".");
|
||||
string cache = "";
|
||||
foreach (var s in splice) {
|
||||
cache += s + ".";
|
||||
if (permission.Contains(cache + "*"))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using System.Linq;
|
||||
using System.Security.Claims;
|
||||
|
||||
namespace Backend.Security.Authorization {
|
||||
public static class ClaimsPrincipalExtensions {
|
||||
public static string GetAccessTokenId(this ClaimsPrincipal principal) =>
|
||||
principal.FindFirstValue(CustomClaimTypes.AccessTokenId);
|
||||
|
||||
public static string GetRefreshTokenId(this ClaimsPrincipal principal) =>
|
||||
principal.FindFirstValue(CustomClaimTypes.RefreshTokenId);
|
||||
|
||||
public static string GetUserId(this ClaimsPrincipal principal) =>
|
||||
principal.FindFirstValue(CustomClaimTypes.UserId);
|
||||
|
||||
public static string[] GetPermissions(this ClaimsPrincipal principal) => principal.Claims
|
||||
.Where(claim => claim.Type.Equals(CustomClaimTypes.Permission))
|
||||
.Select(claim => claim.Value)
|
||||
.ToArray();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace Backend.Security.Authorization {
|
||||
public static class CustomClaimTypes {
|
||||
public const string AccessTokenId = "WebDesktop.AccessTokenId";
|
||||
public const string RefreshTokenId = "WebDesktop.RefreshTokenId";
|
||||
public const string UserId = "WebDesktop.UserId";
|
||||
public const string Permission = "WebDesktop.Permission";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user