Controller not loading .AspNetCore.Identity.Applic

2019-08-05 20:12发布

问题:

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.

回答1:

When you use the Authorize attribute, it will use the default AuthenticationScheme configured using AddAuthentication. In your example, that looks like this:

services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)

Because this is CookieAuthenticationDefaults.AuthenticationScheme("Cookies"), the Authorize attribute is using that when attempting to sign the user in. Your workaround shows that you actually wanted to use IdentityConstants.ApplicationScheme("Identity.Application")` instead.

The Authorize attribute allows you to specify the AuthenticationScheme(s) you want to use, using the AuthenticationSchemes property, which looks like this:

[Authorize(AuthenticationSchemes = "Identity.Application")]

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.



回答2:

I finally figured out the problem this morning.

services.AddAuthentication(options =>
                {
                    options.DefaultAuthenticateScheme = IdentityConstants.ApplicationScheme;
                    options.DefaultChallengeScheme = IdentityConstants.ApplicationScheme;
                })

Both DefaultAuthenticateScheme and DefaultChallengeScheme need to be set. Then [Authorize] alone works

Leaving this as an alternate solution.