public void Encode_Decode(string enc, byte[] alg) { var writer = new JwtWriter(); var descriptor = new JweDescriptor(_bobKey, (KeyManagementAlgorithm)alg, (EncryptionAlgorithm)enc) { Payload = new JwsDescriptor(_signingKey, SignatureAlgorithm.HS256) { Payload = new JwtPayload { { "sub", "Alice" } } } }; var token = writer.WriteToken(descriptor); var policy = new TokenValidationPolicyBuilder() .RequireSignatureByDefault(_signingKey) .WithDecryptionKey(_bobKey) .Build(); var result = Jwt.TryParse(token, policy, out var jwt); Assert.True(result); Assert.True(jwt.Payload.TryGetClaim("sub", out var sub)); Assert.Equal("Alice", sub.GetString()); jwt.Dispose(); }
public void BuilderFails() { var builder = new TokenValidationPolicyBuilder(); Assert.Throws <ArgumentNullException>(() => builder.AddValidator(null)); Assert.Throws <ArgumentOutOfRangeException>(() => builder.MaximumTokenSizeInBytes(-1)); Assert.Throws <InvalidOperationException>(() => builder.RequireMetadataConfiguration("jwks_uri", SignatureAlgorithm.HS256)); Assert.Throws <ArgumentNullException>(() => builder.RequireSignature("issuer", (Jwk)null, SignatureAlgorithm.HS256)); Assert.Throws <InvalidOperationException>(() => builder.RequireSignature("issuer", SymmetricJwk.GenerateKey(128), (SignatureAlgorithm)null)); Assert.Throws <ArgumentNullException>(() => builder.RequireSignature("issuer", (Jwks)null, SignatureAlgorithm.HS256)); Assert.Throws <ArgumentException>(() => builder.RequireSignature("issuer", new StaticKeyProvider(new Jwks(SymmetricJwk.GenerateKey(128))), SignatureAlgorithm.None)); Assert.Throws <ArgumentNullException>(() => builder.RequireSignature("issuer", new StaticKeyProvider(new Jwks(SymmetricJwk.GenerateKey(128))), (SignatureAlgorithm)null)); Assert.Throws <ArgumentNullException>(() => builder.RequireSignature("issuer", (StaticKeyProvider)null, SignatureAlgorithm.HS256)); Assert.Throws <ArgumentNullException>(() => builder.RequireSignature(null, new StaticKeyProvider(new Jwks(SymmetricJwk.GenerateKey(128))), SignatureAlgorithm.HS256)); Assert.Throws <ArgumentNullException>(() => builder.IgnoreSignature(null)); Assert.Throws <ArgumentNullException>(() => builder.AcceptUnsecureToken(null)); Assert.Throws <ArgumentNullException>(() => builder.RequireSignatureByDefault((IKeyProvider)null)); Assert.Throws <ArgumentNullException>(() => builder.RequireSignatureByDefault((Jwk)null)); Assert.Throws <InvalidOperationException>(() => builder.RequireSignatureByDefault(SymmetricJwk.GenerateKey(128))); Assert.Throws <ArgumentNullException>(() => builder.RequireSignatureByDefault(SymmetricJwk.GenerateKey(128), (string)null)); Assert.Throws <NotSupportedException>(() => builder.RequireSignatureByDefault(SymmetricJwk.GenerateKey(128), "")); Assert.Throws <NotSupportedException>(() => builder.RequireSignatureByDefault((Jwk)null, "")); Assert.Throws <ArgumentNullException>(() => builder.RequireSignatureByDefault((IList <Jwk>)null)); Assert.Throws <ArgumentOutOfRangeException>(() => builder.EnableLifetimeValidation(clockSkew: -1)); Assert.Throws <ArgumentNullException>(() => builder.RequireAudience((string)null)); Assert.Throws <ArgumentNullException>(() => builder.RequireAudience((IEnumerable <string>)null)); Assert.Throws <ArgumentNullException>(() => builder.DefaultIssuer(null)); Assert.Throws <ArgumentNullException>(() => builder.EnableTokenReplayValidation(null)); Assert.Throws <ArgumentNullException>(() => builder.RequireAlgorithm(null)); Assert.Throws <ArgumentNullException>(() => builder.WithDecryptionKeys((ICollection <IKeyProvider>)null)); }
public void Read() { var key = new RsaJwk ( n: "w7Zdfmece8iaB0kiTY8pCtiBtzbptJmP28nSWwtdjRu0f2GFpajvWE4VhfJAjEsOcwYzay7XGN0b-X84BfC8hmCTOj2b2eHT7NsZegFPKRUQzJ9wW8ipn_aDJWMGDuB1XyqT1E7DYqjUCEOD1b4FLpy_xPn6oV_TYOfQ9fZdbE5HGxJUzekuGcOKqOQ8M7wfYHhHHLxGpQVgL0apWuP2gDDOdTtpuld4D2LK1MZK99s9gaSjRHE8JDb1Z4IGhEcEyzkxswVdPndUWzfvWBBWXWxtSUvQGBRkuy1BHOa4sP6FKjWEeeF7gm7UMs2Nm2QUgNZw6xvEDGaLk4KASdIxRQ", e: "AQAB" ) { Kid = "1e9gdk7", Alg = SignatureAlgorithm.RsaSha256.Utf8Name }; var reader = new JwtReader(); var policy = new TokenValidationPolicyBuilder() .RequireSignature(key) .Build(); var result = reader.TryReadToken("eyJraWQiOiIxZTlnZGs3IiwiYWxnIjoiUlMyNTYifQ.ewogImlzcyI6ICJodHRwOi8vc2VydmVyLmV4YW1wbGUuY29tIiwKICJzdWIiOiAiMjQ4Mjg5NzYxMDAxIiwKICJhdWQiOiAiczZCaGRSa3F0MyIsCiAibm9uY2UiOiAibi0wUzZfV3pBMk1qIiwKICJleHAiOiAxMzExMjgxOTcwLAogImlhdCI6IDEzMTEyODA5NzAsCiAibmFtZSI6ICJKYW5lIERvZSIsCiAiZ2l2ZW5fbmFtZSI6ICJKYW5lIiwKICJmYW1pbHlfbmFtZSI6ICJEb2UiLAogImdlbmRlciI6ICJmZW1hbGUiLAogImJpcnRoZGF0ZSI6ICIwMDAwLTEwLTMxIiwKICJlbWFpbCI6ICJqYW5lZG9lQGV4YW1wbGUuY29tIiwKICJwaWN0dXJlIjogImh0dHA6Ly9leGFtcGxlLmNvbS9qYW5lZG9lL21lLmpwZyIKfQ.rHQjEmBqn9Jre0OLykYNnspA10Qql2rvx4FsD00jwlB0Sym4NzpgvPKsDjn_wMkHxcp6CilPcoKrWHcipR2iAjzLvDNAReF97zoJqq880ZD1bwY82JDauCXELVR9O6_B0w3K-E7yM2macAAgNCUwtik6SjoSUZRcf-O5lygIyLENx882p6MtmwaL1hd6qn5RZOQ0TLrOYu0532g9Exxcm-ChymrB4xLykpDj3lUivJt63eEGGN6DH5K6o33TcxkIjNrCD4XB1CKKumZvCedgHHF3IAK4dVEDSUoGlH9z4pP_eWYNXvqQOjGs-rDaQzUHl6cQQWNiDpWOl_lxXjQEvQ", policy); var token = result.Token.AsIdToken(); Assert.Equal("http://server.example.com", token.Issuer); Assert.Equal("248289761001", token.Subject); Assert.Equal("s6BhdRkqt3", token.Audiences.FirstOrDefault()); Assert.Equal("n-0S6_WzA2Mj", token.Nonce); Assert.Equal(EpochTime.ToDateTime(1311281970), token.ExpirationTime); Assert.Equal(EpochTime.ToDateTime(1311280970), token.IssuedAt); Assert.Equal("Jane Doe", token.Payload["name"]); Assert.Equal("Jane", token.GivenName); Assert.Equal("Doe", token.FamilyName); Assert.Equal("female", token.Gender); Assert.Equal("0000-10-31", token.Birthdate); Assert.Equal("*****@*****.**", token.Email); Assert.Equal("http://example.com/janedoe/me.jpg", token.Picture); }
public void Encode_Decode(EncryptionAlgorithm enc, KeyManagementAlgorithm alg) { var writer = new JwtWriter(); var encryptionKey = SelectKey(enc.Name, alg.Name); var descriptor = new JweDescriptor { EncryptionKey = encryptionKey, EncryptionAlgorithm = enc, Algorithm = alg, Payload = new JwsDescriptor { SigningKey = _signingKey, Algorithm = SignatureAlgorithm.HmacSha256, Subject = "Alice" } }; var token = writer.WriteToken(descriptor); var reader = new JwtReader(encryptionKey); var policy = new TokenValidationPolicyBuilder() .RequireSignature(_signingKey) .Build(); var result = reader.TryReadToken(token, policy); Assert.Equal(TokenValidationStatus.Success, result.Status); Assert.Equal("Alice", result.Token.Subject); }
static void Main() { // Creates a symmetric key defined for the 'HS256' algorithm var signatureKey = new SymmetricJwk("R9MyWaEoyiMYViVWo8Fk4TUGWiSoaW6U1nOqXri8_XU"); // Creates a symmetric key for encryption var encryptionKey = new SymmetricJwk("R9MyWaEoyiMYViVWo8Fk4T"); var policy = new TokenValidationPolicyBuilder() .RequireSignature(signatureKey, SignatureAlgorithm.HmacSha256) .RequireAudience("636C69656E745F6964") .RequireIssuer("https://idp.example.com/") .Build(); var reader = new JwtReader(encryptionKey); var result = reader.TryReadToken("eyJlbmMiOiJBMTI4Q0JDLUhTMjU2IiwiYWxnIjoiQTEyOEtXIn0.f3VIyjZSlzfxTakllbEQeCIU9xSkoqf9duUsbyqTOs8K9EKu_6xcFw.qbmqiA67XDA89YcmsHWwaA.SiqMox7oLg-kIDN0iGifdtX5ILsL5IyziJJp07O-GTx5OFWSsWiB-5Q_GI8CeGBIaEswpfhR9ND9a6YcqKFFT0pTPnw4cI3tcFOcKgjq1ofCZeu4BQkoifH9QuD744MsNVxGekx-rUQQ8OMcnO7q9sHmc4xkQwRDh8GTjd353mRElJMWU_OBswMc4JnMHYHa9cj4u2f9rqKDG1VHIAFai8A1rhfk8Eh7D7MHWQ1CyrN1enYW7veg2adEbr9VH4qG3hCzsOzUyBWx6aJcrwuGHw.T07kRuo-d66j3lPxFzXfQSFeokkInOzofAx3LWh9v-w", policy); if (result.Succedeed) { Console.WriteLine("The token is " + result.Token); } else { Console.WriteLine("Failed to read the token. Reason: " + Environment.NewLine + result.Status); } }
static void Main() { // Creates a symmetric key defined for the 'HS256' algorithm var signatureKey = SymmetricJwk.FromBase64Url("R9MyWaEoyiMYViVWo8Fk4TUGWiSoaW6U1nOqXri8_XU"); // Creates a symmetric key for encryption var decryptionKey = SymmetricJwk.FromBase64Url("R9MyWaEoyiMYViVWo8Fk4T"); var policy = new TokenValidationPolicyBuilder() .RequireSignature("https://idp.example.com/", signatureKey, SignatureAlgorithm.HS256) .RequireAudience("636C69656E745F6964") .WithDecryptionKey(decryptionKey) .Build(); var result = Jwt.TryParse("eyJhbGciOiJBMTI4S1ciLCJlbmMiOiJBMTI4Q0JDLUhTMjU2Iiwia2lkIjoiZWFOTlpaMXBtREFXSWYzYkg3MFg2V3FfbldzUXhuMjFMUngza1daMG5MYyIsImN0eSI6IkpXVCJ9.PU18XXVByiJLE53zkg1m-SzjZXUdRYkl0X20JtsMKXW54RHn3fcK_w.Bu1SPUTuntwvPfwXTj1OhQ.OuCl09TjUMJk80GdY4n5r6HUnH21dWwT1BAbbvPJg75p_AfMvVNmaQ3dahrSmCkuCI5EF34ynE_qUBAuMH9bcplUWS9GDKJfGugEZgkciWORv5RzXvAAokpElpuaiV09SdBmaepi4FAXvTP4axJUWuOXt2MvjnlwbIXlVqUX9Lha1NnsseBLTjfCclhV0pQEKjnncqjuqTcxmqTqAsxZA1v8RJV_FbzBdVBWwQ-qrjYbsrqtsK13XazZEGwAHU7fJT1vlaBdlni6aTQIlwE7JuLA--6hRM9mr7NZ4SlihCFBLjW-DZ2QoQBd6XeFNGKMnNgUP0t6mYihPlmh1eC0BivPaTtCKf4CH6lrq42_17s.ajGQE7r5eAd9z8a-8mmq2g", policy, out var jwt); if (result) { Console.WriteLine("The token is " + jwt); } else { Console.WriteLine("Failed to read the token. Reason: " + Environment.NewLine + jwt.Error.Status); } jwt.Dispose(); }
public void Encode_Decode(string alg) { var(signingKey, validationKey) = SelectKeys(alg); var writer = new JwtWriter(); var descriptor = new JwsDescriptor(signingKey, (SignatureAlgorithm)alg) { Payload = new JwtPayload { { "sub", "Alice" } } }; var token = writer.WriteTokenString(descriptor); var policy = new TokenValidationPolicyBuilder() .RequireSignatureByDefault(validationKey, (SignatureAlgorithm)alg) .Build(); var result = Jwt.TryParse(token, policy, out var jwt); Assert.True(result); Assert.True(jwt.Payload.TryGetClaim("sub", out var sub)); Assert.Equal("Alice", sub.GetString()); jwt.Dispose(); }
public void Write_Valid(string token) { var descriptor = _tokens.Descriptors[token]; JwtWriter writer = new JwtWriter(); var value = writer.WriteToken(descriptor); var policy = new TokenValidationPolicyBuilder() .WithDecryptionKeys(_keys.Jwks) .IgnoreSignatureByDefault() .Build(); var result = Jwt.TryParse(value, policy, out var jwt); Assert.True(result); if (!(descriptor is JwsDescriptor jwsPayload)) { if (!(descriptor is JweDescriptor jwePayload)) { throw new Xunit.Sdk.IsNotTypeException(typeof(JwtDescriptor), descriptor); } jwsPayload = jwePayload.Payload; } Assert.NotNull(jwsPayload); if (jwsPayload.Payload.Count > 0) { Assert.True(jwt.Payload.TryGetClaim("iat", out var iat)); Assert.True(jwt.Payload.TryGetClaim("exp", out var exp)); Assert.True(jwt.Payload.TryGetClaim("iss", out var iss)); Assert.True(jwt.Payload.TryGetClaim("aud", out var aud)); Assert.True(jwt.Payload.TryGetClaim("jti", out var jti)); } }
static void Main() { // This sample demonstrates how to validate a token that may come form different issuers. // This is common if you have to support multiple Authorization Servers. var keyIssuer1 = SymmetricJwk.FromBase64Url("R9MyWaEoyiMYViVWo8Fk4TUGWiSoaW6U1nOqXri8_XU"); var keyIssuer2 = SymmetricJwk.FromBase64Url("9dobXhxMWH9PoLsKRdv1qp0bEqJm4YNd8JRaTxes8i4R9MyWaEoyiMYViVWo8Fk4TUGWiSoaW6U1nOqXri8_XU"); var keyIssuer3 = SymmetricJwk.FromBase64Url("lh2TJcMdPyNLhfNp0nYLAFM_R0UEXVoZ9N7ife4ZT-A"); var policyMultiIssuer = new TokenValidationPolicyBuilder() .RequireSignature("https://idp1.example.com/", keyIssuer1, SignatureAlgorithm.HS256) .RequireSignature("https://idp2.example.com/", keyIssuer2, SignatureAlgorithm.HS512) .RequireSignature("https://idp3.example.com/", keyIssuer3, SignatureAlgorithm.HS256) .RequireAudience("F6964636C69656E745") .Build(); var token = "eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1MDAwMDcyMDAsImlhdCI6MjAwMDAwNzIwMCwiaXNzIjoiaHR0cHM6Ly9pZHAzLmV4YW1wbGUuY29tLyIsImF1ZCI6IkY2OTY0NjM2QzY5NjU2RTc0NSJ9.a6RiTht8kyTDL9SZVX9kUye7dJL9YSZxJPbAyaaw3QE"; // Try to read the token with the different policies if (Jwt.TryParse(token, policyMultiIssuer, out var jwt)) { Console.WriteLine($"The token is issued by '{jwt.Payload["iss"].GetString()}':"); Console.WriteLine(jwt); jwt.Dispose(); } else { Console.WriteLine("Failed to read the token."); Console.WriteLine(" Reason: " + jwt.Error.Status); jwt.Dispose(); } }
private static JwsWrapper CreateDescriptor(SignatureAlgorithm algorithm) { var jwk = algorithm.Category switch { Cryptography.AlgorithmCategory.None => Jwk.None, Cryptography.AlgorithmCategory.EllipticCurve => ECJwk.GeneratePrivateKey(algorithm), Cryptography.AlgorithmCategory.Rsa => RsaJwk.GeneratePrivateKey(4096, algorithm), Cryptography.AlgorithmCategory.Aes => SymmetricJwk.GenerateKey(algorithm), Cryptography.AlgorithmCategory.AesGcm => SymmetricJwk.GenerateKey(algorithm), Cryptography.AlgorithmCategory.Hmac => SymmetricJwk.GenerateKey(algorithm), _ => throw new InvalidOperationException() }; var descriptor = new JwsDescriptor(jwk, algorithm) { Payload = new JwtPayload { { JwtClaimNames.Iat, EpochTime.UtcNow }, { JwtClaimNames.Exp, EpochTime.UtcNow + EpochTime.OneHour }, { JwtClaimNames.Iss, "https://idp.example.com/" }, { JwtClaimNames.Aud, "636C69656E745F6964" } } }; var policy = new TokenValidationPolicyBuilder() .RequireSignature("https://idp.example.com/", jwk, algorithm) .Build(); var writer = new JwtWriter(); return(new JwsWrapper(writer.WriteToken(descriptor), algorithm, policy)); } }
public void Compatible(EncryptionAlgorithm enc, KeyManagementAlgorithm alg) { var writer = new JwtWriter(); foreach (var encryptionKey in SelectEncryptionKey(enc.Name.ToString(), alg.Name.ToString())) { var descriptor = new JweDescriptor(encryptionKey, alg, enc) { Payload = new JwsDescriptor(_signingKey, SignatureAlgorithm.HS256) { Payload = new JwtPayload { { "sub", "Alice" } } } }; var token = writer.WriteToken(descriptor); var policy = new TokenValidationPolicyBuilder() .RequireSignatureByDefault(_signingKey) .WithDecryptionKeys(_keys.Jwks) .Build(); var result = Jwt.TryParse(token, policy, out var jwt); Assert.True(result); Assert.True(jwt.Payload.TryGetClaim("sub", out var sub)); Assert.Equal("Alice", sub.GetString()); jwt.Dispose(); } }
static void Main() { // Initializes the shared secret as a symmetric key of 256 bits var key = SymmetricJwk.FromBase64Url("R9MyWaEoyiMYViVWo8Fk4TUGWiSoaW6U1nOqXri8_XU"); // Defines the validation policy: // - Require the issuer "https://idp.example.com/", with the predefined key, with the signature algorithm HS256 // - Require the audience "636C69656E745F6964" var policy = new TokenValidationPolicyBuilder() .RequireSignature("https://idp.example.com/", key, SignatureAlgorithm.HS256) .RequireAudience("636C69656E745F6964") .Build(); // Try to parse the JWT. Its return false if (Jwt.TryParse("eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1MDAwMDcyMDAsImlhdCI6MjAwMDAwNzIwMCwiaXNzIjoiaHR0cHM6Ly9pZHAuZXhhbXBsZS5jb20vIiwiYXVkIjoiNjM2QzY5NjU2RTc0NUY2OTY0In0.YrrT1Ddp1ampsDd2GwYZoTz_bUnLt_h--f16wsWBedk", policy, out Jwt jwt)) { Console.WriteLine("The token is " + jwt); } else { Console.WriteLine("Failed to read the token. Error: " + Environment.NewLine + jwt.Error); } // Do not forget to dispose the Jwt, or you may suffer of GC impacts jwt.Dispose(); }
public void Fuzz(string value) { var policy = new TokenValidationPolicyBuilder() .IgnoreSignatureByDefault() .WithDecryptionKey(key) .Build(); var parsed = Jwt.TryParse(value, policy, out var jwt); Assert.NotNull(jwt); jwt.Dispose(); }
/// <summary> /// Requires a JWT representing a SECEVENT, verify the presence of the 'events' claim. /// </summary> /// <param name="builder"></param> /// <returns></returns> public static TokenValidationPolicyBuilder RequireSecEventToken(this TokenValidationPolicyBuilder builder) { if (builder == null) { throw new System.ArgumentNullException(nameof(builder)); } builder.RequireClaim(SecEventClaimNames.Events.ToString()); return(builder); }
public void ConfigurePolicy(TokenValidationPolicyBuilder builder) { if (Jwk != null) { builder.RequireSignature(Issuer, Jwk, SignatureAlgorithm); } else if (JwksUri != null) { builder.RequireSignature(Issuer, JwksUri, SignatureAlgorithm); } }
public TokenValidationPolicy BuildPolicy(string audience) { var builder = new TokenValidationPolicyBuilder(); builder.RequireAudience(audience) .RequireSecEventToken(); for (int i = 0; i < _registrations.Count; i++) { var registration = _registrations[i]; registration.ConfigurePolicy(builder); } return(builder.Build()); }
public void Rfc7516_Decrypt() { Jwk encryptionKey = SymmetricJwk.FromBase64Url("GawgguFyGrWKav7AX4VKUg"); string token = "eyJhbGciOiJBMTI4S1ciLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0.6KB707dM9YTIgHtLvtgWQ8mKwboJW3of9locizkDTHzBC2IlrT1oOQ.AxY8DCtDaGlsbGljb3RoZQ.KDlTtXchhZTGufMYmOYGS4HffxPSUrfmqCHXaI9wOGY.U0m_YmjN04DJvceFICbCVQ"; var policy = new TokenValidationPolicyBuilder() .WithDecryptionKey(encryptionKey) .IgnoreSignatureByDefault() .Build(); var result = Jwt.TryParse(token, policy, out var jwt); Assert.True(result); Assert.Equal("Live long and prosper.", jwt.Plaintext); jwt.Dispose(); }
public void Read() { var reader = new JwtReader(_keys.Jwks); var policy = new TokenValidationPolicyBuilder() .AcceptUnsecureToken() .RequireSecurityEventToken() .Build(); var result = reader.TryReadToken("eyJ0eXAiOiJzZWNldmVudCtqd3QiLCJhbGciOiJub25lIn0.eyJqdGkiOiI0ZDM1NTllYzY3NTA0YWFiYTY1ZDQwYjAzNjNmYWFkOCIsImlhdCI6MTQ1ODQ5NjQwNCwiaXNzIjoiaHR0cHM6Ly9zY2ltLmV4YW1wbGUuY29tIiwiYXVkIjpbImh0dHBzOi8vc2NpbS5leGFtcGxlLmNvbS9GZWVkcy85OGQ1MjQ2MWZhNWJiYzg3OTU5M2I3NzU0IiwiaHR0cHM6Ly9zY2ltLmV4YW1wbGUuY29tL0ZlZWRzLzVkNzYwNDUxNmIxZDA4NjQxZDc2NzZlZTciXSwiZXZlbnRzIjp7InVybjppZXRmOnBhcmFtczpzY2ltOmV2ZW50OmNyZWF0ZSI6eyJyZWYiOiJodHRwczovL3NjaW0uZXhhbXBsZS5jb20vVXNlcnMvNDRmNjE0MmRmOTZiZDZhYjYxZTc1MjFkOSIsImF0dHJpYnV0ZXMiOlsiaWQiLCJuYW1lIiwidXNlck5hbWUiLCJwYXNzd29yZCIsImVtYWlscyJdfX19.", policy); var token = result.Token.AsSecurityEventToken(); var events = token.Events; Assert.True(events.ContainsKey("urn:ietf:params:scim:event:create")); Assert.True(events["urn:ietf:params:scim:event:create"].ContainsKey("ref")); Assert.Equal("https://scim.example.com/Users/44f6142df96bd6ab61e7521d9", (string)events["urn:ietf:params:scim:event:create"]["ref"].Value); }
static void Main() { // This sample demonstrates how to validate a token that may come form different issuers. // This is common if you have to support multiple Authorization Servers. var keyIssuer1 = new SymmetricJwk("R9MyWaEoyiMYViVWo8Fk4TUGWiSoaW6U1nOqXri8_XU"); var policyIssuer1 = new TokenValidationPolicyBuilder() .RequireSignature(keyIssuer1, SignatureAlgorithm.HmacSha256) .RequireAudience("636C69656E745F6964") .RequireIssuer("https://idp1.example.com/") .Build(); var keyIssuer2 = new SymmetricJwk("9dobXhxMWH9PoLsKRdv1qp0bEqJm4YNd8JRaTxes8i4"); var policyIssuer2 = new TokenValidationPolicyBuilder() .RequireSignature(keyIssuer2, SignatureAlgorithm.HmacSha256) .RequireAudience("9656E745F6964636C6") .RequireIssuer("https://idp2.example.com/") .Build(); var keyIssuer3 = new SymmetricJwk("lh2TJcMdPyNLhfNp0nYLAFM_R0UEXVoZ9N7ife4ZT-A"); var policyIssuer3 = new TokenValidationPolicyBuilder() .RequireSignature(keyIssuer3, SignatureAlgorithm.HmacSha256) .RequireAudience("F6964636C69656E745") .RequireIssuer("https://idp3.example.com/") .Build(); var policies = new[] { policyIssuer1, policyIssuer2, policyIssuer3 }; var reader = new JwtReader(); var token = "eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1MDAwMDcyMDAsImlhdCI6MjAwMDAwNzIwMCwiaXNzIjoiaHR0cHM6Ly9pZHAzLmV4YW1wbGUuY29tLyIsImF1ZCI6IkY2OTY0NjM2QzY5NjU2RTc0NSJ9.a6RiTht8kyTDL9SZVX9kUye7dJL9YSZxJPbAyaaw3QE"; for (int i = 0; i < policies.Length; i++) { // Try to read the token with the different policies var result = reader.TryReadToken(token, policies[i]); if (result.Succedeed) { Console.WriteLine($"The token is issued by '{result.Token.Issuer}':"); Console.WriteLine(result.Token); break; } Console.WriteLine($"Failed to read the token for the issuer '{policies[i].RequiredIssuer}'."); Console.WriteLine(" Reason: " + result.Status); } }
private static void Main() { var policy = new TokenValidationPolicyBuilder() .RequireSignature(signingKey) .RequireAudience("636C69656E745F6964") .RequireIssuer("https://idp.example.com/") .EnableLifetimeValidation() .Build(); Console.WriteLine("Starting..."); _reader.EnableHeaderCaching = false; //var sha = new Sha512(); //Span<byte> dest = new byte[64]; //var src = new byte[4096]; while (true) { //sha.ComputeHash(src, dest); _reader.TryReadToken(jwsToken, policy); } }
static void Main() { var key = new SymmetricJwk("R9MyWaEoyiMYViVWo8Fk4TUGWiSoaW6U1nOqXri8_XU"); var policy = new TokenValidationPolicyBuilder() .RequireSignature(key, SignatureAlgorithm.HmacSha256) .RequireAudience("636C69656E745F6964") .RequireIssuer("https://idp.example.com/") .Build(); var reader = new JwtReader(); var result = reader.TryReadToken("eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1MDAwMDcyMDAsImlhdCI6MjAwMDAwNzIwMCwiaXNzIjoiaHR0cHM6Ly9pZHAuZXhhbXBsZS5jb20vIiwiYXVkIjoiNjM2QzY5NjU2RTc0NUY2OTY0In0.YrrT1Ddp1ampsDd2GwYZoTz_bUnLt_h--f16wsWBedk", policy); if (result.Succedeed) { Console.WriteLine("The token is " + result.Token); } else { Console.WriteLine("Failed to read the token. Reason: " + Environment.NewLine + result.Status); } }
public void Write_Binary() { var data = new byte[256]; FillData(data); var key = RsaJwk.FromBase64Url ( n: "sXchDaQebHnPiGvyDOAT4saGEUetSyo9MKLOoWFsueri23bOdgWp4Dy1WlUzewbgBHod5pcM9H95GQRV3JDXboIRROSBigeC5yjU1hGzHHyXss8UDprecbAYxknTcQkhslANGRUZmdTOQ5qTRsLAt6BTYuyvVRdhS8exSZEy_c4gs_7svlJJQ4H9_NxsiIoLwAEk7-Q3UXERGYw_75IDrGA84-lA_-Ct4eTlXHBIY2EaV7t7LjJaynVJCpkv4LKjTTAumiGUIuQhrNhZLuF_RJLqHpM2kgWFLU7-VTdL1VbC2tejvcI2BlMkEpk1BzBZI0KQB0GaDWFLN-aEAw3vRw", e: "AQAB", d: "VFCWOqXr8nvZNyaaJLXdnNPXZKRaWCjkU5Q2egQQpTBMwhprMzWzpR8Sxq1OPThh_J6MUD8Z35wky9b8eEO0pwNS8xlh1lOFRRBoNqDIKVOku0aZb-rynq8cxjDTLZQ6Fz7jSjR1Klop-YKaUHc9GsEofQqYruPhzSA-QgajZGPbE_0ZaVDJHfyd7UUBUKunFMScbflYAAOYJqVIVwaYR5zWEEceUjNnTNo_CVSj-VvXLO5VZfCUAVLgW4dpf1SrtZjSt34YLsRarSb127reG_DUwg9Ch-KyvjT1SkHgUWRVGcyly7uvVGRSDwsXypdrNinPA4jlhoNdizK2zF2CWQ", p: "9gY2w6I6S6L0juEKsbeDAwpd9WMfgqFoeA9vEyEUuk4kLwBKcoe1x4HG68ik918hdDSE9vDQSccA3xXHOAFOPJ8R9EeIAbTi1VwBYnbTp87X-xcPWlEPkrdoUKW60tgs1aNd_Nnc9LEVVPMS390zbFxt8TN_biaBgelNgbC95sM", q: "uKlCKvKv_ZJMVcdIs5vVSU_6cPtYI1ljWytExV_skstvRSNi9r66jdd9-yBhVfuG4shsp2j7rGnIio901RBeHo6TPKWVVykPu1iYhQXw1jIABfw-MVsN-3bQ76WLdt2SDxsHs7q7zPyUyHXmps7ycZ5c72wGkUwNOjYelmkiNS0", dp: "w0kZbV63cVRvVX6yk3C8cMxo2qCM4Y8nsq1lmMSYhG4EcL6FWbX5h9yuvngs4iLEFk6eALoUS4vIWEwcL4txw9LsWH_zKI-hwoReoP77cOdSL4AVcraHawlkpyd2TWjE5evgbhWtOxnZee3cXJBkAi64Ik6jZxbvk-RR3pEhnCs", dq: "o_8V14SezckO6CNLKs_btPdFiO9_kC1DsuUTd2LAfIIVeMZ7jn1Gus_Ff7B7IVx3p5KuBGOVF8L-qifLb6nQnLysgHDh132NDioZkhH7mI7hPG-PYE_odApKdnqECHWw0J-F0JWnUd6D2B_1TvF9mXA2Qx-iGYn8OVV1Bsmp6qU", qi: "eNho5yRBEBxhGBtQRww9QirZsB66TrfFReG_CcteI1aCneT0ELGhYlRlCtUkTRclIfuEPmNsNDPbLoLqqCVznFbvdB7x-Tl-m0l_eFTj2KiqwGqE9PZB9nNTwMVvH3VRRSLWACvPnSiwP8N5Usy-WRXS-V7TbpxIhvepTfE0NNo", alg: KeyManagementAlgorithm.Rsa1_5 ); var descriptor = new BinaryJweDescriptor(key, KeyManagementAlgorithm.Rsa1_5, EncryptionAlgorithm.A128CbcHS256) { Payload = data }; JwtWriter writer = new JwtWriter(); var value = writer.WriteToken(descriptor); Assert.NotNull(value); var policy = new TokenValidationPolicyBuilder() .WithDecryptionKey(key) .IgnoreSignatureByDefault() .Build(); var result = Jwt.TryParse(value, policy, out var jwt); Assert.True(result); Assert.True(jwt.RawValue.Span.SequenceEqual(data)); }
public void Write_Utf8ToEscape() { var plaintext = "Live long and prosper!€"; var descriptor = new PlaintextJweDescriptor(RsaKey, KeyManagementAlgorithm.Rsa1_5, EncryptionAlgorithm.A128CbcHS256); descriptor.Payload = plaintext; JwtWriter writer = new JwtWriter(); var value = writer.WriteToken(descriptor); var policy = new TokenValidationPolicyBuilder() .WithDecryptionKey(RsaKey) .IgnoreSignatureByDefault() .Build(); var result = Jwt.TryParse(value, policy, out var jwt); Assert.True(result); Assert.Equal(plaintext, jwt.Plaintext); }
private static JweWrapper CreateDescriptor(KeyManagementAlgorithm algorithm, EncryptionAlgorithm encryptionAlgorithm) { var jwk = algorithm.Category switch { Cryptography.AlgorithmCategory.None => Jwk.None, Cryptography.AlgorithmCategory.EllipticCurve => ECJwk.GeneratePrivateKey(EllipticalCurve.P256, algorithm), Cryptography.AlgorithmCategory.Rsa => RsaJwk.GeneratePrivateKey(4096, algorithm), Cryptography.AlgorithmCategory.Aes => SymmetricJwk.GenerateKey(algorithm), Cryptography.AlgorithmCategory.AesGcm => SymmetricJwk.GenerateKey(algorithm), Cryptography.AlgorithmCategory.Hmac => SymmetricJwk.GenerateKey(algorithm), Cryptography.AlgorithmCategory.Direct => SymmetricJwk.GenerateKey(encryptionAlgorithm), Cryptography.AlgorithmCategory.Direct | Cryptography.AlgorithmCategory.EllipticCurve => ECJwk.GeneratePrivateKey(EllipticalCurve.P256), _ => throw new InvalidOperationException(algorithm.Category.ToString()) }; var descriptor = new JweDescriptor(jwk, algorithm, encryptionAlgorithm) { Payload = new JwsDescriptor(Jwk.None, SignatureAlgorithm.None) { Payload = new JwtPayload { { JwtClaimNames.Iat, EpochTime.UtcNow }, { JwtClaimNames.Exp, EpochTime.UtcNow + EpochTime.OneHour }, { JwtClaimNames.Iss, "https://idp.example.com/" }, { JwtClaimNames.Aud, "636C69656E745F6964" } } } }; var policy = new TokenValidationPolicyBuilder() .AcceptUnsecureToken("https://idp.example.com/") .WithDecryptionKey(jwk) .Build(); var writer = new JwtWriter(); return(new JweWrapper(writer.WriteToken(descriptor), algorithm, encryptionAlgorithm, policy)); } }
public void Encode_Decode(string alg) { var(signingKey, validationKey) = SelectKeys(alg); var writer = new JwtWriter(); var descriptor = new JwsDescriptor { SigningKey = signingKey, Algorithm = (SignatureAlgorithm)alg, Subject = "Alice" }; var token = writer.WriteToken(descriptor); var reader = new JwtReader(); var policy = new TokenValidationPolicyBuilder() .RequireSignature(validationKey, (SignatureAlgorithm)alg) .Build(); var result = reader.TryReadToken(token, policy); Assert.Equal(TokenValidationStatus.Success, result.Status); Assert.Equal("Alice", result.Token.Subject); }
public override string Transform(IConsole console, string data) { console.Verbose($@"Decrypting the JWK... Password derivation iteration count: {_iterationCount} Password derivation salt size: {_saltSize} bits"); var decryptionKey = PasswordBasedJwk.FromPassphrase(_password, _iterationCount, _saltSize); var policy = new TokenValidationPolicyBuilder().WithDecryptionKeys(decryptionKey).IgnoreNestedToken().AcceptUnsecureTokenByDefault().Build(); Jwt?jwt = null; try { if (!Jwt.TryParse(data, policy, out jwt)) { throw new InvalidOperationException($"Failed to decrypt the key.\n{jwt.Error!.Status}\n{jwt.Error!.Message}"); } console.Verbose("JWK decrypted."); return(jwt.Plaintext); } finally { jwt?.Dispose(); } }
/// <summary>Add configuration from the OIDC configuration, including issuer validation and signature requirement.</summary> public static TokenValidationPolicyBuilder AddOpenIdConfiguration(this TokenValidationPolicyBuilder builder, string metadataAddress, SignatureAlgorithm algorithm) { return(builder.RequireMetadataConfiguration(metadataAddress, algorithm)); }
private void NewConnectionHandler() { var server = new TcpListener(ip, port); server.Start(); var policy = new TokenValidationPolicyBuilder() .RequireSignature(SymmetricJwk.FromBase64Url(confWebSocket.JwsKey), SignatureAlgorithm.HmacSha512) .RequireIssuer("Leierkasten Backend") .Build(); var reader = new JwtReader(); while (running) { TcpClient client; if (server.Pending()) { client = server.AcceptTcpClient(); } else { Thread.Sleep(100); continue; } var stream = client.GetStream(); stream.WriteTimeout = 10; while (client.Available < 3) { Thread.Sleep(100); } var bytes = new byte[client.Available]; stream.Read(bytes, 0, bytes.Length); // This is a textual request, decode it var request = Encoding.UTF8.GetString(bytes); // Check if this is a websocket handshake. If no, skip. if (!new Regex("^GET").IsMatch(request)) { Log.Warn("Denied websocket because client used wrong method."); stream.Write(AccessDeniedResponse, 0, AccessDeniedResponse.Length); continue; } const string eol = "\r\n"; const string guid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; // HTML headers are case insensitive var match = new Regex("Sec-WebSocket-Key: (.*)", RegexOptions.IgnoreCase).Match(request); if (!match.Success) { Log.Warn("Sec-WebSocket-Key was not found in request."); Log.Trace("Request was (base64-encoded): " + Convert.ToBase64String(Encoding.ASCII.GetBytes(request))); stream.Write(AccessDeniedResponse, 0, AccessDeniedResponse.Length); continue; } if (match.Groups.Count != 2) { InvalidMatchNumber(match, stream); continue; } string key = match.Groups[1].Value.Trim(); byte[] hashedAcceptKey = SHA1.Create().ComputeHash(Encoding.UTF8.GetBytes(key + guid)); string base64AcceptKey = Convert.ToBase64String(hashedAcceptKey); Log.Trace("Received Sec-WebSocket-Key: " + key); if (Log.IsTraceEnabled) { StringBuilder hex = new StringBuilder(hashedAcceptKey.Length * 2); foreach (byte b in hashedAcceptKey) { hex.AppendFormat("{0:x2}", b); } Log.Trace("Hashed Sec-WebSocket-Key: " + hex); } Log.Trace("Base64 if Sec-WebSocket-Key Hash: " + base64AcceptKey); string responseStr = "HTTP/1.1 101 Switching Protocols" + eol + "Connection: Upgrade" + eol + "Upgrade: websocket" + eol + "Sec-WebSocket-Accept: " + base64AcceptKey + eol + eol; byte[] response = Encoding.UTF8.GetBytes(responseStr); // Get cookie match = new Regex("lk-session=([^;\r\n]*)", RegexOptions.IgnoreCase).Match(request); if (!match.Success) { Log.Warn("Denied websocket because session cookie is missing."); stream.Write(AccessDeniedResponse, 0, AccessDeniedResponse.Length); continue; } if (match.Groups.Count != 2) { InvalidMatchNumber(match, stream); continue; } // Validate session cookie of user var sessionCookie = match.Groups[1].ToString(); var result = reader.TryReadToken(sessionCookie, policy); if (!result.Succedeed) { Log.Warn($"Denied websocket because JWS token could not be validated: {result.ErrorHeader}, {result.ErrorClaim}."); stream.Write(AccessDeniedResponse, 0, AccessDeniedResponse.Length); continue; } if (result.Token?.Payload == null) { Log.Warn("Denied websocket because JWS token payload is empty."); stream.Write(AccessDeniedResponse, 0, AccessDeniedResponse.Length); continue; } var uid = JsonConvert.DeserializeObject <Dictionary <string, string> >(result.Token.Payload.ToString())["uid"]; // Send handshake response stream.Write(response, 0, response.Length); // Start handler for the connection var handler = new WebSocketConnection(client, uid); if (!ConnectedClients.TryAdd(clientCounter++, handler)) { handler.Stop(); } else { OnClientConnected?.Invoke(this, new ClientConnectedEventArgs(handler)); } } server.Stop(); }