I created a .NET Core 7 project on Windows 10 with Razor pages, but I get this error:
Error CS0311
The type 'WebAppSecurity.Authorization.HRManagerProbationRequirmentHandle' cannot be used as type parameter 'TImplementation' in the generic type or method 'ServiceCollectionServiceExtensions.AddSingleton<TService, TImplementation>(IServiceCollection)'. There is no implicit reference conversion from 'WebAppSecurity.Authorization.HRManagerProbationRequirmentHandle' to 'Microsoft.AspNetCore.Authentication.IAuthenticationHandler'. WebAppSecurity F:\WebProj\WebAppSecurity\WebAppSecurity\Program.cs
program.cs
:
using Microsoft.AspNetCore.Authentication;
using WebAppSecurity.Authorization;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddAuthentication().AddCookie("MyCookieAuth", options =>
{
options.Cookie.Name = "MyCookieAuth";
options.LoginPath = "/Account/Login";
});
builder.Services.AddAuthorization(options =>
{
options.AddPolicy("MustBelongToHRDeparteman",policy => policy.RequireClaim("Department","HR"));
options.AddPolicy("AdminOnly",policy => policy.RequireClaim("Admin"));
options.AddPolicy("HRAdmin", policy => policy.RequireClaim("Department", "HR").RequireClaim("Manager").Requirements.Add(new HRManagerProbationRequirment(3)));
});
builder.Services.AddSingleton<IAuthenticationHandler, HRManagerProbationRequirmentHandle>();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
HRManager
:
using Microsoft.AspNetCore.Authorization;
namespace WebAppSecurity.Authorization
{
public class HRManagerProbationRequirment : IAuthorizationRequirement
{
public HRManagerProbationRequirment(int probationMonth)
{
ProbationMonth = probationMonth;
}
public int ProbationMonth { get; }
}
public class HRManagerProbationRequirmentHandle : AuthorizationHandler<HRManagerProbationRequirment>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, HRManagerProbationRequirment requirement)
{
if (!context.User.HasClaim(x => x.Type == "EmploymentDate"))
{
return Task.CompletedTask;
};
if (DateTime.TryParse(context.User.FindFirst(x => x.Type == "EmploymentDate")?.Value, out DateTime employmentDate))
{
var period = DateTime.Now - employmentDate;
if (period.Days > 30 * requirement.ProbationMonth)
{
context.Succeed(requirement);
}
};
return Task.CompletedTask;
}
}
}
Login :
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.ComponentModel.DataAnnotations;
using System.Security.Claims;
namespace WebAppSecurity.Pages.Account
{
public class LoginModel : PageModel
{
[BindProperty]
public Credential Credential { get; set; } = new Credential();
public void OnGet()
{
}
public async Task<ActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
if (Credential.UserName == "admin" && Credential.Password == "admin")
{
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name,"admin"),
new Claim(ClaimTypes.Email,"admin@gmail.com"),
new Claim("Department" ,"HR"),
new Claim("Admin","true"),
new Claim("Manager","true"),
new Claim("EmploymentDate","2023-03-03"),
};
var identity = new ClaimsIdentity(claims, "MyCookieAuth");
ClaimsPrincipal principal = new ClaimsPrincipal(identity);
await HttpContext.SignInAsync("MyCookieAuth", principal);
return RedirectToPage("/Index");
}
return Page();
}
}
public class Credential
{
[Required]
[Display(Description ="User Name")]
public string UserName { get; set; } = string.Empty;
[Required]
[DataType(DataType.Password)]
public string Password { get; set; } = string.Empty;
}
}
Try to use IAuthorizationHandler:
Classes implementing this interface are able to make a decision if authorization is allowed.
Change below :
builder.Services.AddSingleton<IAuthenticationHandler, HRManagerProbationRequirmentHandle>();
into:
builder.Services.AddSingleton<IAuthorizationHandler, HRManagerProbationRequirmentHandle>();