c# – 为什么我得到SecurityTokenSignatureKeyNotFoundException?

前端之家收集整理的这篇文章主要介绍了c# – 为什么我得到SecurityTokenSignatureKeyNotFoundException?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
当我尝试将此JWT(由Azure移动服务发布)作为HTTP标头/授权/承载令牌传递时:
  1. Header:
  2. {
  3. "alg": "HS256","typ": "JWT","kid": "0"
  4. }
  5. Claims:
  6. {
  7. "ver": 2,"aud": "Facebook","iss": "urn:microsoft:windows-azure:zumo","urn:microsoft:credentials": "pYK8b5...","exp": 1436730730,"uid": "Facebook:10000xxxxxxxxxx"
  8. }

进入我的ASP.NET WEB API配置:

  1. const string issuer = "urn:microsoft:windows-azure:zumo";
  2. byte[] mobileServicesSecret = TextEncodings.Base64Url.Decode(ConfigurationManager.AppSettings["as:SecretKey"]);
  3.  
  4. app.UseJwtBearerAuthentication(
  5. new JwtBearerAuthenticationOptions
  6. {
  7. AuthenticationMode = AuthenticationMode.Active,AllowedAudiences = new[] { "Facebook" },IssuerSecurityTokenProviders = new IIssuerSecurityTokenProvider[]
  8. {
  9. new SymmetricKeyIssuerSecurityTokenProvider(issuer,mobileServicesSecret)
  10. }
  11. });

我明白了:

A first chance exception of type
‘System.IdentityModel.Tokens.SecurityTokenSignatureKeyNotFoundException’
occurred in System.IdentityModel.Tokens.Jwt.dll

我怀疑这是因为“孩子”财产的存在?

编辑:使用这个https://github.com/Magenic/JWTvalidator/tree/master/JwtValidator/JwtValidator,可以验证JWT,所以它没有错.但我真的想用OWIN / Katana.

解决方法

Google建议如下 –
Calling the tokeninfo endpoint

Rather than writing your own code to perform these verification steps,we strongly recommend using a Google API client library for your platform,or calling our tokeninfo validation endpoint.

To validate an ID token using the tokeninfo endpoint,make an HTTPS POST or GET request to the endpoint,and pass your ID token in the id_token parameter. For example,to validate the token “XYZ123”,make the following GET request:

CustomJwtHandler.cs

  1. using System;
  2. using System.Collections.Generic;
  3. using System.IdentityModel.Tokens;
  4. using System.Linq;
  5. using System.Net.Http;
  6. using System.Web;
  7. using System.Web.Configuration;
  8. using Newtonsoft.Json;
  9. using System.Net;
  10. using System.Threading.Tasks;
  11. using System.Threading;
  12. using Services.Models;
  13. using System.Security.Claims;
  14.  
  15. namespace Services
  16. {
  17. /// <summary>
  18. /// This is an implementation of Google JWT verification that
  19. /// demonstrates:
  20. /// - JWT validation
  21. /// </summary>
  22. /// @author kunal.bajpai@gmail.com (Kunal Bajpai)
  23.  
  24.  
  25. public class CustomJwtHandler : DelegatingHandler
  26. {
  27. private const string URL_GOOGLE_TOKEN_INFO = "https://www.googleapis.com/oauth2/v3/tokeninfo";
  28.  
  29. /// <summary>
  30. ///
  31. /// </summary>
  32. /// <param name="request"></param>
  33. /// <param name="cancellationToken"></param>
  34. /// <returns></returns>
  35. protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,CancellationToken cancellationToken)
  36. {
  37. HttpStatusCode statusCode;
  38. string token;
  39.  
  40. var authHeader = request.Headers.Authorization;
  41. if (authHeader == null)
  42. {
  43. // Missing authorization header
  44. return base.SendAsync(request,cancellationToken);
  45. }
  46.  
  47. if (!TryRetrieveToken(request,out token))
  48. {
  49. return Task<HttpResponseMessage>.Factory.StartNew(() => new HttpResponseMessage(HttpStatusCode.Unauthorized));
  50. }
  51.  
  52. try
  53. {
  54. ValidateToken(token);
  55. return base.SendAsync(request,cancellationToken);
  56. }
  57. catch (SecurityTokenInvalidAudienceException)
  58. {
  59. statusCode = HttpStatusCode.Unauthorized;
  60. }
  61. catch (SecurityTokenValidationException)
  62. {
  63. statusCode = HttpStatusCode.Unauthorized;
  64. }
  65. catch (Exception)
  66. {
  67. statusCode = HttpStatusCode.InternalServerError;
  68. }
  69.  
  70. return Task<HttpResponseMessage>.Factory.StartNew(() => new HttpResponseMessage(statusCode));
  71. }
  72. /// <summary>
  73. /// Validates JWT Token
  74. /// </summary>
  75. /// <param name="JwtToken"></param>
  76. private void ValidateToken(string JwtToken)
  77. {
  78. try
  79. {
  80. using (WebClient wc = new WebClient())
  81. {
  82. TokenInfo tokenInfo = JsonConvert.DeserializeObject<TokenInfo>(wc.DownloadString(URL_GOOGLE_TOKEN_INFO + "?id_token=" + JwtToken));
  83.  
  84. ClaimsPrincipal claimsPrincipal = new ClaimsPrincipal(new ClaimsIdentity(ExtractClaims(tokenInfo),tokenInfo.Issuer));
  85.  
  86. Thread.CurrentPrincipal = claimsPrincipal;
  87. HttpContext.Current.User = claimsPrincipal;
  88. }
  89. }
  90. catch (WebException e)
  91. {
  92. HttpStatusCode statusCode = ((HttpWebResponse)e.Response).StatusCode;
  93. if (statusCode == HttpStatusCode.BadRequest)
  94. {
  95. throw new SecurityTokenValidationException();
  96. }
  97. else
  98. {
  99. throw new Exception();
  100. }
  101. }
  102. }
  103.  
  104. /// <summary>
  105. /// Tries to retrieve Token
  106. /// </summary>
  107. /// <param name="request"></param>
  108. /// <param name="token"></param>
  109. /// <returns></returns>
  110. private static bool TryRetrieveToken(HttpRequestMessage request,out string token)
  111. {
  112. token = null;
  113. IEnumerable<string> authorizationHeaders;
  114.  
  115. if (!request.Headers.TryGetValues("Authorization",out authorizationHeaders) ||
  116. authorizationHeaders.Count() > 1)
  117. {
  118. return false;
  119. }
  120.  
  121. var bearerToken = authorizationHeaders.ElementAt(0);
  122. token = bearerToken.StartsWith("Bearer ") ? bearerToken.Substring(7) : bearerToken;
  123. return true;
  124. }
  125.  
  126. private List<Claim> ExtractClaims(TokenInfo tokenInfo)
  127. {
  128. List<Claim> claims = new List<Claim> {
  129. 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)
  130. };
  131.  
  132. return claims;
  133. }
  134. }
  135. }

TokenInfo.cs

  1. using Microsoft.AspNet.Identity.EntityFramework;
  2. using Newtonsoft.Json;
  3.  
  4. namespace Services.Models
  5. {
  6. public class TokenInfo
  7. {
  8. [JsonProperty("iss")]
  9. public string Issuer { get; set; }
  10.  
  11. [JsonProperty("aud")]
  12. public string AudienceClientId { get; set; }
  13.  
  14. [JsonProperty("sub")]
  15. public string ProviderKey { get; set; }
  16.  
  17. [JsonProperty("email_verified")]
  18. public bool IsEmailVerifed { get; set; }
  19.  
  20. [JsonProperty("azp")]
  21. public string AndroidClientId { get; set; }
  22.  
  23. [JsonProperty("email")]
  24. public string Email { get; set; }
  25.  
  26. [JsonProperty("iat")]
  27. public long IssuedAt { get; set; }
  28.  
  29. [JsonProperty("exp")]
  30. public long ExpiresAt { get; set; }
  31.  
  32. [JsonProperty("name")]
  33. public string Name { get; set; }
  34.  
  35. [JsonProperty("picture")]
  36. public string Picture { get; set; }
  37.  
  38. [JsonProperty("given_name")]
  39. public string GivenName { get; set; }
  40.  
  41. [JsonProperty("family_name")]
  42. public string FamilyName { get; set; }
  43.  
  44. [JsonProperty("locale")]
  45. public string Locale { get; set; }
  46.  
  47. [JsonProperty("alg")]
  48. public string Algorithm { get; set; }
  49.  
  50. [JsonProperty("kid")]
  51. public string kid { get; set; }
  52.  
  53. public override bool Equals(object obj)
  54. {
  55. if (obj.GetType() != typeof(ApplicationUser))
  56. {
  57. return false;
  58. }
  59.  
  60. ApplicationUser user = (ApplicationUser)obj;
  61. bool hasLogin = false;
  62.  
  63. foreach (IdentityUserLogin login in user.Logins)
  64. {
  65. if (login.ProviderKey == ProviderKey)
  66. {
  67. hasLogin = true;
  68. break;
  69. }
  70. }
  71. if (!hasLogin) { return false; }
  72.  
  73. if (user.FirstName != GivenName) { return false; }
  74. if (user.LastName != FamilyName) { return false; }
  75. if (user.Locale != Locale) { return false; }
  76.  
  77. return base.Equals(obj);
  78. }
  79. }
  80. }

WebApiConfig.cs

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Net.Http;
  5. using System.Web.Http;
  6. using Microsoft.Owin.Security.OAuth;
  7. using Newtonsoft.Json.Serialization;
  8.  
  9. namespace Services
  10. {
  11. public static class WebApiConfig
  12. {
  13. public static void Register(HttpConfiguration config)
  14. {
  15. // Web API configuration and services
  16. // Configure Web API to use only bearer token authentication.
  17. config.SuppressDefaultHostAuthentication();
  18. config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
  19.  
  20. // Web API routes
  21. config.MapHttpAttributeRoutes();
  22.  
  23. config.Routes.MapHttpRoute(
  24. name: "DefaultApi",routeTemplate: "api/{controller}/{id}",defaults: new { id = RouteParameter.Optional }
  25. );
  26. config.MessageHandlers.Add(new CustomJwtHandler());
  27. }
  28. }
  29. }

猜你在找的C#相关文章