How to Create a Custom Authorizeattribute in ASP.NET Core

How do you create a custom AuthorizeAttribute in ASP.NET Core?

The approach recommended by the ASP.Net Core team is to use the new policy design which is fully documented here. The basic idea behind the new approach is to use the new [Authorize] attribute to designate a "policy" (e.g. [Authorize( Policy = "YouNeedToBe18ToDoThis")] where the policy is registered in the application's Startup.cs to execute some block of code (i.e. ensure the user has an age claim where the age is 18 or older).

The policy design is a great addition to the framework and the ASP.Net Security Core team should be commended for its introduction. That said, it isn't well-suited for all cases. The shortcoming of this approach is that it fails to provide a convenient solution for the most common need of simply asserting that a given controller or action requires a given claim type. In the case where an application may have hundreds of discrete permissions governing CRUD operations on individual REST resources ("CanCreateOrder", "CanReadOrder", "CanUpdateOrder", "CanDeleteOrder", etc.), the new approach either requires repetitive one-to-one mappings between a policy name and a claim name (e.g. options.AddPolicy("CanUpdateOrder", policy => policy.RequireClaim(MyClaimTypes.Permission, "CanUpdateOrder));), or writing some code to perform these registrations at run time (e.g. read all claim types from a database and perform the aforementioned call in a loop). The problem with this approach for the majority of cases is that it's unnecessary overhead.

While the ASP.Net Core Security team recommends never creating your own solution, in some cases this may be the most prudent option with which to start.

The following is an implementation which uses the IAuthorizationFilter to provide a simple way to express a claim requirement for a given controller or action:

public class ClaimRequirementAttribute : TypeFilterAttribute
{
public ClaimRequirementAttribute(string claimType, string claimValue) : base(typeof(ClaimRequirementFilter))
{
Arguments = new object[] {new Claim(claimType, claimValue) };
}
}

public class ClaimRequirementFilter : IAuthorizationFilter
{
readonly Claim _claim;

public ClaimRequirementFilter(Claim claim)
{
_claim = claim;
}

public void OnAuthorization(AuthorizationFilterContext context)
{
var hasClaim = context.HttpContext.User.Claims.Any(c => c.Type == _claim.Type && c.Value == _claim.Value);
if (!hasClaim)
{
context.Result = new ForbidResult();
}
}
}


[Route("api/resource")]
public class MyController : Controller
{
[ClaimRequirement(MyClaimTypes.Permission, "CanReadResource")]
[HttpGet]
public IActionResult GetResource()
{
return Ok();
}
}

DotNet Core Custom Authorize Attribute using Route Params

I was able to solve my problem by doing the following:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class UserAuthorizationAttribute : AuthorizeAttribute, IAuthorizationFilter
{
public void OnAuthorization(AuthorizationFilterContext context)
{
// Here I can get userId from my params.
var userId = context.RouteData.Values["userId"].ToString();

// It is then being checked against current user claims.
// The user is only authorized if the userId is equals to ClaimsType.Value and claims Type is equals to NameIdentifier.
var isUserAuthorized = context.HttpContext.User.Claims.Any(c => c.Type == ClaimTypes.NameIdentifier && c.Value == userId);

if (!isUserAuthorized)
{
context.Result = new UnauthorizedResult();
}
}
}

Pass connection string to custom AuthorizeAttribute in asp.net core

Use the AuthorizationFilterContext.HttpContext.RequestServices.GetService method from the context argument passed into your OnAuthorization method:

public void OnAuthorization(AuthorizationFilterContext context)
{
...

if (user.Identity.IsAuthenticated)
{
var connectionString = context.HttpContext.RequestServices
.GetService(typeof(IConfiguration))
.GetConnectionString("EmployeeDBConnection");
// GetConnectionString is an extension method, so add
// using Microsoft.Extensions.Configuration

...
}
}

Using this technique, you could also simply use your DbContext as well.

Custom Authorize attribute - ASP .NET Core 2.2

You can use IAuthorizationPolicyProvider to get the policy and then use ClaimsAuthorizationRequirement.ClaimType to get a claim name. And since it has async API, it is better to use IAsyncAuthorizationFilter instead of IAuthorizationFilter. Try this:

public class CustomAuthorizeAttribute : AuthorizeAttribute, IAsyncAuthorizationFilter
{
public async Task OnAuthorizationAsync(AuthorizationFilterContext authorizationFilterContext)
{
var policyProvider = authorizationFilterContext.HttpContext
.RequestServices.GetService<IAuthorizationPolicyProvider>();
var policy = await policyProvider.GetPolicyAsync(UserPolicy.Read);
var requirement = (ClaimsAuthorizationRequirement)policy.Requirements
.First(r => r.GetType() == typeof(ClaimsAuthorizationRequirement));

if (authorizationFilterContext.HttpContext.User.Identity.IsAuthenticated)
{
if (!authorizationFilterContext.HttpContext
.User.HasClaim(x => x.Value == requirement.ClaimType))
{
authorizationFilterContext.Result =
new ObjectResult(new ApiResponse(HttpStatusCode.Unauthorized));
}
}
}
}

How do I create a custom Authorize attribute that does not depend on claims in ASP.NET Core?

You can simply create Authorization Filter

public class CustomAuthorizationFilter : IAuthorizationFilter
{
public void OnAuthorization(AuthorizationFilterContext context)
{
string id = context.HttpContext.Request.Query["id"]?.ToString();

if (!string.IsNullOrEmpty(id))
{
// Authorization logic
}
}
}


Related Topics



Leave a reply



Submit