c# - Identity Server 4 - 空闲时注销用户

标签 c# asp.net-core .net-core identityserver4 openid-connect

Hej 社区,

我陷入困境,我需要一些建议或解决方案。我有一个相当简单的 Identity Server 4 设置:

  1. 具有 ASP.NET Identity 的 Identity Server 4
  2. ASP.NET Core 2.2 MVC 客户端

我想在 10 分钟不活动后自动注销用户。在下面的示例中,我使用了 10 秒来使测试更快一些。身份验证、重定向和用户强制注销按预期工作,就像使用下面的代码的魅力一样。但是,当用户空闲时间超过设置的10秒时,用户仍然处于登录状态,并且不会重定向到IDS主机上的登录页面。

MVC 客户端使用 Hybrid Grant 设置为:

客户定义

var mvcClient = new Client
{
    ClientId = "account-mvc",
    ClientName = "Account MVC",
    ClientUri = "https://localhost:5002",

    AllowedGrantTypes = GrantTypes.Hybrid,
    ClientSecrets = { new Secret("secret".Sha256()) },

    EnableLocalLogin = true,
    RequireConsent = false,
    AllowOfflineAccess = false,
    AccessTokenLifetime = 10,   // 10 s by intention
    IdentityTokenLifetime = 10, // 10 s by intention

    RedirectUris = "https://localhost:5002/signin-oidc",
    PostLogoutRedirectUris = "https://localhost:5002/signout-callback-oidc",
    FrontChannelLogoutUri = "https://localhost:5002/signout-oidc",

    AllowedScopes =
    {
        IdentityServerConstants.StandardScopes.OpenId,
        IdentityServerConstants.StandardScopes.Profile,
        IdentityServerConstants.StandardScopes.Email,
    },
};

身份服务器选项

services.AddIdentityServer(options =>
{
    options.Authentication.CheckSessionCookieName = "auth-cookie";
    options.Authentication.CookieLifetime = new System.TimeSpan(0, 0, 10);
    options.Authentication.CookieSlidingExpiration = false;

    options.Csp.Level = IdentityServer4.Models.CspLevel.Two;

    options.Events.RaiseErrorEvents = true;
    options.Events.RaiseInformationEvents = true;
    options.Events.RaiseFailureEvents = true;
    options.Events.RaiseSuccessEvents = true;
})
.Add... // Left out for brevity

在 MVC 客户端的启动中我添加:

MVC 客户端启动

services.AddAuthentication(options =>
        {
            options.DefaultScheme = "Cookies";
            options.DefaultChallengeScheme = "oidc";
        })
        .AddCookie("Cookies", options => 
        {
            options.ExpireTimeSpan = TimeSpan.FromSeconds(10);
            options.SlidingExpiration = false;
            options.Cookie.Name = "mvc-cookie";
        })
        .AddOpenIdConnect("oidc", options =>
        {
            options.SignInScheme = "Cookies";

            options.Authority = "https://localhost:5001/";
            options.ClientId = "account-mvc";
            options.ClientSecret = "secret";
            options.ResponseType = "code id_token";

            options.SaveTokens = true;
            options.GetClaimsFromUserInfoEndpoint = true;

            options.Scope.Add("openid");
            options.Scope.Add("profile");
            options.Scope.Add("email");
        });

并在Configure方法中添加了app.UseAuthentication()

问题

一旦 session 超时,如何确保用户在 Identity Server 上注销?任何提示和帮助表示赞赏!

最佳答案

经过更多调试后,我发现 MVC 客户端的 cookie 生命周期按预期工作,并且具有滑动到期时间。然而,一旦 cookie 过期,就会联系 Idenity Server (IDS) 并刷新 cookie,因为 session 在 IDS 上仍然处于事件状态/事件状态。

我想出了两种解决方案,并决定暂时使用解决方案 1,看看从长远来看它是否最合适。

If anyone has a comment or recommendation towards security and best practice please comment or post another solution.

解决方案 1:客户端的最大 SSO 生命周期

客户属性(property) UserSsoLifetime (在 Identity Server 4 中可用 v2.3 )可用于设置用户必须重新进行身份验证才能使用客户端的最长时间。因此,对于问题的示例,唯一需要添加的是在客户端定义中添加 UserSsoLifetime = 10 ,例如,

客户定义

var mvcClient = new Client
{
    ClientId = "account-mvc",
    ClientName = "Account MVC",
    ClientUri = "https://localhost:5002",

    AllowedGrantTypes = GrantTypes.Hybrid,
    ClientSecrets = { new Secret("secret".Sha256()) },

    EnableLocalLogin = true,
    RequireConsent = false,
    AllowOfflineAccess = false,
    UserSsoLifetime = 10,       // <- HERE
    AccessTokenLifetime = 10,   // 10 s by intention
    IdentityTokenLifetime = 10, // 10 s by intention

    RedirectUris = "https://localhost:5002/signin-oidc",
    PostLogoutRedirectUris = "https://localhost:5002/signout-callback-oidc",
    FrontChannelLogoutUri = "https://localhost:5002/signout-oidc",

    AllowedScopes =
    {
        IdentityServerConstants.StandardScopes.OpenId,
        IdentityServerConstants.StandardScopes.Profile,
        IdentityServerConstants.StandardScopes.Email,
    },
};

这将强制用户在 10 秒不活动后重新进行身份验证。

解决方案 2:OIDC 属性

这个SO question解决了 OIDC 属性的问题,该属性可用于强制用户在 session 过期后通过登录提示重新进行身份验证 - 请参阅 @Scotty Brady's answer .

因此,问题中指出的示例应如下所示。请注意,只有 MVC 客户端需要更改,即删除 Cookie 生命周期并添加 OIDC 选项,强制重新身份验证并使用 IDS 中的 token 生命周期(每行标记有 // <- HERE )。这样,就可以使用 IDS 的 cookie 设置(滑动生命周期为 10 秒)。

MVC 客户端启动

services.AddAuthentication(options =>
        {
            options.DefaultScheme = "Cookies";
            options.DefaultChallengeScheme = "oidc";
        })
        .AddCookie("Cookies") // <- HERE
        .AddOpenIdConnect("oidc", options =>
        {
            options.SignInScheme = "Cookies";

            options.Authority = "https://localhost:5001/";
            options.ClientId = "account-mvc";
            options.ClientSecret = "secret";
            options.ResponseType = "code id_token";

            options.UseTokenLifetime = true; // <- HERE
            options.SaveTokens = true;
            options.GetClaimsFromUserInfoEndpoint = true;

            options.Events.OnRedirectToIdentityProvider = context => // <- HERE
            {                                                        // <- HERE
                context.ProtocolMessage.Prompt = "login";            // <- HERE
                return Task.CompletedTask;                           // <- HERE
            };                                                       // <- HERE

            options.Scope.Add("openid");
            options.Scope.Add("profile");
            options.Scope.Add("email");
        });

关于c# - Identity Server 4 - 空闲时注销用户,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54593677/

相关文章:

c# - 如何在 C# 中计算整数的除法和模数?

c# - MVC3 中的 "Hooks"

entity-framework-core - EF Core 1.1-preview1 添加迁移错误

docker - 通过 docker 容器从控制台应用程序连接到 redis

c# - 使用 FromQuery 时是否可以将类对象默认为 null

c# - ASP.NET Core 测试 - 在夹具中初始化 InMemory SQLite dbcontext 时获取 NullReferenceException

c# - ResourceDictionary.MergedDictionaries导致奇怪的错误

c# - "System.IO.Stream+NullStream"到底是什么/意味着什么?

c# - 在 Web API 调用中检索 SignalR connectionId

c# - ASP.Net Core 在运行时注册 Controller