Identity Server 4-空闲时注销用户

时间:2019-02-08 13:40:20

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

Hej社区,

我被困住了,我需要一些建议或解决方案的指针。我有一个非常简单的Identity Server 4安装程序:

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

我想在闲置10分钟后自动注销用户。在下面的示例中,我使用10 s使测试更快。身份验证,重定向和用户执行的注销操作可以按预期方式进行,并且使用下面的代码像超级按钮一样。但是,当用户闲置时间超过设置的10秒时,该用户仍将登录,并且不会重定向到IDS主机上的登录页面。

使用混合授权设置MVC客户端为:

客户定义

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");
        });

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

问题

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

2 个答案:

答案 0 :(得分:3)

经过更多调试后,我发现MVC客户端的cookie生存期可以按预期的那样随着滑动到期而工作。但是,一旦Cookie过期,便会与Idenity Server(IDS)联系,并刷新cookie,因为该会话在IDS上仍处于活动状态。

我找到了两个解决方案,决定从中暂时使用 Solution 1 ,从长远来看,它是否最合适。

  

如果有人对安全性和最佳实践有任何评论或建议,请发表评论或发布其他解决方案。

解决方案1:客户端的最大SSO寿命

客户端属性UserSsoLifetime(在v2.3的Identity Server 4中可用)可用于设置用户必须重新认证才能使用客户端之前的最长时间。因此,对于该问题的示例,唯一需要的添加是在客户定义中,通过添加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属性解决了该问题,该属性可用于在会话期满后强制用户通过登录提示重新进行身份验证-请参见@Scotty Brady's answer

因此对于问题中指示的示例,应类似于以下内容。请注意,只有MVC客户端需要更改,即删除了Cookie生存期,并添加了OIDC选项以强制进行重新身份验证并使用IDS中的令牌生存期(每行标记有// <- HERE)。这样,将使用IDS中的cookie设置(滑动寿命为10s)。

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");
        });

答案 1 :(得分:1)

您可以使用IdentityServer的End Session Endpoint

  

结束会话终结点可用于触发单点退出(see spec)。

     

要使用结束会话终结点,客户端应用程序将重定向   用户的浏览器到结束会话的网址。用户的所有应用程序   在用户会话期间通过浏览器登录可以   参加登出。

您可以使用此端点使用 post_logout_redirect_uri 参数将最终用户重定向回登录页面。