简体   繁体   中英

ASP.NET Core 2.1 API JWT token Session.id changes on every request

I have a asp.net core 2.1 API that I connect to using and Angular 4 app and authenticate thru a JWT token. I also have 2 SignalR hubs there as well.

The authentication works nice and I am sure it works because after login I have access to the methods and classes I have set [Authorize] on.

The problem is the injected _accessor.HttpContext.Session.Id changes every time with every request. So the real issues is I cannot use session variables.

I am at a loss and it seems to me I am missing something here. Can someone please help me with some ideas? Any help is much appreciated.

This is my startup.cs so far:

public class Startup
{
    public Startup(IConfiguration configuration, IHostingEnvironment env)
    {
        Configuration = configuration;
        if (env.IsDevelopment())
        {
            Log.Logger = new LoggerConfiguration()
                .MinimumLevel.Debug()
                .WriteTo.RollingFile(Path.Combine(env.ContentRootPath+"/logs/", "log-{Date}.txt"))
                //, outputTemplate: "{MachineName} {EnvironmentUserName}: {Message:lj}{NewLine}{Exception}"
                .WriteTo.Seq("http://192.168.1.164:5341")
                .Enrich.WithMachineName()
                .Enrich.WithEnvironmentUserName()
                .CreateLogger();
        }
        else
        {
            Log.Logger = new LoggerConfiguration()
                .MinimumLevel.Information()
                .WriteTo.RollingFile(Path.Combine(env.ContentRootPath + "/logs/", "log-{Date}.txt"))
                .Enrich.WithMachineName()
                .Enrich.WithEnvironmentUserName()
                .CreateLogger();
        }
    }

public IConfiguration Configuration { get; }

public void ConfigureServices(IServiceCollection services)
{
    var key = Encoding.ASCII.GetBytes(Configuration.GetSection("AppSettings:Token").Value);
    services.AddDbContext<PaymentServicesContext>(options => options.UseSqlServer(Configuration.GetConnectionString("PaymentDatabase")));

    services.AddSession(options =>
    {
        options.IdleTimeout = TimeSpan.FromMinutes(10);
        options.Cookie.HttpOnly = true;
    });

    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1).AddSessionStateTempDataProvider();

    services.AddAuthentication(options =>
    {
        options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
        options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
    })
    .AddJwtBearer(options =>
    {
        options.TokenValidationParameters =
        new TokenValidationParameters
        {
            LifetimeValidator = (before, expires, token, param) =>
            {
                return expires > DateTime.UtcNow;
            },
            ValidateAudience = false,
            ValidateIssuerSigningKey = true,
            ValidateIssuer = false,
            ValidateActor = false,
            ValidateLifetime = true,
            IssuerSigningKey = new SymmetricSecurityKey(key)
        };
        options.Events = new JwtBearerEvents
        {
            OnMessageReceived = context =>
            {
                var accessToken = context.Request.Query["access_token"];
                var path = context.HttpContext.Request.Path;
                if (!string.IsNullOrEmpty(accessToken))
                {
                    context.Token = accessToken;
                }
                return Task.CompletedTask;
            }
        };
    });
    services.AddAutoMapper();
    services.AddCors();
    services.AddSignalR(options => options.EnableDetailedErrors = true);

    ///services
    services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
    services.AddTransient<IBrainzService, BrainzService>();
    services.AddTransient<ISecurityService, SecurityService>();

}

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    loggerFactory.AddConsole(Configuration.GetSection("Logging"));
    loggerFactory.AddDebug();
    loggerFactory.AddSerilog();

    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler(builder =>
        {
            builder.Run(async context =>
            {
                context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;

                var error = context.Features.Get<IExceptionHandlerFeature>();
                if (error != null)
                {
                    
                    await context.Response.WriteAsync(error.Error.Message);
                }
            });
        });
    }


    app.UseCors(builder => builder.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod().AllowCredentials())
        .UseStaticFiles()
        .UseWebSockets();

    app.UseAuthentication();
    if (!env.IsDevelopment())
    {
        app.UseHttpsRedirection();
    }
    app.UseWebSockets();

    app.UseSignalR(
        routes =>
        {
            routes.MapHub<MessagingHub>("/messagingHub");
            routes.MapHub<UpdatesHub>("/updatesHub");
        });

    app.UseSession();
    app.UseMvc();
  }
}

The configuration works. The problem was that Angular's HttpClient does not store/get/send cookies by default as I have found out the hard way. All I had to do was add {withCredentials: true } option to the login request and the session cookie popped into the browser! To get the session back you have to add this option to all requests and the API will know the session!

One solution would be to create an Interceptor to intercept all requests before it leaves the client application. This tutorial explains it well. You can also do this on a per-request level by setting the withCredentials to true .

const requestOptions = {
 headers: new HttpHeaders({
  'Authorization': "my-request-token"
 }),
 withCredentials: true
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM