1

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.

6
  • Do you have app.UseAuthentication() in the middleware configuration in Startup? Commented Dec 13, 2017 at 13:10
  • @juunas yes its in configure. Commented Dec 13, 2017 at 13:13
  • Before UseMvc() I assume? :) Commented Dec 13, 2017 at 13:18
  • Try [Authorize(AuthenticationSchemes = IdentityConstants.ApplicationScheme)] instead of just [Authorize]. Commented Dec 13, 2017 at 13:20
  • 1
    @serpent5 [Authorize(AuthenticationSchemes = IdentityConstants.ApplicationScheme)] says an attribute argument must be a constant expression or array creation expression of an attribute parameter type. Commented Dec 13, 2017 at 13:33

2 Answers 2

8

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.

Sign up to request clarification or add additional context in comments.

5 Comments

Ok so am I doing something wrong with with i have the cookies set up? Or is it ok to do it like this?
There's nothing inherently wrong with what you're doing - It's perfectly fine to use multiple AuthenticationSchemes and differentiate between them like this. The real question is whether you need both schemes, but that's not something I'm able to answer for your specific project.
Unfortunately this didn't completely solve the problem so I have opened another question related to it. stackoverflow.com/q/47920836/1841839
Why "Identity.Application" not constant value, but readonly in IdentityConstants.ApplicationScheme
@Novikov I don't know for sure, but I wonder if it's because readonly allows for the value to be changed in a new version and for usage to automatically use that new value. If it were const, changing it would be a breaking change. It doesn't seem like a strong argument, but that is an important difference between const and readonly.
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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.