【问题标题】:Authentication, WsFederation & Cookie - User gets logged out after app restart身份验证、WsFederation 和 Cookie - 用户在应用重启后注销
【发布时间】:2023-03-09 02:40:01
【问题描述】:

我有以下

services.AddDataProtection().PersistKeysToFileSystem(new DirectoryInfo("keys")).SetApplicationName("Base");

services.AddAuthentication(sharedOptions =>
                    {
                        sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                        sharedOptions.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                        sharedOptions.DefaultChallengeScheme = WsFederationDefaults.AuthenticationScheme;
                    })
                    .AddWsFederation(options =>
                    {
                        options.DataProtectionProvider = DataProtectionProvider.Create("Base");
                        options.CallbackPath = "/api/signin-wsfed";
                        options.Events.OnRedirectToIdentityProvider = context =>
                        {
                            var list = context?.Request?.GetTypedHeaders()?.Accept;
                            if (list != null && list.Any(x => x.MediaType.Value.Contains("application/json")))
                            {
                                Log("OnRedirectToIdentityProvider", "Request for URL: '{URL}', Method: '{Method}', Status Code: '{StatusCode}', Old Status Code: '{OldStatusCode}'", context.Request.Path, context.Request.Method, 401, context?.Response?.StatusCode);
                                context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
                                context.HandleResponse();
                            }
                            else
                            {
                                Log("OnRedirectToIdentityProvider", "Request for URL: '{URL}', Method: '{Method}', Status Code: '{StatusCode}'", context?.Request?.Path, context?.Request?.Method, context?.Response?.StatusCode);
                            }

                            return Task.CompletedTask;
                        };
                        options.Events.OnAuthenticationFailed = context =>
                        {
                            Log("OnAuthenticationFailed", "Auth Failed: '{Exception}'", context.Exception);

                            return Task.CompletedTask;
                        };

                        options.Events.OnSecurityTokenValidated = context =>
                        {
                            Log("OnSecurityTokenValidated", "Validated for '{User}', Valid '{ValidFrom}' to '{ValidTo}'", context?.Principal?.FindFirst(ClaimTypes.Upn), context?.SecurityToken.ValidFrom, context?.SecurityToken.ValidTo);                      
                            return Task.CompletedTask;
                        };

                        // options.UseTokenLifetime = false;
                        options.Wtrealm = Configuration.GetSection("WsFederation").GetValue<string>("Wtrealm");
                        options.MetadataAddress = Configuration.GetSection("WsFederation").GetValue<string>("MetadataAddress");
                        options.BackchannelHttpHandler = new HttpClientHandler()
                        {
                            ServerCertificateCustomValidationCallback = (_, __, ___, ____) => true
                        };
                    })
                    .AddCookie(options =>
                    {
                        options.DataProtectionProvider = DataProtectionProvider.Create("Base");
                        options.SlidingExpiration = true;

                        // options.ExpireTimeSpan = TimeSpan.FromMinutes(10);
                        options.Events.OnValidatePrincipal += context =>
                        {
                            Log("OnValidatePrincipal", "Validate Cookie for: {User}. Token Issued Utc: '{IssuedUtc}', Token Expires Utc: '{ExpiresUtc}', Cookie Option Valid For: '{CookieOptionValidFor}', Allow Refresh: {AllowRefresh}, ShouldRenew: {ShouldRenew}, Cookie Valid For: '{CookieValidFor}'",
                                context.HttpContext.GetUsername(),
                                context.Properties.IssuedUtc, context.Properties.ExpiresUtc,
                                context.Options.ExpireTimeSpan, context.Properties.AllowRefresh, context.ShouldRenew, context?.Options?.Cookie?.Expiration);

                            return Task.CompletedTask;
                        };

                        options.AccessDeniedPath = null;
                        options.Events.OnRedirectToAccessDenied = context =>
                        {
                            Log("OnRedirectToAccessDenied", "Denied for user: '{User}', For path: '{Url}', Method: '{Method}'", context.HttpContext.GetUsername(), context.Request.Path, context.Request.Method);
                            context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
                            return Task.CompletedTask;
                        };

                        options.Events.OnSignedIn = context =>
                        {
                            var username = context.Principal.FindFirstValue(ClaimTypes.Upn);
                            using (LogContext.PushProperty("User", username))
                            {
                                Log("OnSignedIn", "User '{User}' logged in at: '{At}', Token Expires At: '{Expires}', Sliding Expiration: '{SlidingExpiration}', Cookie Lifetime: '{CookieLifetime}'", 
                                    username, 
                                    DateTimeOffset.Now, 
                                    context.Properties.ExpiresUtc, 
                                    context.Options.SlidingExpiration, 
                                    context.Options.ExpireTimeSpan);
                            }
                            return Task.CompletedTask;
                        };

                        options.Events.OnSigningIn = context =>
                        {

                            context.Properties.AllowRefresh = true;
                            context.CookieOptions.Expires = DateTimeOffset.UtcNow.AddHours(8);

                            return Task.CompletedTask;
                        };
                    });

每次重新启动/重启应用时,用户都会被重定向到 adfs 端点,收到新的令牌并发出新的 cookie ...

我有一种感觉,我必须在这里遗漏一些东西......但不确定是什么。

正如所有日志条目所见,我已经尝试了很多......

我今天添加了 DataProtection 部分......它没有失败......应用程序像以前一样运行......它没有在“keys”目录中发布新的密钥环,所以我猜它正在使用该密钥环来解密数据。但是还是不行……

现在我没有想法,需要一些帮助来理解这个问题。

欢迎任何关于如何调试的提示或想法...

如果需要更多信息,请告诉我。

【问题讨论】:

    标签: asp.net authentication cookies .net-core


    【解决方案1】:

    我是 /#"()#/"(=!/#)("=#/ biiiiiip ...

    覆盖 options.DataProtectionProvider 在 Cookie 和 WsFederation 中......我的上帝。

    删除该部分后,现在每次重新启动后它都可以工作。我知道我在应用程序下使用了一个目录......但是在部署新版本时,密钥被更新并且用户必须再次登录是可以的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-06-15
      • 2014-10-31
      • 2021-05-24
      • 2013-04-05
      • 1970-01-01
      • 2020-12-03
      • 2012-09-06
      • 1970-01-01
      相关资源
      最近更新 更多