0

Using ASP.NET MVC Core 3, I am trying to detect is a user is authenticated.

Reading up suggests use User.Identity.IsAuthenticated instead of Request.IsAuthenticated

I am seeing no error messages/exceptions, but User.Indentity.IsAuthenticated is always false

The issue is this . I am trying to set AddAuthentication twice. If I comment out everything but the first 2 lines, then User.Identity.IsAuthenticated returns true after I log in.

 services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie();

        
        services.AddAuthentication(options =>
        {
            options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        }).AddJwtBearer(jwtBearerOptions =>
                    {
                        jwtBearerOptions.TokenValidationParameters = new TokenValidationParameters()
                        {
                            ValidateIssuer = true,
                            ValidateAudience = true,
                            ValidateLifetime = true,
                            ValidateIssuerSigningKey = true,
                            ValidIssuer = Configuration["Jwt:Issuer"],
                            ValidAudience = Configuration["Jwt:Issuer"],
                            //IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration.GetSection("Secrets")["jwt"]))
                            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:Key"])),
                            ClockSkew = TimeSpan.Zero
                        };
                    }
           );
MyDaftQuestions
  • 4,487
  • 17
  • 63
  • 120
  • Can you check via your browser tools whether a cookie is being set correctly and that this cookie is also passed on following requests? Also, does `User.Claims` contain anything? – poke Aug 13 '20 at 21:04
  • I have found the issue, but don't know why it is an issue or how to fix it. updated my post – MyDaftQuestions Aug 13 '20 at 21:06
  • The multiple AddAuthentication() calls would appear to be the problem. See https://stackoverflow.com/questions/49694383/use-multiple-jwt-bearer-authentication, https://learn.microsoft.com/en-us/aspnet/core/security/authorization/limitingidentitybyscheme?view=aspnetcore-3.1 and so on. – CodeCaster Aug 13 '20 at 21:23
  • Does this answer your question? [User.Identity.IsAuthenticated always false in .net core custom authentication](https://stackoverflow.com/questions/45261732/user-identity-isauthenticated-always-false-in-net-core-custom-authentication) – Michael Freidgeim Jun 11 '21 at 22:43

1 Answers1

1

The issue is this. I am trying to set AddAuthentication twice.

Well, that doesn’t work. AddAuthentication, like other Add~ methods, adds the required services to make authentication work. So on its own, calling it multiple times has zero effect.

However, when passing an argument, then you are configuring the AuthenticationOptions as well.

Calling services.AddAuthentication(schemeName) is basically the same as the following:

services.AddAuthentication(options =>
{
    options.DefaultScheme = schemeName;
});

So in your case, you are configuring the default scheme to be CookieAuthenticationDefaults.AuthenticationScheme. But when you then call AddAuthentication again, you are reconfiguring the options. Since you are setting both the DefaultAuthenticateScheme and the DefaultChallengeScheme, the setup looks like this in the end:

options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;

As I explain in detail in another answer, the default scheme is only used when the more explicit default value is not configured. Each authentication action however only calls a single scheme.

When you use the authentication middleware with app.UseAuthentication(), then the default authenticate scheme will be used to authenticate the user. This is the JWT bearer scheme in your case though, so users that have a cookie will not be authenticated. Only when you remove the configuration of DefaultAuthenticateScheme, the DefaultScheme will be used instead to the successfully authenticate the user.

To solve your issue, you should decide on a single scheme that you want to use by default. If your app is a standard web application with a UI, then you want that to be the cookie scheme, so users visiting your app will be authenticated correctly. If you in addition have some APIs where you will need to authenticate clients using JWT bearer, then you should consider requiring that scheme explicitly on those APIs. You can do that for example by specifying the scheme in authorization policies or by using the [Authorize] attribute:

[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
public class MyApiController : ControllerBase
{
    …
}
poke
  • 369,085
  • 72
  • 557
  • 602
  • This is really clear. I can see, the hybrid approach I wanted to take has lead me into this issue. At least I can now understand what options I have and it feels like choosing only 1 is the best approach (but I can now see how specify a scheme per end point!. Since JWT is the default, I decorated my end point (with the Authorize) for Cookies with `[Authorize(AuthenticationSchemes = CookieAuthenticationDefaults.AuthenticationScheme)]` – MyDaftQuestions Aug 15 '20 at 13:44