2016-04-14 16 views
2

私はoAuth 2.0ミドルウェアを使用してJWTを検証しようとしています。私は私のStartup.csクラスでカスタムプロバイダを使用してみました:oAuth 2.0/owinでJWTトークン検証をカスタマイズする方法は?

public class CustomOAuthBearerProvider : IOAuthBearerAuthenticationProvider 
{ 
    public Task ApplyChallenge(OAuthChallengeContext context) 
    {    
     return Task.FromResult<object>(null); 
    } 

    public Task RequestToken(OAuthRequestTokenContext context) 
    {    
     return Task.FromResult<object>(null); 
    } 

    public Task ValidateIdentity(OAuthValidateIdentityContext context) 
    {    
     return Task.FromResult<object>(null); 
    } 
} 
:IOAuthBearerAuthenticationProviderを継承し、私のCustomOAuthBearerProviderで

public class Startup 
{ 
    public void Configuration(IAppBuilder app) 
    { 
     HttpConfiguration config = new HttpConfiguration(); 

     // Web API routes 
     config.MapHttpAttributeRoutes(); 

     ConfigureOAuth(app); 

     app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll); 

     app.UseWebApi(config); 

    } 

    public void ConfigureOAuth(IAppBuilder app) 
    { 

     OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions() 
     { 
      //For Dev enviroment only (on production should be AllowInsecureHttp = false) 
      AllowInsecureHttp = true, 
      TokenEndpointPath = new PathString("/oauth2/token"), 
      AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(5), 
      Provider = new CustomOAuthProvider(), 
      AccessTokenFormat = new RMAJwtAuthenticator.CustomJwtFormat("www.abc.com") 
     }; 

     // OAuth 2.0 Bearer Access Token Generation 
     app.UseOAuthAuthorizationServer(OAuthServerOptions); 

     // start : Code for Validating JWT 
     var issuer = "www.abc.com"; 
     var audience = "www.xyz.com"; 
     var secret = TextEncodings.Base64Url.Decode("Yuer534553HDS&dsa"); 

     // Api controllers with an [Authorize] attribute will be validated with JWT 
     app.UseJwtBearerAuthentication(
      new JwtBearerAuthenticationOptions 
      { 
       AuthenticationMode = AuthenticationMode.Active, 
       AllowedAudiences = new[] { audience }, 
       IssuerSecurityTokenProviders = new IIssuerSecurityTokenProvider[] 
       { 
        new SymmetricKeyIssuerSecurityTokenProvider(issuer, secret) 
       }, 
       Provider = new CustomOAuthBearerProvider() 


      }); 

     //End: Code for Validating JWT 

    } 
} 

、私はApplyChallenge()、RequestToken()とValidateIdentity()のdefinationを提供しました

今、私はAuthorizedリソースを取得しようとすると、最初のRequestToken()がヒットし、JWTがどのように検証され、コントロールがValidateIdentity()メソッドに渡されたのかわかりません。

私が検証プロセスをカスタマイズしたいのは、データベースにJWTの有効期限を保存して拡張することです(元のトークンを変更せずにJWTの有効期限を延長することもできます)。

ご意見、ご提案、良い悪い練習のオプションやリンクがあれば、助けてください。 ありがとうございます。

答えて

3

実際にJWTのカスタム検証を行うことができます。私は期限切れ時間のないJWTを作成し、その署名を通して検証しました.JWTで有効期限を過ぎても同じことができます。 さて、先に好き代わりJWTBearerAuthenticationを使用しての、私たちは以下のようにOAuthBearerAuthenticationを使用することができます。

public void ConfigureOAuth(IAppBuilder app) 
    { 
     OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions() 
     { 
      //For Dev enviroment only (on production should be AllowInsecureHttp = false) 
      AllowInsecureHttp = true, 
      TokenEndpointPath = new PathString("/api/token"), 
      //provide Expire Time 
      //AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(5), 
      Provider = new CustomOAuthProvider(), 
      //provide issuer name/url 
      // 
      AccessTokenFormat = new RMAJwtAuthenticator.CustomJwtFormat("www.abc.com") 
     }; 

     // OAuth 2.0 Bearer Access Token Generation 
     app.UseOAuthAuthorizationServer(OAuthServerOptions); 

     //// start : Code for Validating JWT 

     OAuthBearerAuthenticationOptions OAuthBearerOptions = new OAuthBearerAuthenticationOptions() 
     { 
      AccessTokenFormat = OAuthServerOptions.AccessTokenFormat, 
      AccessTokenProvider = OAuthServerOptions.AccessTokenProvider, 
      AuthenticationMode = OAuthServerOptions.AuthenticationMode, 
      AuthenticationType = OAuthServerOptions.AuthenticationType, 
      Description = OAuthServerOptions.Description, 
      Provider = new CustomOAuthBearerProvider() 
     }; 
     app.UseOAuthBearerAuthentication(OAuthBearerOptions); 

     //////End: Code for Validating JWT 

    } 

そして、あなたがある保護を解除方法をあなたのJWTを検証するために、あなたのJWTを作成し、同じCustomJwtFormatクラスを使用することができますISecureDataFormatインターフェイスで宣言されています。

public class CustomJwtFormat : ISecureDataFormat<AuthenticationTicket> 
{ 
    //Needs to be configured in Configuration file 
    const string AudiencePropertyKey = "audience"; 
    const string signatureAlgorithm = "www.w3.org/2001/04/xmldsig-more#hmac-sha256"; 
    const string digestAlgorithm = "www.w3.org/2001/04/xmlenc#sha256"; 

    private readonly string _issuer = string.Empty; 

    public CustomJwtFormat(string issuer) 
    { 
     _issuer = issuer; 
    } 

    /// <summary> 
    /// Creates JWT Token here, using AuthenticationTicket 
    /// </summary> 
    /// <param name="data"></param> 
    /// <returns></returns> 
    public string Protect(AuthenticationTicket data) 
    { 
     JwtAuthHelper objJwtAuthHelper = new JwtAuthHelper(); 
     try 
     { 
      if (data == null) 
      { 
       throw new ArgumentNullException("data"); 
      } 

      string audienceId = data.Properties.Dictionary.ContainsKey(AudiencePropertyKey) ? data.Properties.Dictionary[AudiencePropertyKey] : null; 

      if (string.IsNullOrWhiteSpace(audienceId)) throw new InvalidOperationException("AuthenticationTicket.Properties does not include audience"); 

      //check if audience is valid (in case of audience is stored in DB or some list) 
      Audience audience = AudiencesStore.FindAudience(audienceId); 

      //In case , if each audience has separate secretKey 
      //Right now we have a common secret key 
      if (audience != null) 
      { 
       var symmetricKey = TextEncodings.Base64Url.Decode(audience.EncryptedSecret);//any encrypted (or simple) key from 3rd party client 

       //***added refernce of System.IdenityModel to get SigningCredentials class refernce 
       // instead of using ThinkTecture nugget packaged dlls 
       var SigningCredentials = new SigningCredentials(new InMemorySymmetricSecurityKey(symmetricKey), signatureAlgorithm, digestAlgorithm); 

       var issued = data.Properties.IssuedUtc; 
       var expires = data.Properties.ExpiresUtc; 

       //Modified to keep issued and expirey time as NULL 
       var token = new JwtSecurityToken(_issuer, audienceId, data.Identity.Claims, null, null, SigningCredentials); 
       //var token = new JwtSecurityToken(_issuer, audienceId, data.Identity.Claims, issued.Value.UtcDateTime, expires.Value.UtcDateTime, SigningCredentials); 

       var handler = new JwtSecurityTokenHandler(); 

       var jwt = handler.WriteToken(token); 

      } 

      return string.Empty; 
     } 
     catch (Exception) 
     { 
      throw; 
     } 
    } 

    /// <summary> 
    /// UnProtect ticket : Validates JWT 
    /// </summary> 
    /// <param name="protectedText"></param> 
    /// <returns></returns> 
    public AuthenticationTicket Unprotect(string protectedText) 
    { 
     // start : Code for Validating JWT      

     //JwtSecurityTokenHandler 
     System.IdentityModel.Tokens.JwtSecurityTokenHandler tokenHandler = new System.IdentityModel.Tokens.JwtSecurityTokenHandler(); 
     System.Security.Claims.ClaimsPrincipal claimsPrincipal; 

     try 
     { 
      System.IdentityModel.Tokens.JwtSecurityToken tokenReceived = new System.IdentityModel.Tokens.JwtSecurityToken(protectedText); 

      //Configure Validation parameters// Now its Generalized//token must have issuer and audience 
      var issuer = tokenReceived.Issuer; 
      List<string> strAudience = (List<string>)tokenReceived.Audiences; 
      var audience = strAudience.Count > 0 ? strAudience[0].ToString(): string.Empty; 
      Audience audForContext = AudiencesStore.FindAudience(audience); 
      var symmetricKey = Microsoft.Owin.Security.DataHandler.Encoder.TextEncodings.Base64Url.Decode(audForContext.EncryptedSecret); 

      var validationParameters = new System.IdentityModel.Tokens.TokenValidationParameters() 
      { 
       ValidAudience = audience, 
       IssuerSigningKey = new System.IdentityModel.Tokens.InMemorySymmetricSecurityKey(symmetricKey), 
       ValidIssuer = issuer, 
       RequireExpirationTime = false 
      }; 

      System.IdentityModel.Tokens.SecurityToken validatedToken;     
      //if token gets validated claimsPrincipal has value otherwise it throws exception     
      claimsPrincipal = tokenHandler.ValidateToken(protectedText, validationParameters, out validatedToken); 

      var props = new AuthenticationProperties(new Dictionary<string, string> { { "audience", audience } }); 
      var ticket = new AuthenticationTicket((System.Security.Claims.ClaimsIdentity)claimsPrincipal.Identity, props); 
      return ticket; 
     } 
     catch (Exception) 
     { 

      throw; 
     } 

     ////End: Custom code to handle Validate Token 
    } 

} 
関連する問題