My project has two controllers to support users from different roles - Members and Consultants. On sign-in I set the "Role" ClaimType for each.
There is a different sign-in page for members and consultants and after sign-in both the MemberController and ConsultantController redirect to a "Desktop" action.
CONSULTANTCONTROLLER.CS
[HttpPost()]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> SignIn(SignIn sin)
{
try
{
// check authorisation
if (ModelState.IsValid)
{
sin = await RepoSamadhi.ShopSignIn(sin);
if (sin.ShopID == 0 || sin.IsValidationFail || string.IsNullOrEmpty(sin.ShopToken))
{
is_err = true;
_logger.LogInformation("Consultant SignIn Invalid Credentials", sin.EmailAddress);
ModelState.AddModelError("Consultant", "Account not found. Check your credentials.");
}
}
else
{
sin.IsSignInFailed = true;
return View("SignIn", sin);
}
// create claims
var claims = new List<Claim>
{
new Claim(ClaimTypes.Sid, sin.ShopToken),
new Claim(ClaimTypes.NameIdentifier, sin.ShopID.ToString()),
new Claim(ClaimTypes.Email, sin.EmailAddress.ToLower()),
new Claim(ClaimTypes.Role, "Consultant")
};
// create identity
var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme); // cookie or local
// create principal
ClaimsPrincipal principal = new ClaimsPrincipal(new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme));
// create auth properties
var authProperties = new AuthenticationProperties
{
IsPersistent = sin.RememberMe;
};
// sign-in
await HttpContext.SignInAsync(scheme: CookieAuthenticationDefaults.AuthenticationScheme, principal: principal, properties: authProperties);
}
catch (Exception ex)
{
gFunc.ProcessError(ex);
}
return RedirectToAction("Desktop", new { date = DateTime.Today.ToString("d MMM yyyy"), timer = false });
}
STARTUP.CS
public void ConfigureServices(IServiceCollection services)
{
try
{
services.AddRazorPages()
.AddRazorRuntimeCompilation();
services.AddControllersWithViews();
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>
{
options.ExpireTimeSpan = new TimeSpan(30, 0, 0, 0);
options.LoginPath = new PathString("/Home/Index/");
options.AccessDeniedPath = new PathString("/Home/Index/");
options.LogoutPath = new PathString("/Home/Index/");
options.Validate();
});
services.Configure<Microsoft.AspNetCore.Identity.IdentityOptions>(options =>
{
options.Password.RequireDigit = true;
options.Password.RequireLowercase = true;
options.Password.RequireNonAlphanumeric = true;
options.Password.RequireUppercase = true;
options.Password.RequiredLength = 8;
options.Password.RequiredUniqueChars = 1;
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
options.Lockout.MaxFailedAccessAttempts = 5;
options.Lockout.AllowedForNewUsers = true;
options.User.AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+";
options.User.RequireUniqueEmail = false;
});
// add detection services container and device resolver service
services.AddDetectionCore()
.AddDevice();
services.AddMvc();
services.AddAntiforgery();
services.Configure<MvcOptions>(options =>
{
options.Filters.Add(new RequireHttpsAttribute());
});
}
catch (Exception ex)
{
gFunc.ProcessError(ex);
}
}
QUESTION
How can I configure the Authentication service to redirect the user to the correct SignIn page when they attempt to access an Authorize resource) but are not signed in (ie. no valid authentication cookie)? At the moment I have just one "AccessDeniedPath" and it takes the user to the home page.