OAuth2 WebApi 令牌过期

Posted

技术标签:

【中文标题】OAuth2 WebApi 令牌过期【英文标题】:OAuth2 WebApi Token Expiration 【发布时间】:2016-02-15 13:05:38 【问题描述】:

我正在尝试动态设置令牌过期时间,但它似乎只是默认为 20 分钟。

这是我的 ConfigureAuth:

public void ConfigureAuth(IAppBuilder app)


        OAuthOptions = new OAuthAuthorizationServerOptions
        
            TokenEndpointPath = new PathString("/Token"),
            Provider = new ApplicationOAuthProvider(""),
            // In production mode set AllowInsecureHttp = false
            AllowInsecureHttp = true
        ;

        // Enable the application to use bearer tokens to authenticate users
        app.UseOAuthBearerTokens(OAuthOptions);


这是我的 GrantResourceOwnerCredentials 方法:

    public override Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
    

        context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[]  "*" );

        var hasValidLogin = (new login().authenticate(context.UserName, context.Password, "") == "valid");

        if (hasValidLogin == false)
        
            context.SetError("invalid_grant", "The user name or password is incorrect.");
            return Task.FromResult<object>(null);
        

        var oAuthIdentity = CreateIdentity(context);
        var oAuthProperties = CreateProperties(context);

        AuthenticationTicket ticket = new AuthenticationTicket(oAuthIdentity, oAuthProperties);

        context.Validated(ticket);
        return Task.FromResult<object>(null);
    

这是我可以设置过期时间的 SetProperties 方法:

    public static AuthenticationProperties CreateProperties(OAuthGrantResourceOwnerCredentialsContext context)
    

        IDictionary<string, string> data = new Dictionary<string, string>
        
             "client_id", context.ClientId 
        ;

        var response = new AuthenticationProperties(data);
        response.ExpiresUtc = DateTime.Now.AddMonths(1);

        return response;
    

即使在那之后,令牌仍在返回:


  "access_token": ".....",
  "token_type": "bearer",
  "expires_in": 1199,
  "client_id": ".....",
  ".expires": "Fri, 13 Nov 2015 20:24:06 GMT",
  ".issued": "Fri, 13 Nov 2015 20:04:06 GMT"

任何想法为什么我不能在当前位置设置到期时间?该服务器将采用具有不同指定到期时间的各种不同客户端,因此我认为这是执行此操作的地方。还有其他地方我应该这样做吗?谢谢!

【问题讨论】:

【参考方案1】:

您看到的行为直接是由于 OAuth2 授权服务器总是在您在 GrantResourceOwnerCredentials 通知中设置它时丢弃您自己的过期时间(其他 Grant* 通知也是受影响):https://github.com/jchannon/katanaproject/blob/master/src/Microsoft.Owin.Security.OAuth/OAuthAuthorizationServerHandler.cs#L386

解决方法是将到期日期设置为 AuthenticationTokenProvider.CreateAsync(用于OAuthAuthorizationServerOptions.AccessTokenProvider的类):

只需将context.Ticket.Properties.ExpiresUtc 设置为您选择的到期日期,它就会按预期工作:

public class AccessTokenProvider : AuthenticationTokenProvider

    public override void Create(AuthenticationTokenCreateContext context)
    
        context.Ticket.Properties.ExpiresUtc = // set the appropriate expiration date.

        context.SetToken(context.SerializeTicket());
    


您还可以查看AspNet.Security.OpenIdConnect.Server,它是 OWIN/Katana 提供的 OAuth2 授权服务器的一个分支,本机支持从 GrantResourceOwnerCredentials 设置到期日期:https://github.com/aspnet-contrib/AspNet.Security.OpenIdConnect.Server/tree/dev

【讨论】:

@Pinpoint 但是为什么“OAuth2 授权服务器在您在 GrantResourceOwnerCredentials 中设置它时总是丢弃您自己的过期时间”? 可能是一个错误(它不会是第一个,并且由于该组件不再维护,因此没有修复) @Pinpoint 我和katanaproject.codeplex.com/SourceControl/latest#src/…有同样的行为 同一个项目(我只使用GitHub,因为它更容易定位特定行) @Pinpoint 我在重播“这个组件不再维护”,我认为是【参考方案2】:

您可以在TokenEndPoint 方法而不是GrantResourceOwnerCredentials 方法中设置它。请参阅我对类似问题的回答here。

希望对你有帮助。

【讨论】:

【参考方案3】:

我将把它扔在这里,截至目前,有一种更简单的方法,无需创建新类,它只是设置选项:

OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()

    ...
    AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(30),
    ..
;

【讨论】:

Erti-Chris Eelmaa,这样您就可以为所有令牌设置一般超时。问题是动态设置它。【参考方案4】:

我们也有类似的情况,不同的客户端有不同的令牌超时时间,因此我们希望能够相应地设置过期时间。在我们实现的 AuthenticationTokenProvider 中,我们设置了过期时间,但在签名令牌时它被覆盖了。

我们最终满意的解决方案是覆盖 TokenEndpoint 方法。然后我们就可以实现客户端特定的过期:

    public override Task TokenEndpoint(OAuthTokenEndpointContext context)
    
        if (context.TokenIssued)
        
            // client information
            var accessExpiration = DateTimeOffset.Now.AddSeconds(accessTokenTimeoutSeconds);
            context.Properties.ExpiresUtc = accessExpiration;
        

        return Task.FromResult<object>(null);
    

*已编辑以解决竞争条件。

【讨论】:

我认为这不安全。 context.Options 在请求之间共享。对于并行进行的请求,您将覆盖 AccessTokenExpireTimeSpan 谢谢@user3608068,我已经相应地更新了答案! 感谢分享,我目前也在配置一个 API 以根据客户端发布具有不同到期时间的令牌。这非常有效。

以上是关于OAuth2 WebApi 令牌过期的主要内容,如果未能解决你的问题,请参考以下文章

Xamarin.iOS / Web API JWT 刷新令牌(如果过期)

GoogleAPI oauth2 刷新令牌在 1 小时后过期

google oauth2 刷新令牌何时过期?

移动应用程序的 OAuth2 访问令牌是不是必须过期?

OAuth 2.0 刷新令牌是不是完全过期?

Webapi 2.0如何在访问令牌过期时实现刷新JWT令牌