2015-06-13 23 views
7

Khi tôi cố gắng để vượt qua JWT này (do Azure Services Mobile) là một tiêu đề HTTP/Authorization/Bearer mã thông báo:Tại sao tôi nhận được SecurityTokenSignatureKeyNotFoundException?

Header: 
{ 
    "alg": "HS256", 
    "typ": "JWT", 
    "kid": "0" 
} 
Claims: 
{ 
    "ver": 2, 
    "aud": "Facebook", 
    "iss": "urn:microsoft:windows-azure:zumo", 
    "urn:microsoft:credentials": "pYK8b5...", 
    "exp": 1436730730, 
    "uid": "Facebook:10000xxxxxxxxxx" 
} 

Into WEB API ASP.NET của tôi cấu hình:

const string issuer = "urn:microsoft:windows-azure:zumo"; 
byte[] mobileServicesSecret = TextEncodings.Base64Url.Decode(ConfigurationManager.AppSettings["as:SecretKey"]); 

app.UseJwtBearerAuthentication(
    new JwtBearerAuthenticationOptions 
    { 
     AuthenticationMode = AuthenticationMode.Active, 
     AllowedAudiences = new[] { "Facebook" }, 
     IssuerSecurityTokenProviders = new IIssuerSecurityTokenProvider[] 
       { 
        new SymmetricKeyIssuerSecurityTokenProvider(issuer, mobileServicesSecret) 
       } 
    }); 

tôi nhận được:

Một ngoại lệ cơ hội đầu tiên của loại 'System.IdentityModel.Tokens.SecurityTokenSignatureKeyNotFoundException' xảy ra ở Syst em.IdentityModel.Tokens.Jwt.dll

Tôi nghi ngờ điều này là do sự hiện diện của tài sản "đứa trẻ"?

CHỈNH SỬA: Sử dụng https://github.com/Magenic/JWTvalidator/tree/master/JwtValidator/JwtValidator này, bạn có thể xác thực JWT, vì vậy không có gì sai với nó. Nhưng tôi thực sự muốn sử dụng OWIN/Katana.

+0

Bạn có khắc phục được sự cố không? Tôi bị mắc kẹt với điều này. Bạn có thể cung cấp mã. –

+0

@KunalB. không, xin lỗi tôi chưa bao giờ tìm thấy một giải pháp để sử dụng Owin/Katana. Tôi đã phải sử dụng lớp JwtValidator trong liên kết và sử dụng một thuộc tính xác thực tùy chỉnh để xác nhận hợp lệ nó. Microsoft làm những gì họ làm tốt nhất; một nhóm (nhóm dịch vụ di động Azure) nằm ở một bên của hàng rào, nhóm còn lại (nhóm ASP.NET) ngồi ở phía bên kia, và họ có thể chưa bao giờ nói chuyện với nhau ... :( –

+0

Sau 2 ngày, đây là những gì Tôi tìm thấy - http://markwalsh.io/development/2014/12/02/ASP.Net%20Web%20API%20with%20JWT/ điều này làm việc cho tôi.Trong khi gỡ lỗi tôi vẫn nhận được một số tin nhắn lạ. –

Trả lời

0

Google gợi ý như sau - Calling the tokeninfo endpoint

Thay vì viết mã riêng của bạn để thực hiện các bước xác minh, chúng tôi khuyên bạn sử dụng một thư viện ứng dụng khách Google API cho nền tảng của bạn, hoặc gọi endpoint xác nhận tokeninfo của chúng tôi .

Để xác thực mã thông báo ID sử dụng điểm cuối tokeninfo, hãy gửi một yêu cầu HTTPS POST hoặc GET tới điểm cuối và chuyển mã thông báo ID của bạn trong thông số id_token. Ví dụ, để xác nhận các dấu hiệu "xyz123", thực hiện yêu cầu GET sau:

CustomJwtHandler.cs

using System; 
using System.Collections.Generic; 
using System.IdentityModel.Tokens; 
using System.Linq; 
using System.Net.Http; 
using System.Web; 
using System.Web.Configuration; 
using Newtonsoft.Json; 
using System.Net; 
using System.Threading.Tasks; 
using System.Threading; 
using Services.Models; 
using System.Security.Claims; 

namespace Services 
{ 
    /// <summary> 
    /// This is an implementation of Google JWT verification that 
    /// demonstrates: 
    /// - JWT validation 
    /// </summary> 
    /// @author [email protected] (Kunal Bajpai) 


    public class CustomJwtHandler : DelegatingHandler 
    { 
     private const string URL_GOOGLE_TOKEN_INFO = "https://www.googleapis.com/oauth2/v3/tokeninfo"; 

     /// <summary> 
     /// 
     /// </summary> 
     /// <param name="request"></param> 
     /// <param name="cancellationToken"></param> 
     /// <returns></returns> 
     protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 
     { 
      HttpStatusCode statusCode; 
      string token; 

      var authHeader = request.Headers.Authorization; 
      if (authHeader == null) 
      { 
       // Missing authorization header 
       return base.SendAsync(request, cancellationToken); 
      } 

      if (!TryRetrieveToken(request, out token)) 
      { 
       return Task<HttpResponseMessage>.Factory.StartNew(() => new HttpResponseMessage(HttpStatusCode.Unauthorized)); 
      } 

      try 
      { 
       ValidateToken(token); 
       return base.SendAsync(request, cancellationToken); 
      } 
      catch (SecurityTokenInvalidAudienceException) 
      { 
       statusCode = HttpStatusCode.Unauthorized; 
      } 
      catch (SecurityTokenValidationException) 
      { 
       statusCode = HttpStatusCode.Unauthorized; 
      } 
      catch (Exception) 
      { 
       statusCode = HttpStatusCode.InternalServerError; 
      } 

      return Task<HttpResponseMessage>.Factory.StartNew(() => new HttpResponseMessage(statusCode)); 
     } 
     /// <summary> 
     /// Validates JWT Token 
     /// </summary> 
     /// <param name="JwtToken"></param> 
     private void ValidateToken(string JwtToken) 
     { 
      try 
      { 
       using (WebClient wc = new WebClient()) 
       { 
        TokenInfo tokenInfo = JsonConvert.DeserializeObject<TokenInfo>(wc.DownloadString(URL_GOOGLE_TOKEN_INFO + "?id_token=" + JwtToken)); 

        ClaimsPrincipal claimsPrincipal = new ClaimsPrincipal(new ClaimsIdentity(ExtractClaims(tokenInfo), tokenInfo.Issuer)); 

        Thread.CurrentPrincipal = claimsPrincipal; 
        HttpContext.Current.User = claimsPrincipal; 
       } 
      } 
      catch (WebException e) 
      { 
       HttpStatusCode statusCode = ((HttpWebResponse)e.Response).StatusCode; 
       if (statusCode == HttpStatusCode.BadRequest) 
       { 
        throw new SecurityTokenValidationException(); 
       } 
       else 
       { 
        throw new Exception(); 
       } 
      } 
     } 

     /// <summary> 
     /// Tries to retrieve Token 
     /// </summary> 
     /// <param name="request"></param> 
     /// <param name="token"></param> 
     /// <returns></returns> 
     private static bool TryRetrieveToken(HttpRequestMessage request, out string token) 
     { 
      token = null; 
      IEnumerable<string> authorizationHeaders; 

      if (!request.Headers.TryGetValues("Authorization", out authorizationHeaders) || 
      authorizationHeaders.Count() > 1) 
      { 
       return false; 
      } 

      var bearerToken = authorizationHeaders.ElementAt(0); 
      token = bearerToken.StartsWith("Bearer ") ? bearerToken.Substring(7) : bearerToken; 
      return true; 
     } 

     private List<Claim> ExtractClaims(TokenInfo tokenInfo) 
     { 
      List<Claim> claims = new List<Claim> { 
       new Claim(ClaimTypes.Name, tokenInfo.Name), 
       new Claim(ClaimTypes.Email, tokenInfo.Email), 
       new Claim(ClaimTypes.GivenName, tokenInfo.GivenName), 
       new Claim(ClaimTypes.Surname, tokenInfo.FamilyName), 
       new Claim(ApplicationUser.CLAIM_TYPE_LOCALE, tokenInfo.Locale), 
       new Claim(ClaimTypes.NameIdentifier, tokenInfo.ProviderKey, ClaimValueTypes.String, tokenInfo.Issuer), 
       new Claim(ApplicationUser.CLAIM_TYPE_EMAIL_CONFIRMED, tokenInfo.IsEmailVerifed.ToString(), ClaimValueTypes.Boolean) 
      }; 

      return claims; 
     } 
    } 
} 

TokenInfo.cs

using Microsoft.AspNet.Identity.EntityFramework; 
using Newtonsoft.Json; 

namespace Services.Models 
{ 
    public class TokenInfo 
    { 
     [JsonProperty("iss")] 
     public string Issuer { get; set; } 

     [JsonProperty("aud")] 
     public string AudienceClientId { get; set; } 

     [JsonProperty("sub")] 
     public string ProviderKey { get; set; } 

     [JsonProperty("email_verified")] 
     public bool IsEmailVerifed { get; set; } 

     [JsonProperty("azp")] 
     public string AndroidClientId { get; set; } 

     [JsonProperty("email")] 
     public string Email { get; set; } 

     [JsonProperty("iat")] 
     public long IssuedAt { get; set; } 

     [JsonProperty("exp")] 
     public long ExpiresAt { get; set; } 

     [JsonProperty("name")] 
     public string Name { get; set; } 

     [JsonProperty("picture")] 
     public string Picture { get; set; } 

     [JsonProperty("given_name")] 
     public string GivenName { get; set; } 

     [JsonProperty("family_name")] 
     public string FamilyName { get; set; } 

     [JsonProperty("locale")] 
     public string Locale { get; set; } 

     [JsonProperty("alg")] 
     public string Algorithm { get; set; } 

     [JsonProperty("kid")] 
     public string kid { get; set; } 

     public override bool Equals(object obj) 
     { 
      if (obj.GetType() != typeof(ApplicationUser)) 
      { 
       return false; 
      } 

      ApplicationUser user = (ApplicationUser)obj; 
      bool hasLogin = false; 

      foreach (IdentityUserLogin login in user.Logins) 
      { 
       if (login.ProviderKey == ProviderKey) 
       { 
        hasLogin = true; 
        break; 
       } 
      } 
      if (!hasLogin) { return false; } 

      if (user.FirstName != GivenName) { return false; } 
      if (user.LastName != FamilyName) { return false; } 
      if (user.Locale != Locale) { return false; } 

      return base.Equals(obj); 
     } 
    } 
} 

WebApiConfig. cs

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Net.Http; 
using System.Web.Http; 
using Microsoft.Owin.Security.OAuth; 
using Newtonsoft.Json.Serialization; 

namespace Services 
{ 
    public static class WebApiConfig 
    { 
     public static void Register(HttpConfiguration config) 
     { 
      // Web API configuration and services 
      // Configure Web API to use only bearer token authentication. 
      config.SuppressDefaultHostAuthentication(); 
      config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType)); 

      // Web API routes 
      config.MapHttpAttributeRoutes(); 

      config.Routes.MapHttpRoute(
       name: "DefaultApi", 
       routeTemplate: "api/{controller}/{id}", 
       defaults: new { id = RouteParameter.Optional } 
      ); 
      config.MessageHandlers.Add(new CustomJwtHandler()); 
     } 
    } 
} 
+0

Bạn nghĩ gì nếu chúng tôi gọi cho Dịch vụ của Google như vậy thường xuyên để xác thực mã thông báo? – Redplane

+0

Không có gì xảy ra. Bạn có thể sẽ hết hạn mức. –

+0

Đó là lý do tại sao tôi đang suy nghĩ về việc xác minh Mã thông báo Google trên máy chủ mà tôi triển khai – Redplane

Các vấn đề liên quan