【问题标题】:Absolute and idle session timeout owin WebAPIWebAPI 中的绝对和空闲会话超时
【发布时间】:2016-09-22 13:25:57
【问题描述】:

我正在使用 OAuth Bearer 身份验证创建一个 WebAPI,如下所示:

       var oAuthServerOptions = new OAuthAuthorizationServerOptions
        {
            TokenEndpointPath = new PathString("/token"),
            AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(100),
            Provider = new AuthorizationServerProvider(),
            RefreshTokenProvider = new RefreshTokenProvider(),
        };

应用程序将为经过身份验证的用户生成令牌,令牌将在 100 分钟后过期。用户必须使用刷新令牌才能继续访问应用程序。 现在,我想将政策更改如下:

  • 如果用户空闲 100 分钟,则用户必须再次登录(应用程序必须返回 401)- 空闲超时
  • 如果用户没有空闲,则用户必须在 8 小时后再次登录 - 绝对超时

我已经搜索了几天,但找不到任何合适的解决方案

这里有解决我的问题的解决方案或示例吗? 目前,我删除了刷新令牌功能,因此用户必须在 100 分钟后再次登录。

非常感谢。

【问题讨论】:

    标签: session asp.net-web-api timeout token owin


    【解决方案1】:

    我看不到在 OAuth 2.0 中同时出现两个超时的方法。

    仅关于第一次超时,空闲超时,可以设置刷新令牌超时为100分钟。访问令牌超时时间会更短,每次访问令牌过期时,您都会获得新的访问令牌和刷新令牌。如果用户会话空闲超过 100 分钟,当应用尝试刷新令牌时,oauth 服务器会意识到刷新令牌已过期且无效。然后用户需要输入他们的凭据。

    对于第二次超时,您可以将访问令牌超时设置为 8 小时,并且不实施刷新令牌。

    考虑到令牌将被发送到资源服务器,这不能与 oauth 服务器相同。资源服务器只能检查令牌中的票证是否未过期,但无法控制用户输入凭据后第一次授予令牌的时间。

    如果您同时控制 oauth 和资源服务器,则可以采取一种变通方法,为刷新令牌实现 100 分钟超时,并在票证中包含用户输入凭据的时间属性。请以以下代码为例:

    public class AuthorizationServerProvider : OAuthAuthorizationServerProvider
    {
        ...
        public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
        {
            ...
            var props = new AuthenticationProperties(new Dictionary<string, string>
            {
                {
                    "client_id", clientId
                },
                { 
                    "ownerCredentialsTimestamp", DateTime.UtcNow.ToString()
                }
            });
    
            var ticket = new AuthenticationTicket(identity, props);
            context.Validated(ticket);
        }
        ...
    }
    

    当资源服务器获取到token中包含的ticket时,可以将属性中的值与当前时间进行比较。在差异大于 8 小时的情况下可以返回 401 - Unauthorized 响应,强制客户端应用请求另一个访问令牌:

    public class AccessTokenProvider : IAuthenticationTokenProvider
    {
        public async Task ReceiveAsync(AuthenticationTokenReceiveContext context)
        {
            context.DeserializeTicket(context.Token);
    
            if (context.Ticket.Properties.Dictionary["ownerCredentialsTimestamp"] != null)
            {
                var ownerCredentialsTimestamp = Convert.ToDateTime(context.Ticket.Properties.Dictionary["ownerCredentialsTimestamp"]).ToUniversalTime();
    
                if (/* difference is bigger than 8 hours */)
                {
                    context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
                }
            }
        }
    }
    

    此时,客户端应用程序将尝试通过“refresh_token”请求获取新的访问令牌。 oauth 服务器必须再次检查与当前刷新令牌相关的最后输入凭据的时间,数据库表中可能有一列存储刷新令牌(如果这是您的情况)。

    您可以在RefreshTokenProvider.ReceiveAsync() 方法中查看:

    public class RefreshTokenProvider : IAuthenticationTokenProvider
    {
        ...
        public async Task ReceiveAsync(AuthenticationTokenReceiveContext context)
        {
            ...
            /* Check the received refresh token, including the last time that the credentials were entered for this user */
            ...
        }
        ...
    }
    

    或者在AuthorizationServerProvicer.GrantRefreshToken()方法中:

    public class AuthorizationServerProvider : OAuthAuthorizationServerProvider
    {
        ...
        public override async Task GrantRefreshToken(OAuthGrantRefreshTokenContext context)
        {
            ...
            /* Check the last time that the credentials were entered for this user */
            ...
        }
        ...
    }
    

    这是一个非常特殊的解决方案,与 OAuth 2.0 协议无关。

    希望对你有帮助。

    【讨论】:

    • 您的解决方案听起来很不错。我将检查我当前的源代码并尽快回复。非常感谢。 :)
    • 您的回答给了我一个想法来完成我的问题。谢了。
    猜你喜欢
    • 1970-01-01
    • 2012-02-17
    • 2013-06-18
    • 2022-08-17
    • 2012-03-31
    • 1970-01-01
    • 2021-03-07
    • 2013-03-31
    • 1970-01-01
    相关资源
    最近更新 更多