/// <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)); }
/// <summary> /// Gets the first<see cref="SecurityKey"/> that matches a <see cref="SecurityKeyIdentifierClause"/> /// </summary> /// <param name="keyIdentifierClause">the <see cref="SecurityKeyIdentifierClause"/> to match.</param> /// <returns>The first <see cref="SecurityKey"/> that matches the <see cref="SecurityKeyIdentifierClause"/>. /// <para>null if there is no match.</para></returns> /// <para>Only <see cref="NamedKeySecurityKeyIdentifierClause"/> are matched.</para> /// <exception cref="ArgumentNullException">'keyIdentifierClause' is null.</exception> public override SecurityKey ResolveKeyIdentifierClause(SecurityKeyIdentifierClause keyIdentifierClause) { if (keyIdentifierClause == null) { throw new ArgumentNullException("keyIdentifierClause"); } // if name matches, return first non null NamedKeySecurityKeyIdentifierClause namedKeyIdentifierClause = keyIdentifierClause as NamedKeySecurityKeyIdentifierClause; if (namedKeyIdentifierClause != null) { if (string.Equals(namedKeyIdentifierClause.Name, this.name, StringComparison.Ordinal)) { foreach (SecurityKey securityKey in this.securityKeys) { if (securityKey == null) { continue; } return(securityKey); } } } return(null); }
protected override void ValidateTestCase( string testVariation ) { IdentityConfiguration identityConfig = new IdentityConfiguration( IdentityConfiguration.DefaultServiceName ); Assert.IsNotNull( identityConfig.IssuerTokenResolver ); Assert.IsFalse( identityConfig.IssuerTokenResolver.GetType() != typeof( NamedKeyIssuerTokenResolver ) , string.Format( "Expected identityConfiguration.IsuerTokenResolver.GetType() == typeof( NamedKeyIssuerTokenResolver ), was: '{0}'", identityConfig.IssuerTokenResolver.GetType() ) ); NamedKeyIssuerTokenResolver resolver = identityConfig.IssuerTokenResolver as NamedKeyIssuerTokenResolver; Assert.IsTrue( resolver.SecurityKeys.Count == 0 ); Assert.IsTrue( IssuerTokenResolver.DefaultStoreName == StoreName.TrustedPeople ); Assert.IsTrue( IssuerTokenResolver.DefaultStoreLocation == StoreLocation.LocalMachine ); // Should not find key SecurityKey key = null; NamedKeySecurityKeyIdentifierClause clause = new NamedKeySecurityKeyIdentifierClause( "keyName", "KeyingMaterial.SymmetricKeyBytes_256" ); Assert.IsFalse( resolver.TryResolveSecurityKey( clause, out key ) ); Assert.IsNull( key ); // Should not find token SecurityToken token = null; Assert.IsFalse( resolver.TryResolveToken( clause, out token ) ); Assert.IsNull( token ); }
public void NamedKeySecurityKeyIdentifierClause_Constructor() { NamedKeySecurityKeyIdentifierClause namedKeySecurityKeyIdentifierClause; ExpectedException expectedException = new ExpectedException(typeExpected: typeof(ArgumentNullException), substringExpected: "name"); try { namedKeySecurityKeyIdentifierClause = new NamedKeySecurityKeyIdentifierClause(null, null); expectedException.ProcessNoException(); } catch(Exception exception) { expectedException.ProcessException(exception); } expectedException = new ExpectedException(typeExpected: typeof(ArgumentNullException), substringExpected: "id"); try { namedKeySecurityKeyIdentifierClause = new NamedKeySecurityKeyIdentifierClause("name", null); expectedException.ProcessNoException(); } catch (Exception exception) { expectedException.ProcessException(exception); } expectedException = ExpectedException.ArgumentNullException(substringExpected: "name"); try { namedKeySecurityKeyIdentifierClause = new NamedKeySecurityKeyIdentifierClause(name: " ", id: "id"); expectedException.ProcessNoException(); } catch (Exception exception) { expectedException.ProcessException(exception); } expectedException = ExpectedException.ArgumentNullException(substringExpected: "id"); try { namedKeySecurityKeyIdentifierClause = new NamedKeySecurityKeyIdentifierClause("name", " "); expectedException.ProcessNoException(); } catch (Exception exception) { expectedException.ProcessException(exception); } }
/// <summary> /// Answers if the <see cref="SecurityKeyIdentifierClause"/> is a match. /// </summary> /// <param name="keyIdentifierClause">The <see cref="SecurityKeyIdentifierClause"/></param> /// <returns>true if matched.</returns> /// <remarks><para>A successful match occurs when <see cref="NamedKeySecurityKeyIdentifierClause.Name"/> == <see cref="Id"/>.</para> /// <para>Only <see cref="NamedKeySecurityKeyIdentifierClause"/> are matched.</para></remarks> /// <exception cref="ArgumentNullException">'keyIdentifierClause' is null.</exception> public override bool MatchesKeyIdentifierClause(SecurityKeyIdentifierClause keyIdentifierClause) { if (keyIdentifierClause == null) { throw new ArgumentNullException("keyIdentifierClause"); } NamedKeySecurityKeyIdentifierClause namedKeyIdentifierClause = keyIdentifierClause as NamedKeySecurityKeyIdentifierClause; if (namedKeyIdentifierClause != null) { if (string.Equals(namedKeyIdentifierClause.Name, this.name, StringComparison.Ordinal)) { return(true); } } return(false); }
/// <summary> /// Initializes a new instance of the <see cref="JwtHeader"/> class. With the Header Parameters as follows: /// <para>{ { typ, JWT }, { alg, Mapped( <see cref="System.IdentityModel.Tokens.SigningCredentials.SignatureAlgorithm"/> } } /// See: Algorithm Mapping below.</para> /// </summary> /// <param name="signingCredentials">The <see cref="SigningCredentials"/> that will be or were used to sign the <see cref="JwtSecurityToken"/>.</param> /// <remarks> /// <para>For each <see cref="SecurityKeyIdentifierClause"/> in signingCredentials.SigningKeyIdentifier</para> /// <para>if the clause is a <see cref="NamedKeySecurityKeyIdentifierClause"/> Header Parameter { clause.Name, clause.KeyIdentifier } will be added.</para> /// <para>For example, if clause.Name == 'kid' and clause.KeyIdentifier == 'SecretKey99'. The JSON object { kid, SecretKey99 } would be added.</para> /// <para>In addition, if the <see cref="SigningCredentials"/> is a <see cref="X509SigningCredentials"/> the JSON object { x5t, Base64UrlEncoded( <see cref="X509Certificate.GetCertHashString()"/> } will be added.</para> /// <para>This simplifies the common case where a X509Certificate is used.</para> /// <para>================= </para> /// <para>Algorithm Mapping</para> /// <para>================= </para> /// <para><see cref="System.IdentityModel.Tokens.SigningCredentials.SignatureAlgorithm"/> describes the algorithm that is discoverable by the CLR runtime.</para> /// <para>The { alg, 'value' } placed in the header reflects the JWT specification.</para> /// <see cref="JwtSecurityTokenHandler.OutboundAlgorithmMap"/> contains a signature mapping where the 'value' above will be translated according to this mapping. /// <para>Current mapping is:</para> /// <para>    'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256' => 'RS256'</para> /// <para>    'http://www.w3.org/2001/04/xmldsig-more#hmac-sha256' => 'HS256'</para> /// </remarks> public JwtHeader(SigningCredentials signingCredentials = null) : base(StringComparer.Ordinal) { this.Add(JwtConstants.ReservedHeaderParameters.Type, JwtConstants.HeaderType); if (signingCredentials != null) { this.signingCredentials = signingCredentials; string algorithm = signingCredentials.SignatureAlgorithm; if (JwtSecurityTokenHandler.OutboundAlgorithmMap.ContainsKey(signingCredentials.SignatureAlgorithm)) { algorithm = JwtSecurityTokenHandler.OutboundAlgorithmMap[algorithm]; } this.Add(JwtConstants.ReservedHeaderParameters.Algorithm, algorithm); if (signingCredentials.SigningKeyIdentifier != null) { foreach (SecurityKeyIdentifierClause clause in signingCredentials.SigningKeyIdentifier) { NamedKeySecurityKeyIdentifierClause namedKeyClause = clause as NamedKeySecurityKeyIdentifierClause; if (namedKeyClause != null) { this.Add(namedKeyClause.Name, namedKeyClause.KeyIdentifier); } } } X509SigningCredentials x509SigningCredentials = signingCredentials as X509SigningCredentials; if (x509SigningCredentials != null && x509SigningCredentials.Certificate != null) { this.Add(JwtConstants.ReservedHeaderParameters.X509CertificateThumbprint, Base64UrlEncoder.Encode(x509SigningCredentials.Certificate.GetCertHash())); } } else { this.Add(JwtConstants.ReservedHeaderParameters.Algorithm, JwtConstants.Algorithms.NONE); } }
public override ReadOnlyCollection<ClaimsIdentity> ValidateToken(SecurityToken token) { SimpleWebToken swt = token as SimpleWebToken; if (swt == null) { throw new SecurityTokenValidationException("The received token is of incorrect token type.Expected SimpleWebToken"); } // check issuer name registry for allowed issuers string issuerName = swt.Issuer; // check expiration if (DateTime.Compare(swt.ValidTo, DateTime.UtcNow) <= 0) { throw new SecurityTokenExpiredException("The incoming token has expired. Get a new access token from the Authorization Server."); } // check audience if (base.Configuration.AudienceRestriction.AudienceMode != AudienceUriMode.Never) { var allowedAudiences = base.Configuration.AudienceRestriction.AllowedAudienceUris; if (!allowedAudiences.Any(uri => uri == swt.AudienceUri)) { throw new AudienceUriValidationFailedException(); } } // retrieve signing key var clause = new NamedKeySecurityKeyIdentifierClause(swt.Issuer, swt.Issuer); var securityKey = Configuration.IssuerTokenResolver.ResolveSecurityKey(clause) as InMemorySymmetricSecurityKey; if (securityKey == null) { throw new SecurityTokenValidationException("No signing key found"); } // check signature if (!swt.VerifySignature(securityKey.GetSymmetricKey())) { throw new SecurityTokenValidationException("Signature verification of the incoming token failed."); } var id = new ClaimsIdentity("SWT"); foreach (var claim in swt.Claims) { var value = claim.Value; value.Split(',').ToList().ForEach(v => id.AddClaim(new Claim(claim.Type, HttpUtility.UrlDecode(v), ClaimValueTypes.String, issuerName))); } return new ReadOnlyCollection<ClaimsIdentity>(new ClaimsIdentity[] { id }); }
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"); }
public void NamedKeySecurityKeyIdentifierClause_Publics() { // new NameKeyParametersVariation //{ // TestCase = "MatchesName", // TestAction = // () => (new NamedKeySecurityKeyIdentifierClause("bob", null)).Matches(null) //}, NamedKeySecurityKeyIdentifierClause namedKeySecurityKeyIdentifierClause = new NamedKeySecurityKeyIdentifierClause("name", "keyidentifier"); Assert.IsTrue("name" == namedKeySecurityKeyIdentifierClause.Name); Assert.IsTrue("keyidentifier" == namedKeySecurityKeyIdentifierClause.Id); // *** Matches (null) ExpectedException expectedException = new ExpectedException(typeExpected: typeof(ArgumentNullException), substringExpected: "keyIdentifierClause"); try { namedKeySecurityKeyIdentifierClause.Matches(null); expectedException.ProcessNoException(); } catch (Exception exception) { expectedException.ProcessException(exception); } }
public void NamedKeySecurityKeyIdentifierClause_Defaults() { NamedKeySecurityKeyIdentifierClause namedKeySecurityKeyIdentifierClause = new NamedKeySecurityKeyIdentifierClause("name", "keyidentifier"); Assert.IsTrue("NamedKeySecurityKeyIdentifierClause" == namedKeySecurityKeyIdentifierClause.ClauseType); }