WebAPI中的绝对和空闲会话超时

时间:2016-05-25 05:44:31

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

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

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

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

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

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

是否有任何解决方案或样本适用于我的问题? 目前,我删除了该刷新令牌功能,因此用户必须在100分钟后再次登录。

非常感谢。

1 个答案:

答案 0 :(得分:0)

我没有看到在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);
    }
    ...
}

当资源服务器获取令牌中包含的票证时,可以将属性中的值与当前时间进行比较。如果差异大于8小时可以返回401 - 未经授权的响应,强制客户端应用程序要求另一个访问令牌:

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协议无关。

我希望它可以帮到你。