I am building MVC Core app that has multiple logins for different users:
- CMSUsers.
- ClientUsers
Each Users' type is stored in different sql server table. As I am using Cookie Authentication without ASP.NET Core Identity, I created the following schemes:
- CMS
- Client
I have registered the schemes in the Startup.cs file as:
public void ConfigureServices(IServiceCollection services)
{
services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddAuthentication("CMS")
.AddCookie("CMS", o => { o.LoginPath = "/CMS/Login"; })
.AddCookie("Client", o => { o.LoginPath = "/Client/Login"; });
services.AddControllersWithViews();
}
I have decorated Controller Actions with its shceme and required Role as needed:
[Authorize(AuthenticationSchemes = "Client", Roles = "AdminRole")]
Some Actions are not decorated with Authorize as they are used by all users (Logged in or Logged out).
The Problem: When any of the Users' type (CMS or Client, wether they are logged in or not) try to submiting a simple form:
<form action="/Home/Search" method="post">
<div >
@Html.AntiForgeryToken();
<input type="text" name="Search" value="">
<button type="submit">Search</button>
</div>
</form>
and the target actions is:
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Search(SearchViewModel vm)
{
vm.Results = ""; //Do some work
return View("Search", vm);
}
only CMSUsers manage to reach the target action, because CMS scheme is the default scheme as registered in Startup.cs:
services.AddAuthentication("CMS")
.AddCookie("CMS", o => { o.LoginPath = "/CMS/Login"; })
.AddCookie("Client", o => { o.LoginPath = "/Client/Login"; });
If I change the default scheme to Client, only Client Scheme will manage to call the target action and CMS will get error 400.
Also, if I remove the [ValidateAntiForgeryToken] from the target action, all users can submit the form successfully.
What am I missing?
Or is it a single scheme authentication only?
CodePudding user response:
After searching the web, adding the following to the Startup.cs solved the problem.
app.Use(async (context, next) =>
{
var principal = new ClaimsPrincipal();
var result1 = await context.AuthenticateAsync("CMS");
if (result1?.Principal != null)
{
principal.AddIdentities(result1.Principal.Identities);
}
var result2 = await context.AuthenticateAsync("Client");
if (result2?.Principal != null)
{
principal.AddIdentities(result2.Principal.Identities);
}
context.User = principal;
await next();
});