2017-05-25 227 views
1

我有一个REST API使用OAuth熊标记身份验证。令牌由不对称密钥签名,REST api使用公钥验证令牌。我得到了下面的代码工作。但是,有一种情况需要在需要更新密钥时处理。我正在考虑传入一个辅助公钥,并让该框架首先使用主键和辅助键验证令牌。这样,当我需要更新密钥时,我可以轻松添加二级密钥,交换和退出。问题是看下面的代码只需要一个签名密钥。有没有办法指定多个?如何在UseJwtBearerAuthentication中指定多个IssuerSigningKey?

public void ConfigureAuth(IAppBuilder app) 
    { 
     app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll); 

     // codes to get signningKey ignored here 

     app.UseJwtBearerAuthentication(
      new JwtBearerAuthenticationOptions 
      { 
       TokenValidationParameters = new TokenValidationParameters 
       { 
        ValidateAudience = false, 
        ValidateIssuer = false, 
        IssuerSigningKey = new RsaSecurityKey(signingKey) 
       }, 
      }); 
    } 

感谢,

回答

0

好吧,我想我想通了。有两种方法。一个简单直接的方法是使用IssuerSigningKeys属性(我怎么不能在第一时间发现它)。代码如下所示:

 app.UseJwtBearerAuthentication(
      new JwtBearerAuthenticationOptions 
      { 
       TokenValidationParameters = new TokenValidationParameters 
       { 
        ValidateAudience = false, 
        ValidateIssuer = false, 
        IssuerSigningKeys = new List<RsaSecurityKey> 
        { 
         Utils.GetSigningKey(isPrimary: true), 
         Utils.GetSigningKey(isPrimary: false) 
        }, 
       }, 
      }); 

第二种方法是自定义IOAuthBearerAuthenticationProvider。该代码看起来是这样的:首先,

 app.UseJwtBearerAuthentication(
      new JwtBearerAuthenticationOptions 
      { 
       AllowedAudiences = new string[] { "*" }, 
       IssuerSecurityTokenProviders = new List<IIssuerSecurityTokenProvider>() 
       { 
        // Dummy object which won't be used anywhere. It is used to work around parameter validation error about no token provider specified. 
        new SymmetricKeyIssuerSecurityTokenProvider("dummy", "dummy") 
       }, 

       // This is where validation work happens. 
       Provider = new BearerAuthenticationProvider(app) 
      }); 

然后,BearerAuthenticationProvider类:

/// <summary> 
/// Bearer authentication provider. 
/// </summary> 
public class BearerAuthenticationProvider : IOAuthBearerAuthenticationProvider 
{ 
    /// <summary> 
    /// App config. 
    /// </summary> 
    private readonly IAppBuilder appConfig; 

    /// <summary> 
    /// Handles applying the authentication challenge to the response message. 
    /// </summary> 
    public Func<OAuthChallengeContext, Task> OnApplyChallenge { get; set; } 

    /// <summary> 
    /// Handles processing OAuth bearer token. 
    /// </summary> 
    public Func<OAuthRequestTokenContext, Task> OnRequestToken { get; set; } 

    /// <summary> 
    /// Handles validating the identity produced from an OAuth bearer token. 
    /// </summary> 
    public Func<OAuthValidateIdentityContext, Task> OnValidateIdentity { get; set; } 

    /// <summary> 
    /// Initializes a new instance of the <see cref="T:Microsoft.Owin.Security.OAuth.OAuthBearerAuthenticationProvider" /> class 
    /// </summary> 
    public BearerAuthenticationProvider(IAppBuilder appConfig) 
    { 
     this.appConfig = appConfig; 
     this.OnRequestToken = (OAuthRequestTokenContext context) => 
     { 
      var idContext = new OAuthValidateIdentityContext(context.OwinContext, null, null); 

      this.ValidateIdentity(idContext); 
      return Task.FromResult<int>(0); 
     }; 
     this.OnValidateIdentity = (OAuthValidateIdentityContext context) => Task.FromResult<object>(null); 
     this.OnApplyChallenge = (OAuthChallengeContext context) => Task.FromResult<object>(null); 
    } 

    /// <summary> 
    /// Handles applying the authentication challenge to the response message. 
    /// </summary> 
    /// <param name="context"></param> 
    /// <returns></returns> 
    public Task ApplyChallenge(OAuthChallengeContext context) 
    { 
     return this.OnApplyChallenge(context); 
    } 

    /// <summary> 
    /// Handles processing OAuth bearer token. 
    /// </summary> 
    /// <param name="context"></param> 
    /// <returns></returns> 
    public virtual Task RequestToken(OAuthRequestTokenContext context) 
    { 
     return this.OnRequestToken(context); 
    } 

    /// <summary> 
    /// Handles validating the identity produced from an OAuth bearer token. 
    /// </summary> 
    /// <param name="context"></param> 
    /// <returns></returns> 
    public virtual Task ValidateIdentity(OAuthValidateIdentityContext context) 
    { 
     const string AuthHeaderName = "Authorization"; 
     if (context.Request.Headers.ContainsKey(AuthHeaderName)) 
     { 
      var jwt = context.Request.Headers[AuthHeaderName].Replace("Bearer ", string.Empty); 
      var token = new JwtSecurityToken(jwt); 
      var claimIdentity = new ClaimsIdentity(token.Claims, "ExternalBearer"); 

      var param = new TokenValidationParameters() 
      { 
       ValidateAudience = false, 
       ValidateIssuer = false, 
       IssuerSigningKeys = new List<RsaSecurityKey> 
       { 
        Utils.GetSigningKey(isPrimary: true), 
        Utils.GetSigningKey(isPrimary: false) 
       }, 
      }; 

      SecurityToken securityToken = null; 
      var handler = new JwtSecurityTokenHandler(); 
      var identity = handler.ValidateToken(token.RawData, param, out securityToken); 

      var claimPrincipal = new ClaimsPrincipal(claimIdentity); 
      context.Response.Context.Authentication.User = claimPrincipal; 
      context.Validated(claimIdentity); 
     } 
     else 
     { 
      throw new Exception("Invalid authorization header."); 
     } 

     return this.OnValidateIdentity(context); 
    } 
} 

第一种方法初始化在应用程序启动,只有做出改变路两个签名密钥,当进程重新启动。第二种方法在运行时检索密钥,因此密钥翻转不需要重新启动服务。

相关问题