I have a simple controller which is called after the user logs in. I can see on my identity server that the user is logged in. I can also see that .AspNetCore.Identity.Application cookie is set in the browser.
After login the user is forwarded to this controller using
RedirectToAction(nameof(Index), "Manage")
The problem is that the controller doesn't appear to be authenticated. I have tried HttpContext.User and everything else i can think the controller isn't reading the cookie
[Authorize]
[Route("[controller]/[action]")]
public class ManageController : Controller
{
[HttpGet]
[AllowAnonymous]
public async Task<IActionResult> Index(ManageMessageId? message = null)
{
// try to find user here.
}
}
I have found a work around which forces it to load the cookie
var loadTheStupidCookie = await HttpContext.AuthenticateAsync(IdentityConstants.ApplicationScheme);
var user = await _userManager.GetUserAsync(loadTheStupidCookie.Principal);
This works but I think its over kill to have to load it in every method in the controller. Shouldn't the controller be able to load the cookie for me?
From startup.cs
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
options.LoginPath = new PathString("/Account/Login");
options.AccessDeniedPath = new PathString("/Account/Forbidden/");
})
.AddGoogle("Google", options =>
{
options.AccessType = "offline";
options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
options.ClientId = "xxxxx.apps.googleusercontent.com";
options.ClientSecret = "XXXX";
});
Note: Removing [AllowAnonymous] causes it to not work at all probably due to the fact that it cant see the authentication.
When you use the
Authorize
attribute, it will use the defaultAuthenticationScheme
configured usingAddAuthentication
. In your example, that looks like this:Because this is
CookieAuthenticationDefaults.AuthenticationScheme
("Cookies"), theAuthorize
attribute is using that when attempting to sign the user in. Your workaround shows that you actually wanted to useIdentityConstants.ApplicationScheme
("Identity.Application")` instead.The
Authorize
attribute allows you to specify theAuthenticationScheme
(s) you want to use, using theAuthenticationSchemes
property, which looks like this:It turns out you can't use
IdentityConstants.ApplicationScheme
directly, as this is not a compile-time constant. Although you could use the string value explicitly, you can get the compile time safety by setting up a policy, for example. See the docs for an example on how to do that.I finally figured out the problem this morning.
Both DefaultAuthenticateScheme and DefaultChallengeScheme need to be set. Then [Authorize] alone works
Leaving this as an alternate solution.