/// <summary> /// Finds a named collection of <see cref="SecurityKey"/>(s) that match the <see cref="SecurityKeyIdentifierClause"/> and returns a <see cref="NamedKeySecurityToken"/> that contains the <see cref="SecurityKey"/>(s). /// </summary> /// <param name="keyIdentifierClause">The <see cref="SecurityKeyIdentifier"/> to resolve to a <see cref="SecurityToken"/></param> /// <param name="token">The resolved <see cref="SecurityToken"/>.</param> /// <remarks>If there is no match, then <see cref="IssuerTokenResolver"/> and 'base' are called in order.</remarks> /// <returns>true if token was resolved.</returns> /// <exception cref="ArgumentNullException">if 'keyIdentifierClause' is null.</exception> protected override bool TryResolveTokenCore(SecurityKeyIdentifierClause keyIdentifierClause, out SecurityToken token) { if (keyIdentifierClause == null) { throw new ArgumentNullException("keyIdentifierClause"); } token = null; NamedKeySecurityKeyIdentifierClause namedKeyIdentifierClause = keyIdentifierClause as NamedKeySecurityKeyIdentifierClause; if (namedKeyIdentifierClause != null) { IList <SecurityKey> resolvedKeys = null; if (this.keys.TryGetValue(namedKeyIdentifierClause.Name, out resolvedKeys)) { token = new NamedKeySecurityToken(namedKeyIdentifierClause.Name, namedKeyIdentifierClause.Id, resolvedKeys); return(true); } } if (IssuerTokenResolver != null && IssuerTokenResolver.TryResolveToken(keyIdentifierClause, out token)) { return(true); } return(base.TryResolveTokenCore(keyIdentifierClause, out token)); }
public override ClaimsPrincipal ValidateToken(JWTSecurityToken jwt, TokenValidationParameters validationParameters) { Check.IsNotNull(jwt, "jwt"); Check.IsNotNull(validationParameters, "validationParameters"); diagnostics.WriteInformationTrace(TraceEventId.InboundParameters, "JWT token details from ACS: {0}, {1}, {2}, {3}", jwt.Issuer, jwt.ValidFrom, jwt.ValidTo, jwt.RawData); string audienceUrl; if (this.Configuration != null) { audienceUrl = this.Configuration.AudienceRestriction.AllowedAudienceUris[0].ToString(); } else { audienceUrl = validationParameters.AllowedAudience; } // set up valid issuers if ((validationParameters.ValidIssuer == null) && (validationParameters.ValidIssuers == null || !validationParameters.ValidIssuers.Any())) { List<string> issuers = new List<string>(); issuers.AddRange(ConfigurationManager.AppSettings["Issuers"].Split(new[] { ',' })); validationParameters.ValidIssuers = issuers; } // setup signing token. if (validationParameters.SigningToken == null) { var resolver = (NamedKeyIssuerTokenResolver)this.Configuration.IssuerTokenResolver; if (resolver.SecurityKeys != null) { List<SecurityKey> skeys; if (resolver.SecurityKeys.TryGetValue(audienceUrl, out skeys)) { var tok = new NamedKeySecurityToken(audienceUrl, skeys); validationParameters.SigningToken = tok; } } } diagnostics.WriteInformationTrace(TraceEventId.Flow, "Successfully validated JWT token from ACS"); return base.ValidateToken(jwt, validationParameters); }
/// <summary> /// Finds a named collection of <see cref="SecurityKey"/>(s) that match the <see cref="SecurityKeyIdentifierClause"/> and returns a <see cref="NamedKeySecurityToken"/> that contains the <see cref="SecurityKey"/>(s). /// </summary> /// <param name="keyIdentifierClause">The <see cref="SecurityKeyIdentifier"/> to resolve to a <see cref="SecurityToken"/></param> /// <param name="token">The resolved <see cref="SecurityToken"/>.</param> /// <remarks>If there is no match, then <see cref="IssuerTokenResolver"/> and 'base' are called in order.</remarks> /// <returns>true if token was resolved.</returns> /// <exception cref="ArgumentNullException">if 'keyIdentifierClause' is null.</exception> protected override bool TryResolveTokenCore(SecurityKeyIdentifierClause keyIdentifierClause, out SecurityToken token) { if (keyIdentifierClause == null) throw new ArgumentNullException("keyIdentifierClause"); token = null; NamedKeySecurityKeyIdentifierClause namedKeyIdentifierClause = keyIdentifierClause as NamedKeySecurityKeyIdentifierClause; if (namedKeyIdentifierClause != null) { IList<SecurityKey> resolvedKeys = null; if (this.keys.TryGetValue(namedKeyIdentifierClause.Name, out resolvedKeys)) { token = new NamedKeySecurityToken(namedKeyIdentifierClause.Name, namedKeyIdentifierClause.Id, resolvedKeys); return true; } } if (IssuerTokenResolver != null && IssuerTokenResolver.TryResolveToken(keyIdentifierClause, out token)) { return true; } return base.TryResolveTokenCore(keyIdentifierClause, out token); }
public void NamedKeySecurityKeyIdentifierClause_Extensibility() { string clauseName = "kid"; string keyId = Issuers.GotJwt; NamedKeySecurityKeyIdentifierClause clause = new NamedKeySecurityKeyIdentifierClause(clauseName, keyId); SecurityKeyIdentifier keyIdentifier = new SecurityKeyIdentifier(clause); SigningCredentials signingCredentials = new SigningCredentials(KeyingMaterial.DefaultSymmetricSecurityKey_256, SecurityAlgorithms.HmacSha256Signature, SecurityAlgorithms.Sha256Digest, keyIdentifier); JwtHeader jwtHeader = new JwtHeader(signingCredentials); SecurityKeyIdentifier ski = jwtHeader.SigningKeyIdentifier; Assert.AreEqual(ski.Count, 1, "ski.Count != 1 "); NamedKeySecurityKeyIdentifierClause clauseOut = ski.Find<NamedKeySecurityKeyIdentifierClause>(); Assert.IsNotNull(clauseOut, "NamedKeySecurityKeyIdentifierClause not found"); Assert.AreEqual(clauseOut.Name, clauseName, "clauseOut.Id != clauseId"); Assert.AreEqual(clauseOut.Id, keyId, "clauseOut.KeyIdentifier != keyId"); NamedKeySecurityToken NamedKeySecurityToken = new NamedKeySecurityToken(clauseName, keyId, new SecurityKey[] { KeyingMaterial.DefaultSymmetricSecurityKey_256 }); Assert.IsTrue(NamedKeySecurityToken.MatchesKeyIdentifierClause(clause), "NamedKeySecurityToken.MatchesKeyIdentifierClause( clause ), failed"); List<SecurityKey> list = new List<SecurityKey>() { KeyingMaterial.DefaultSymmetricSecurityKey_256 }; Dictionary<string, IList<SecurityKey>> keys = new Dictionary<string, IList<SecurityKey>>() { { "kid", list }, }; NamedKeyIssuerTokenResolver nkitr = new NamedKeyIssuerTokenResolver(keys: keys); SecurityKey sk = nkitr.ResolveSecurityKey(clause); Assert.IsNotNull(sk, "NamedKeySecurityToken.MatchesKeyIdentifierClause( clause ), failed"); }
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { Check.IsNotNull(request, "request"); HttpStatusCode statusCode; string token; if (request.RequestUri.AbsolutePath.Contains("/authenticate")) { return base.SendAsync(request, cancellationToken); } if (request.RequestUri.AbsolutePath.Contains("/signout")) { return base.SendAsync(request, cancellationToken); } if (request.RequestUri.AbsolutePath.Contains("/SignOutCallback")) { return base.SendAsync(request, cancellationToken); } if (request.RequestUri.AbsolutePath.Contains("/windowsLiveAuthorization")) { return base.SendAsync(request, cancellationToken); } if (request.RequestUri.AbsolutePath.Contains("api/GetSupportedIdentityProviders")) { return base.SendAsync(request, cancellationToken); } if (request.RequestUri.AbsolutePath.Contains("api/SignInCallBack")) { return base.SendAsync(request, cancellationToken); } if (!TryRetrieveToken(request, out token)) { statusCode = HttpStatusCode.Unauthorized; return Task<HttpResponseMessage>.Factory.StartNew(() => new HttpResponseMessage(statusCode)); } try { diagnostics.WriteInformationTrace(TraceEventId.Flow, "Validating bearer token: {0}", token); string issuersValue = ConfigurationManager.AppSettings["Issuers"]; string signingSymmetricKey = ConfigurationManager.AppSettings["SigningSymmetricKey"]; string allowedAudience = ConfigurationManager.AppSettings["AllowedAudience"]; // Use JWTSecurityTokenHandler to validate the JWT token ApiJWTSecurityTokenHandler tokenHandler = new ApiJWTSecurityTokenHandler(); List<string> issuers = new List<string>(); issuers.AddRange(issuersValue.Split(new[] { ',' })); InMemorySymmetricSecurityKey securityKey = new InMemorySymmetricSecurityKey(Convert.FromBase64String(signingSymmetricKey)); NamedKeySecurityToken namedToken = new NamedKeySecurityToken(allowedAudience, new List<SecurityKey>() { securityKey }); // Set the expected properties of the JWT token in the TokenValidationParameters TokenValidationParameters validationParameters = new TokenValidationParameters() { AllowedAudience = allowedAudience, ValidIssuers = issuers, SigningToken = namedToken }; ClaimsPrincipal claimsPrincipal = tokenHandler.ValidateToken(token, validationParameters); ClaimsIdentity claimsIdentity = (ClaimsIdentity)claimsPrincipal.Identity; try { IUserService userService = (IUserService)GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof(IUserService)); User user = IdentityHelper.GetCurrentUser(userService, claimsPrincipal); foreach (var role in user.UserRoles) { if (!claimsIdentity.HasClaim(ClaimTypes.Role, role.Role.Name)) { claimsIdentity.AddClaim(new Claim(ClaimTypes.Role, role.Role.Name)); } } } catch (UserNotFoundException) { // No need to do anything here because GetUsersByNameIdentifier action in UsersController will take care of sending appropriate http response. } Thread.CurrentPrincipal = claimsPrincipal; if (HttpContext.Current != null) { HttpContext.Current.User = claimsPrincipal; } diagnostics.WriteInformationTrace(TraceEventId.Flow, "Authorization token validated successfully"); return base.SendAsync(request, cancellationToken); } catch (SecurityTokenValidationException secutiryTokenValidationException) { FederatedAuthentication.WSFederationAuthenticationModule.SignOut(true); HttpResponseMessage response = request.CreateErrorResponse(HttpStatusCode.Unauthorized, secutiryTokenValidationException); return Task<HttpResponseMessage>.Factory.StartNew(() => response); } }