2

I'm developing an ASP.NET Core 2.2 web application. I want to store user claims in application memory, not in cookies.

I add AddDistributedMemoryCache, AddSession and UseSession as described here, but when page is requested, I still see cookie data sent to server and received from the server.

My Startup class:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDistributedMemoryCache();

        services.AddSession(options =>
        {
            // Set a short timeout for easy testing.
            options.IdleTimeout = TimeSpan.FromSeconds(10);
            options.Cookie.HttpOnly = true;
            // Make the session cookie essential
            options.Cookie.IsEssential = true;
        });

        services.Configure<CookiePolicyOptions>(options =>
        {
            // This lambda determines whether user consent for non-essential cookies is needed for a given request.
            options.CheckConsentNeeded = context => true;
            options.MinimumSameSitePolicy = SameSiteMode.None;
        });

        services.AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(
                Configuration.GetConnectionString("DefaultConnection")));
        services.AddDefaultIdentity<IdentityUser>()
            .AddDefaultUI(UIFramework.Bootstrap4)
            .AddEntityFrameworkStores<ApplicationDbContext>();


        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseDatabaseErrorPage();
        }
        else
        {
            app.UseExceptionHandler("/Error");
            // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseStaticFiles();
        app.UseSession();
        app.UseCookiePolicy();

        app.UseAuthentication();

        app.UseMvc();
    }
}

Cookie data:

cookie: .AspNet.Consent=yes; .AspNetCore.Antiforgery.WGD7B_OvtEU=CfDJ8K-fe5FucclFpIYHgLvWwKY0RPLnAZQX6JnN1muQjDbx0UK4C310gp8L2RHdWlsHmoYJihQxtGuUB5GNG742rl7N-UgTynSNz09Jsb11kVgRcxAgQk5yaZnbcaQGQ0tiJUCoKAdwxEgykc2Fc3-vVCY; .AspNetCore.Identity.Application=CfDJ8K-fe5FucclFpIYHgLvWwKaod7oR4502P-cppU0aQI_WYHsvaTEL-Y5Ca1hnJOBznUpadpPkq5ubrH04UhMBpXTnK1ASjuMXMPBhr3PKqPSnXPYPFmhgki1_RicCVDQyl7mRYuWPUY2RjVkgoEIXCBj96zCRK9PWZo0N6N4hAETl-z0LAExj1Sjo6Xz3uWvHsg5GtJijlQmE6BjSh0ObMulxgDFJZEw13IbWJmlLFv7kdvs9va59wBPlEhHFER1Rs0iKW2cpVqQTPK7SjgQrSlo8_KQYHWzYa3xFSjuhrWJnm-Y4u9jXA6yCoaVxG1U-1EbOaQRfUXFs2F9IX6dU7iExsNqhPR4o2CKlt6ERI0JT_p7jHv0hrHbBiUjUVMYi_qoAQRv1OXfVZBLkoRve20gvjQtD3aRZFZR5poX-bq0pw6CNBTLexzD_bU1jJnpaf61OKbQM2-qJnWPS7YayFjJt3k_qALbnquUsSBMDMm3PoFcU26_Ubyu6RTZ-aanKc1bdcEA5o3WF8JksZkrvRFhZZuvWahDpnQCxxy-rELKwXcybcWHi-QB7gxSm6Q6S84NX2390mbHVJ1RO8eUmUF4

How can I make it store only in memory, not in cookies?

1 Answer 1

5

You need to set SessionStore for identity cookie authentication, so your authentication cookie is only an identifier.

Instead of

services.AddDefaultIdentity<IdentityUser>()

Use this

services.AddAuthentication(o =>
{
    o.DefaultScheme = IdentityConstants.ApplicationScheme;
    o.DefaultSignInScheme = IdentityConstants.ExternalScheme;
}).AddIdentityCookies(o =>
{
    o.ApplicationCookie.PostConfigure(cookie => cookie.SessionStore = new MemoryCacheTicketStore());
});

services.AddIdentityCore<IdentityUser>(o =>
{
    o.Stores.MaxLengthForKeys = 128;
}).AddDefaultUI()
.AddDefaultTokenProviders();

MemoryCacheTicketStore.cs

public class MemoryCacheTicketStore : ITicketStore
{
    private const string KeyPrefix = "AuthSessionStore-";
    private IMemoryCache _cache;

    public MemoryCacheTicketStore()
    {
        _cache = new MemoryCache(new MemoryCacheOptions());
    }

    public async Task<string> StoreAsync(AuthenticationTicket ticket)
    {
        var guid = Guid.NewGuid();
        var key = KeyPrefix + guid.ToString();
        await RenewAsync(key, ticket);
        return key;
    }

    public Task RenewAsync(string key, AuthenticationTicket ticket)
    {
        var options = new MemoryCacheEntryOptions();
        var expiresUtc = ticket.Properties.ExpiresUtc;
        if (expiresUtc.HasValue)
        {
            options.SetAbsoluteExpiration(expiresUtc.Value);
        }
        options.SetSlidingExpiration(TimeSpan.FromHours(1)); // TODO: configurable.

        _cache.Set(key, ticket, options);

        return Task.FromResult(0);
    }

    public Task<AuthenticationTicket> RetrieveAsync(string key)
    {
        AuthenticationTicket ticket;
        _cache.TryGetValue(key, out ticket);
        return Task.FromResult(ticket);
    }

    public Task RemoveAsync(string key)
    {
        _cache.Remove(key);
        return Task.FromResult(0);
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

i get en error 'InvalidOperationException: Unable to resolve service for type 'Microsoft.AspNetCore.Identity.IUserStore1[Microsoft.AspNetCore.Identity.IdentityUser]' while attempting to activate 'Microsoft.AspNetCore.Identity.UserManager1[Microsoft.AspNetCore.Identity.IdentityUser]'.'
Did you also remove AddEntityFrameworkStore ? If so bring them back

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.