c# – 为什么我得到SecurityTokenSignatureKeyNotFoundException
当我尝试将此JWT(由Azure移动服务发布)作为HTTP标头/授权/承载令牌传递时:
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" } 进入我的ASP.NET WEB API配置: 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) } }); 我明白了:
我怀疑这是因为“孩子”财产的存在? 编辑:使用这个https://github.com/Magenic/JWTvalidator/tree/master/JwtValidator/JwtValidator,可以验证JWT,所以它没有错.但我真的想用OWIN / Katana. 解决方法
Google建议如下 –
Calling the tokeninfo endpoint
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 kunal.bajpai@gmail.com (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()); } } } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |