Open seriouz opened 7 years ago
There is a redis provider, it popped up in 1.1; https://github.com/aspnet/DataProtection/tree/dev/src/Microsoft.AspNetCore.DataProtection.Redis
I created a new web project (vs2015) with identity. When i follow the guidance of your link it does not work either. I think the problem is, that i cannot set a TicketDataFormat when i use PersistKeysToRedis
.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using SharedCookieRedis.Data;
using SharedCookieRedis.Models;
using SharedCookieRedis.Services;
using StackExchange.Redis;
using Microsoft.AspNetCore.DataProtection;
namespace SharedCookieRedis
{
public class Startup
{
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);
if (env.IsDevelopment())
{
// For more details on using the user secret store see http://go.microsoft.com/fwlink/?LinkID=532709
builder.AddUserSecrets();
}
builder.AddEnvironmentVariables();
Configuration = builder.Build();
}
public IConfigurationRoot Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
var redis = ConnectionMultiplexer.Connect("localhost:6379");
services.AddDataProtection().PersistKeysToRedis(redis, "DataProtection-Keys");
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
services.AddMvc();
// Add application services.
services.AddTransient<IEmailSender, AuthMessageSender>();
services.AddTransient<ISmsSender, AuthMessageSender>();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
app.UseBrowserLink();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseIdentity();
// Add external authentication middleware below. To configure them please see http://go.microsoft.com/fwlink/?LinkID=532715
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
}
}
Ah, that might be right. The cookie is supposed to be self contained. I don't think we ever looked at using redis on both sides to store the identity, and then issue a reference cookie. The data protection provider for redis is just for key storage.
Thanks for your reply! So "cookie sharing" is not working out of the box currently with redis (https://github.com/blowdart/idunno.CookieSharing Article 3)? I am now using DataProtectionProvider with a folder, which works flawlessly.
Sharing working:
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
var protectionProvider = DataProtectionProvider.Create(new DirectoryInfo(@"c:\testKeyFolder"));
var dataProtector = protectionProvider.CreateProtector(
"CookieAuthenticationMiddleware", "Cookie", "v2");
var ticketFormat = new TicketDataFormat(dataProtector);
services.AddIdentity<ApplicationUser, IdentityRole>(options =>
{
options.Cookies = new Microsoft.AspNetCore.Identity.IdentityCookieOptions
{
ApplicationCookie = new CookieAuthenticationOptions
{
AuthenticationScheme = "Cookie",
LoginPath = new PathString("/Account/Login/"),
AccessDeniedPath = new PathString("/Account/Forbidden/"),
AutomaticAuthenticate = true,
AutomaticChallenge = true,
CookieName = ".AspNet.SharedCookie",
TicketDataFormat = ticketFormat
}
};
})
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
The cookie sharing I'm referring to is for logins/authentication, in it's basic form, where the cookie has all the user information, nothing more. Not sessions, not reference cookies where the identity is elsewhere, because, honestly that covers the 99% of what folks want.
Ah I see, if it works with a folder it ought to work with redis as the key store. @pakrym do you think you can make this work?
I don't see how it is possible to allow cookie sharing over redis in 1.1. Is there a RedisDataProtectionProvider? The root of my problem lays in an enviroment, where the published dotnet folder is copied into a dynamic folder (
/opt/deploy/number-{1-n}
). Every time the folder with the app changes, all tokens of the system are invalid (authentication cookies, email-tokens etc). I tried to use Redis but this did not work either and all tokens were claimed invalid.