【问题标题】:ASP.NET API OAuth2 Refresh token - Deserialize ticket not workingASP.NET API OAuth2 刷新令牌 - 反序列化票证不起作用
【发布时间】:2017-12-06 04:57:38
【问题描述】:

我正在使用 ASP.NET API2 和 OWIN 实现 OAuth 2 刷新令牌,以下代码是我的 OAuthAuthorizationOptions

 public static OAuthAuthorizationServerOptions AuthorizationServerOptions
    {
        get
        {
            if (_AuthorizationServerOptions == null)
            {
                _AuthorizationServerOptions = new OAuthAuthorizationServerOptions()
                {
                    AuthenticationType = OAuthDefaults.AuthenticationType,
                    AllowInsecureHttp = true,
                    TokenEndpointPath = new PathString(AuthSettings.TokenEndpoint),
                    AuthorizeEndpointPath = new PathString(AuthSettings.AuthorizeEndpoint),
                    AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(AuthSettings.TokenExpiry),
                    Provider = new CustomOAuthAuthorizationServerProvider(AuthSettings.PublicClientId),
                    // TODO: Remove the dependency with Thinktecture.IdentityModel library here
                    AccessTokenFormat = new CustomJWTFormat(),
                    RefreshTokenProvider = new CustomRefreshTokenProvider()
                };
            }
            return _AuthorizationServerOptions;
        }
    }

这是我的 CustomRefreshTokenProvider 类

public override Task CreateAsync(AuthenticationTokenCreateContext context)
    {
        var identifier = context.Ticket.Identity.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier);
        if (identifier == null || string.IsNullOrEmpty(identifier.Value))
        {
            return Task.FromResult<object>(null);
        }
        var refreshToken = HashHelper.Hash(Guid.NewGuid().ToString("n"));
        var tokenIssued = DateTime.UtcNow;
        var tokenExpire = DateTime.UtcNow.AddSeconds(AuthSettings.RefreshTokenExpiry);
        context.Ticket.Properties.IssuedUtc = tokenIssued;
        context.Ticket.Properties.ExpiresUtc = tokenExpire;
        context.Ticket.Properties.AllowRefresh = true;
        var protectedTicket = context.SerializeTicket();
        AuthService.AddUserRefreshTokenSession(
            identifier.Value,
            refreshToken,
            tokenIssued,
            tokenExpire,
            protectedTicket);
        context.SetToken(refreshToken);
        return Task.FromResult<object>(null);
    }
    public override Task ReceiveAsync(AuthenticationTokenReceiveContext context)
    {
        var refToken = context.Token;
        var protectedTicket = AuthService.GetProtectedTicket(refToken);
        if (!string.IsNullOrEmpty(protectedTicket))
        {
            context.DeserializeTicket(protectedTicket);
        }
        return Task.FromResult<object>(null);
    }

我使用邮递员将 POST 请求发送到令牌端点,如下所示 Postman refresh token 服务器返回 400 错误请求状态码。 我调试了一下,发现 context.DeserializeTicket(protectedTicket) 抛出异常

Exception thrown: 'System.Security.Cryptography.CryptographicException' in System.Web.dll

我认为这不是过期问题,因为 AuthSettings.RefreshTokenExpiry 是从现在起 30 天。 我还尝试将机器密钥添加到我的 web.config OAuth Refresh Token does not deserialize / invalid_grant

但它仍然无法正常工作。

有人有想法吗? 任何解决方案都将受到高度赞赏。

【问题讨论】:

  • 你找到解决办法了吗,我也有同样的问题。
  • @Amin K 抱歉回复晚了,我刚回答,是你需要的吗?

标签: asp.net asp.net-web-api2 owin


【解决方案1】:

抱歉回复晚了。 我已经解决了这个问题并最终得到了一个从我的项目中完全删除 Thinktecture.Identity 的解决方案,因为它与 System.IdentityModel.Tokens.JWT.dll 有某种冲突

如果您仍想使用 Thinktecture.Identity,另一个解决方案是将 System.IdentityModel.Tokens.JWT 降级到 v4.0.2.206221351(这个版本对我有用,我没有用其他版本测试过)。

这里是CustomJWTFormat.cs的代码

using Microsoft.Owin.Security; using Microsoft.Owin.Security.OAuth; using MST.Service.Core.Logging; using System; using System.Security.Claims; namespace MST.Service.Core.Auth { public class CustomJWTFormat : ISecureDataFormat { private byte[] _SymetricKey = null; public CustomJWTFormat() { _SymetricKey = Convert.FromBase64String(AuthSettings.JwtTokenSecret); } /// /// Create jwt token /// /// /// Token string public string Protect(AuthenticationTicket data) { var tokenHandler = new System.IdentityModel.Tokens.JwtSecurityTokenHandler(); var now = DateTime.UtcNow; System.IdentityModel.Tokens.JwtSecurityToken jwtSecurityToken = new System.IdentityModel.Tokens.JwtSecurityToken( AuthSettings.Issuer, AuthSettings.JwtAudiences, data.Identity.Claims, DateTime.UtcNow, DateTime.UtcNow.AddMinutes(AuthSettings.TokenExpiry), new System.IdentityModel.Tokens.SigningCredentials( new System.IdentityModel.Tokens.InMemorySymmetricSecurityKey(_SymetricKey), System.IdentityModel.Tokens.SecurityAlgorithms.HmacSha256Signature, System.IdentityModel.Tokens.SecurityAlgorithms.Sha256Digest) ); var token = tokenHandler.WriteToken(jwtSecurityToken); return token; } public AuthenticationTicket Unprotect(string protectedText) { var tokenHandler = new System.IdentityModel.Tokens.JwtSecurityTokenHandler(); var validationParameters = new System.IdentityModel.Tokens.TokenValidationParameters() { RequireExpirationTime = true, ValidateIssuer = true, ValidateLifetime = true, AuthenticationType = OAuthDefaults.AuthenticationType, ValidIssuers = new string[] { AuthSettings.Issuer }, ValidAudiences = new string[] { AuthSettings.JwtAudiences }, ValidateAudience = true, ValidateIssuerSigningKey = false, IssuerSigningKey = new System.IdentityModel.Tokens.InMemorySymmetricSecurityKey(_SymetricKey) }; System.IdentityModel.Tokens.SecurityToken securityToken = null; ClaimsPrincipal principal = null; try { principal = tokenHandler.ValidateToken(protectedText, validationParameters, out securityToken); var validJwt = securityToken as System.IdentityModel.Tokens.JwtSecurityToken; if (validJwt == null) { throw new ArgumentException("Invalid JWT"); } } catch (Exception ex) { LoggerManager.AuthLog.Error($"Parse token error: {ex.ToString()}"); return null; } // Validation passed. Return a valid AuthenticationTicket: return new AuthenticationTicket(principal.Identity as ClaimsIdentity, new AuthenticationProperties()); } } }

和 JWTBearerAuthenticationOptions(如果您在同一台机器上托管资源服务器和授权服务器)

 public static JwtBearerAuthenticationOptions JwtAuthenticationOptions
    {
        get
        {
            if (_JwtAuthenticationOptions == null)
            {
                _JwtAuthenticationOptions = new JwtBearerAuthenticationOptions()
                {
                    //AuthenticationMode = Microsoft.Owin.Security.AuthenticationMode.Passive,
                    AuthenticationType = OAuthDefaults.AuthenticationType,
                    AllowedAudiences = new[] { AuthSettings.JwtAudiences },
                    IssuerSecurityTokenProviders = new IIssuerSecurityTokenProvider[]
                    {
                        new SymmetricKeyIssuerSecurityTokenProvider(AuthSettings.Issuer, AuthSettings.JwtTokenSecret)
                    }
                };
            }
            return _JwtAuthenticationOptions;
        }
    }

在 Startup.cs 中像往常一样注册中间件

app.UseJwtBearerAuthentication(AuthenticationOptions.JwtAuthenticationOptions);

【讨论】:

    猜你喜欢
    • 2015-07-16
    • 2016-08-03
    • 1970-01-01
    • 2021-08-24
    • 2017-04-19
    • 1970-01-01
    • 2015-01-08
    • 2017-04-20
    • 1970-01-01
    相关资源
    最近更新 更多