'How to access HttpContext and Request in RequireAssersion?
I'm trying to create a custom authorization policy. Let's say I want the URL to contain a token. For example:
https://example.com/customer/list?token=2nHxltsDOjThQJWufcGU1v36RdqYoBE9
I want to show the list of customer to the user, only if:
- URL has a token query string
- token is valid
I tried this:
services.AddAuthorization(options =>
{
options.AddPolicy("IsPaydar", policy => policy.RequireAssertion(x => // stuck here))
});
But I don't see how can I access HttpContext or the Request object from inside the policy.RequireAssertion
.
How can I implement this?
Solution 1:[1]
You can create a custom Authorization Handler, and in this handler get the token parameter from the Query string, and valid the joken. Refer the following steps:
Create a JwtTokenRequirement class: here we can set the query string parameter key value. then in the handler method, we could according to it to find the token.
//required using Microsoft.AspNetCore.Authorization; public class JwtTokenRequirement : IAuthorizationRequirement { public JwtTokenRequirement(string tokenname) { TokenName = tokenname; } public string TokenName { get; set; } }
Create the JWTTokenHandler:
//required using Microsoft.AspNetCore.Authorization; //required using Microsoft.AspNetCore.Http; public class JWTTokenHandler : AuthorizationHandler<JwtTokenRequirement> { IHttpContextAccessor _httpContextAccessor = null; public JWTTokenHandler(IHttpContextAccessor httpContextAccessor) { _httpContextAccessor = httpContextAccessor; } protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, JwtTokenRequirement requirement) { HttpContext httpContext = _httpContextAccessor.HttpContext; // Access context here var token = httpContext.Request.Query[requirement.TokenName].ToString(); //get the jwtkoken if (!string.IsNullOrEmpty(token)) { if (IsValidToken(token)) { context.Succeed(requirement); } } else { context.Fail(); } return Task.FromResult(0); } public bool IsValidToken(string authToken) { //validate Token here return true; } }
Add the following code to the ConfigureServices method:
services.AddHttpContextAccessor(); services.AddAuthorization(options => { options.AddPolicy("jwtpolicy", policy => policy.Requirements.Add(new JwtTokenRequirement("jwttoken"))); //configure the policy and set the parameter key value. in this sample the key is "jwttoken" }); services.AddSingleton<IAuthorizationHandler, JWTTokenHandler>();
Apply the Authorize attribute on the API action method:
[Authorize(Policy = "jwtpolicy")] [HttpGet("{id}")] public string Get(int id) { return "value"; }
Then the result is like this:
Solution 2:[2]
Since the question was specifically about RequireAssertion
, which takes a Func, which receives an AuthorizationHandlerContext
, the answer is that the HttpContext is the AuthorizationHandlerContext’s Resource. To use OP’s code:
services.AddAuthorization(options =>
{
options.AddPolicy("IsPaydar", policy
=> policy.RequireAssertion(x => (x.Resource as HttpContext)?.Request?.Query["token"] == "myCoolToken")
});
Whether the Resource property really contains the HttpContext is up to the framework, so Zhi Lv’s solution is certainly going to be more robust and you should probably use it anyway if your validation logic exceeds one line.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Zhi Lv |
Solution 2 | BenderBoy |