User doesn't seem authenticated in pipline inside`Use` in dotnetcore 2.0

I am trying to provide a property ActiveUserfor Serilog.
Unfortunately, I can not find the right place to check the current user.

Is the code httpContext.User.Identity.IsAuthenticatedalways false in the code below ?

But only when entering the carrier token

  • The bearer input token is working correctly because the user is authenticated for the controller methods and the user must belong to the correct roles for authentication. Although the username is incorrectly set - claims are present, and IsAuthenticated - true.
  • If I use the cookie login, the user is configured correctly and the claims are set correctly and Serilog is working correctly. This is true if you use a carrier token or cookie to log in. Once a user is logged in with a cookie, he always works.

When the carrier token is verified, the user is not immediately installed?

Aspnetcore 2.0 project

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{

    ... (other configuration items)

    app.UseIdentityServer();
    app.UseAuthentication();

    app.Use(async (httpContext, next) =>
    {
        // HERE IsAuthenticated IS ALWAYS FALSE
        // HERE THE CLAIMS ARE ALWAYS EMPTY, UNLESS
        // I LOGIN USING THE COOKIE AS WELL - THEN IT WORKS
        var userName = httpContext.User.Identity.IsAuthenticated 
            ? httpContext.User.GetClaim("name")
            : "(unknown)";
        LogContext.PushProperty(
            "ActiveUser",
            !string.IsNullOrWhiteSpace(userName)
                 ? userName
                 : "(unknown)");
        await next.Invoke();
    });

    app.UseMvc(
        routes =>
        {
            routes.MapRoute(
                "default",
                "{controller=Home}/{action=Index}/{id?}");
        });

In my controller method, the user is configured correctly and authenticated.

[Authorize]
[HttpGet("user")]
public object UserDetail()
{
    // HERE THE CLAIMS ARE SET, IsAuthenticated IS ALWAYS TRUE
    // AS THE USER MUST BE AUTHENTICATED TO GET HERE
    Debug.Assert(this.User.Identity.IsAuthenticated == true)

change
Delving into this issue, it appears that the token JWTBearer confirmed after my intermediate software has already been completed. Middleware should be executed AFTER the token is verified.

TL DR
(full configuration)

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseBrowserLink();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
    }

    app.UseStaticFiles();
    app.UseIdentityServer();
    app.UseAuthentication();
    app.Use(async (httpContext, next) =>
                    {
                        var userName = httpContext.User.Identity.IsAuthenticated 
                        ? httpContext.User.GetClaim("email")
                        : "(unknown)";
                        LogContext.PushProperty("ActiveUser", !string.IsNullOrWhiteSpace(userName) ? userName : "(unknown)");
                        await next.Invoke();
                    });

    app.UseMvc(
        routes =>
        {
            routes.MapRoute(
                "default",
                "{controller=Home}/{action=Index}/{id?}");
        });

}

(more configuration)

   public void ConfigureServices(IServiceCollection services)
   {
        JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
        services.AddAuthentication()
            .AddOpenIdConnect(
                o =>
                {
                    o.Authority = "https://localhost:44319";
                    o.ClientId = "api";
                    o.ClientSecret = "secret";
                    o.RequireHttpsMetadata = false;
                    o.ResponseType = "code id_token token";
                    o.GetClaimsFromUserInfoEndpoint = true;
                })
            .AddJwtBearer(
                o =>
                {
                    o.Authority = "https://localhost:44319";
                    o.Audience = "api";
                    o.RequireHttpsMetadata = false;
                    //o.SaveToken = true;
                });

        services.AddMemoryCache();
        services.AddIdentity<ApplicationUser, ApplicationRole>(
                x =>
                {
                    x.Password.RequireNonAlphanumeric = false;
                    x.Password.RequireUppercase = false;
                })
            .AddEntityFrameworkStores<FormWorkxContext>()
            .AddDefaultTokenProviders()
            .AddIdentityServer();

        // NB
        services.Configure<IdentityOptions>(
            options =>
            {
                options.ClaimsIdentity.RoleClaimType = ClaimTypes.Role;
                options.ClaimsIdentity.UserNameClaimType = ClaimTypes.Name;
            });

        services.ConfigureApplicationCookie(
            options =>
            {
                options.LoginPath = "/login";
                options.LogoutPath = "/logout";
                options.Events.OnRedirectToLogin = this.ProcessStatusCodeResponse;
            });

        services.AddIdentityServer()
            .AddDeveloperSigningCredential()
            .AddInMemoryIdentityResources(Config.GetIdentityResources())
            .AddInMemoryApiResources(Config.GetApis())
            .AddInMemoryClients(Config.GetClients())
            .AddAspNetIdentity<ApplicationUser>();

        services.AddTransient<IEmailSender, EmailSender>();

        services.AddMvc(
                _ =>
                {
                    _.Filters.Add(
                        new AuthorizeFilter(
                            new AuthorizationPolicyBuilder(
                                    JwtBearerDefaults.AuthenticationScheme,
                                    IdentityConstants.ApplicationScheme)
                                .RequireAuthenticatedUser()
                                .Build()));
                    _.Filters.Add(new ExceptionFilter());
                    _.ModelBinderProviders.Insert(0, new PartyModelBinderProvider());
                    _.ModelBinderProviders.Insert(0, new DbGeographyModelBinder());
                    _.ModelMetadataDetailsProviders.Add(new KeyTypeModelMetadataProvider());
                })
            .AddFluentValidation(fv => fv.RegisterValidatorsFromAssemblyContaining<Startup>())
            .AddJsonOptions(json => json.SerializerSettings.Converters.Add(new DbGeographyJsonConverter()));
    }
+4
source
3

:

var principal = new ClaimsPrincipal(new ClaimsIdentity(claims));

SignInAsync. , User.Identity.Name , User.Identity.IsAuthenticated true.

, authenticationType ClaimsIdentity :

var principal = new ClaimsPrincipal(new ClaimsIdentity(claims, "local"));

IsAuthenticated true.

, , authenticationType -, JWT. .

ok , , authenticationType. , , , AuthenticateAsync. Context.User, .

2 AddJwtBearer :

o.Events.OnTokenValidated = async (context) => {
    context.Principal = new ClaimsPrincipal(new ClaimsIdentity(context.Principal.Claims, "local"));
};
0

, - , :

, , , . HttpContext.User / , . "" . , AuthorizeFilter. JWT , , .. , User , .

+2

Authenticate the user explicitly in your user middleware by adding the following line of code:

var result = await context.Request.HttpContext.AuthenticateAsync(JwtBearerDefaults.AuthenticationScheme);//AuthenticationOptions.DefaultAuthenticateScheme)
            if (result.Succeeded)
            {
                //context.User.AddIdentity(result.Principal);
                context.User = result.Principal;
            }
0
source

Source: https://habr.com/ru/post/1685943/


All Articles