I used a specific authorization policy for user log in, so created custom Authorization Handler. And I would like to display use a specific alert message if they failed the policy. I read the documentation and found that I could access AuthorizationFilterContext via casting AuthorizationHandlerContext. I tried to add message to HttpContext.Items property and access it in my controller, but it returns false when i check it with TryGetValue method.
if (context.HasFailed && context.Resource is AuthorizationFilterContext mvcContext)
{
mvcContext.HttpContext.Items["message"] = "alert message";
}
and this is the code i used in controller action that will be executed when authorization has failed,
public IActionResult Login()
{
bool t = HttpContext.Items.TryGetValue("message", out Object e);
//t is false
TempData["message"] = e as string;
return View();
}
and this is startup class where i registered all authentication services.
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
options.AccessDeniedPath = "/Account/Login";
options.LoginPath = "/Account/Login";
});
services.AddAuthorization(options =>
{
options.AddPolicy("CustomRequirement", policy => policy.Requirements.Add(new CustomRequirement()));
});
Is there any way i could work it out?
added full handler.
public class CustomRequirementHandler : AuthorizationHandler<CustomRequirement>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, CustomRequirement requirement)
{
Dictionary<string, string> claims = context.User.Claims.ToDictionary(p => p.Type, p => p.Value);
if (claims.TryGetValue("SessionId", out string sessionId) && claims.TryGetValue("UserId", out string userName) )
{
bool qq = ;//we check session id and user id that is stored in our database, true if valid.
if (qq)
{
context.Succeed(requirement);
}
else
{
context.Fail();
}
}
else
{
context.Fail();
}
if (context.HasFailed && context.Resource is AuthorizationFilterContext mvcContext)
{
var tempData = _tempDictionaryFactory.GetTempData(mvcContext.HttpContext);
tempData["message"] = "alert message";
}
return Task.CompletedTask;
}
}
I guess add this will make dependency injected?
private ITempDataDictionaryFactory _tempDictionaryFactory;
public SingleConcurrentSessionHandler(ITempDataDictionaryFactory tempDataDictionaryFactory)
{
_tempDictionaryFactory = tempDataDictionaryFactory;
}
Update - here is the logger log for new empty project with custom AuthorizationHandler.
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
Request starting HTTP/1.1 GET http://localhost:50236/
info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2]
Authorization failed for user: (null).
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[3]
Authorization failed for the request at filter 'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'.
info: Microsoft.AspNetCore.Mvc.ChallengeResult[1]
Executing ChallengeResult with authentication schemes ().
info: Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler[12]
AuthenticationScheme: Cookies was challenged.
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
Executed action WebApplication1.HomeController.Index (WebApplication1) in 6217.0905ms
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Request finished in 6389.8033ms 302
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
Request starting HTTP/1.1 GET http://localhost:50236/Account/Login?ReturnUrl=%2F
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
Executing action method WebApplication1.Controllers.AccountController.Login (WebApplication1) with arguments ((null)) - ModelState is Valid
info: Microsoft.AspNetCore.Mvc.Formatters.Json.Internal.JsonResultExecutor[1]
Executing JsonResult, writing value .
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
Executed action WebApplication1.Controllers.AccountController.Login (WebApplication1) in 3723.1458ms
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Request finished in 3741.0345ms 200 application/json; charset=utf-8
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
Request starting HTTP/1.1 GET http://localhost:50236/favicon.ico
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Request finished in 4.1151ms 404 text/plain