首页 > 解决方案 > Identity Server 和 ASP.NET Core Identity 的单独 Cookie 过期时间

问题描述

我目前有一个有效的 Identity Server 4 实例,用于保护本机移动应用程序(iOS 和 Android)访问的 API。对于这些移动应用程序,我们要求退出过程是删除从 Identity Server 接收到的令牌的情况(例如,没有到 Identity Server 的往返)。

我们目前面临的问题是,当用户退出并立即尝试再次登录时,浏览器“认为”用户已经通过身份验证,因为第一次登录时存在 Identity Server Auth cookie在。

目前我们的 Identity Server 配置使用 Asp.Net Core Identity 和Quickstart UI,我已经能够通过将 ASP.NET Core Identity cookie 的过期时间更改为 1 秒来解决这种情况,如下所示:

services.AddIdentity<UserEntity, ApplicationRoleEntity>()
.AddEntityFrameworkStores<UserContext>()
.AddDefaultTokenProviders();

services.ConfigureApplicationCookie(options =>
{
    options.ExpireTimeSpan = TimeSpan.FromSeconds(1);
});

因为 Auth cookie 现在在一秒钟后过期,所以当用户退出 Native 应用程序并立即尝试再次登录时,他们会看到 Identity Server 登录 UI,并且登录会按预期工作。

然而,当在浏览器中使用时(不是作为登录的一部分),上述更改显然会影响 Quickstart UI 本身的使用,因为当 cookie 在一秒钟后过期时,用户会立即从快速启动应用程序中注销。

我希望在这里实现的可能是将 ASP.Net Core Identity cookie 与 Identity Server 使用的 Auth Cookie 分开 - 基本上这样 Native App 可以继续按原样运行(使用立即无效的 Identity Server Auth cookie登录后无效,因为此时我们有我们的令牌)但用户可以在浏览器中使用快速启动 UI,而他们的该应用程序的 cookie 不会立即过期。

2018 年 10 月 30 日更新 - 建议的解决方案

查看我的原始帖子后,总结此要求的最简单方法是,当通过本机应用程序登录时,我要求用户始终必须通过登录过程,即使浏览器具有有效的身份验证 cookie服务器。这意味着注销过程可以简单地删除本地存储的令牌,因为当用户尝试再次登录时,他们将再次经历登录过程。

我现在有一个似乎可以满足我的要求的解决方案,它涉及为 ASP.NET Core Identity and Identity Server 使用的应用程序 cookie 创建一个 CookieEvents 类。这是在启动时设置如下。

services.ConfigureApplicationCookie(options =>
{
    options.EventsType = typeof(CookieEvents);
});

在 CookieEvents 类中,当授权端点发生登录事件时,我将一个新项目添加到 AuthenticationItems.Items 字典中。在未来从本机移动应用程序(我使用 CookieEvents 的 ValidatePrincipal 中的查询字符串中的 client_id 识别)向授权端点发出登录请求时,我然后检查是否存在添加到 cookie 的项目,如果找到,则主体是被拒绝,这会强制用户再次执行登录过程,即使用于登录的浏览器具有有效的身份验证 cookie。下面的 CookieEvents 类示例(为简洁起见,删除了私有方法)

public override Task SigningIn(CookieSigningInContext context)
{
    if (IsRequestToAuthorizeEndpoint(context.Request) &&
    !context.Properties.Items.ContainsKey("signed-in"))
    {
        context.Properties.Items.Add("signed-in", "true");
    }

    return base.SigningIn(context);
}

public override Task ValidatePrincipal(CookieValidatePrincipalContext 
context)
{
    if (IsNativeAppSignIn(context.Request) &&
        context.Properties.Items.ContainsKey("signed-in"))
    {
        context.RejectPrincipal();
        return Task.CompletedTask;
    }

    return base.ValidatePrincipal(context);
}

在测试中,这似乎运行良好,也意味着如果用户在浏览器中使用实际 UI,他们现在不再立即退出,因为 1 秒到期不再存在。

作为一种解决方案,这种方法是否存在任何明显的缺陷,即始终希望用户在从本机应用程序登录时通过登录流程,即使他们的浏览器具有身份验证 cookie?

标签: asp.net-core-mvcasp.net-identityidentityserver4

解决方案


推荐阅读