From 13dc86c35909d935057a103ee3492f1b5c2a4401 Mon Sep 17 00:00:00 2001 From: Laszlo Schreck Date: Wed, 3 Oct 2018 13:11:56 +0900 Subject: [PATCH 1/9] Fix handling binary HTTP request content --- src/Medidata.MAuth.Core/Constants.cs | 3 ++ .../MAuthCoreExtensions.cs | 45 ++++++++++++++----- 2 files changed, 37 insertions(+), 11 deletions(-) diff --git a/src/Medidata.MAuth.Core/Constants.cs b/src/Medidata.MAuth.Core/Constants.cs index 7e10930..4aad4ca 100644 --- a/src/Medidata.MAuth.Core/Constants.cs +++ b/src/Medidata.MAuth.Core/Constants.cs @@ -1,4 +1,5 @@ using System; +using System.Text; using System.Text.RegularExpressions; namespace Medidata.MAuth.Core @@ -27,5 +28,7 @@ internal static class Constants public static readonly string KeyNormalizeLinesStartRegexPattern = "^(?-----BEGIN [A-Z ]+[-]+)"; public static readonly string KeyNormalizeLinesEndRegexPattern = "(?-----END [A-Z ]+[-]+)$"; + + public static readonly byte[] NewLine = Encoding.UTF8.GetBytes("\n"); } } diff --git a/src/Medidata.MAuth.Core/MAuthCoreExtensions.cs b/src/Medidata.MAuth.Core/MAuthCoreExtensions.cs index 47d434f..e68ddb8 100644 --- a/src/Medidata.MAuth.Core/MAuthCoreExtensions.cs +++ b/src/Medidata.MAuth.Core/MAuthCoreExtensions.cs @@ -8,6 +8,7 @@ using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; +using static Medidata.MAuth.Core.Constants; using Newtonsoft.Json.Linq; using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Encodings; @@ -73,11 +74,15 @@ public static Task Verify(this byte[] signedData, byte[] signature, string /// /// A Task object which will result the SHA512 hash of the signature when it completes. public static async Task GetSignature(this HttpRequestMessage request, AuthenticationInfo authInfo) => - ($"{request.Method.Method}\n" + - $"{request.RequestUri.AbsolutePath}\n" + - $"{(request.Content != null ? await request.Content.ReadAsStringAsync() : string.Empty)}\n" + - $"{authInfo.ApplicationUuid.ToHyphenString()}\n" + - $"{authInfo.SignedTime.ToUnixTimeSeconds()}") + new byte[][] + { + request.Method.Method.ToBytes(), NewLine, + request.RequestUri.AbsolutePath.ToBytes(), NewLine, + (request.Content != null ? await request.Content.ReadAsByteArrayAsync() : new byte[] { }), NewLine, + authInfo.ApplicationUuid.ToHyphenString().ToBytes(), NewLine, + authInfo.SignedTime.ToUnixTimeSeconds().ToString().ToBytes() + } + .Concat() .AsSHA512Hash(); /// @@ -124,8 +129,8 @@ public async static Task AddAuthenticationInfo( $"MWS {authInfo.ApplicationUuid.ToHyphenString()}:" + $"{await request.CalculatePayload(authInfo)}"; - request.Headers.Add(Constants.MAuthHeaderKey, authHeader); - request.Headers.Add(Constants.MAuthTimeHeaderKey, authInfo.SignedTime.ToUnixTimeSeconds().ToString()); + request.Headers.Add(MAuthHeaderKey, authHeader); + request.Headers.Add(MAuthTimeHeaderKey, authInfo.SignedTime.ToUnixTimeSeconds().ToString()); return request; } @@ -165,7 +170,7 @@ public async static Task FromResponse(this HttpContent content) /// The date and time to be converted. /// The total seconds elapsed from the Unix epoch (1970-01-01 00:00:00). public static long ToUnixTimeSeconds(this DateTimeOffset value) => - (long)(value - Constants.UnixEpoch).TotalSeconds; + (long)(value - UnixEpoch).TotalSeconds; /// /// Converts a value that is a Unix time in seconds to a UTC . @@ -173,7 +178,7 @@ public static long ToUnixTimeSeconds(this DateTimeOffset value) => /// The Unix time seconds to be converted. /// The equivalent of the Unix time. public static DateTimeOffset FromUnixTimeSeconds(this long value) => - Constants.UnixEpoch.AddSeconds(value); + UnixEpoch.AddSeconds(value); /// @@ -209,6 +214,8 @@ public static TValue GetFirstValueOrDefault(this HttpHeaders headers, st public static byte[] AsSHA512Hash(this string value) => Hex.Encode(SHA512.Create().ComputeHash(Encoding.UTF8.GetBytes(value))); + public static byte[] AsSHA512Hash(this byte[] value) => + Hex.Encode(SHA512.Create().ComputeHash(value)); /// /// Provides a string PEM (ASN.1) format key as an object. @@ -257,9 +264,25 @@ private static string RemoveLineBreaks(this string key) => key.Replace("\r", string.Empty).Replace("\n", string.Empty); private static string InsertLineBreakAfterBegin(this string key) => - Regex.Replace(key, Constants.KeyNormalizeLinesStartRegexPattern, "${begin}\n"); + Regex.Replace(key, KeyNormalizeLinesStartRegexPattern, "${begin}\n"); private static string InsertLineBreakBeforeEnd(this string key) => - Regex.Replace(key, Constants.KeyNormalizeLinesEndRegexPattern, "\n${end}"); + Regex.Replace(key, KeyNormalizeLinesEndRegexPattern, "\n${end}"); + + + private static byte[] ToBytes(this string value) => Encoding.UTF8.GetBytes(value); + + private static byte[] Concat(this byte[][] values) + { + var result = new byte[values.Sum(x => x.Length)]; + var offset = 0; + foreach (var value in values) + { + Buffer.BlockCopy(value, 0, result, offset, value.Length); + offset += value.Length; + } + + return result; + } } } From 9e29a2020c89838ec06a1c4370ebff6d54c648f7 Mon Sep 17 00:00:00 2001 From: Laszlo Schreck Date: Wed, 3 Oct 2018 13:46:20 +0900 Subject: [PATCH 2/9] Refactor the tests to be able to test binary --- .../Infrastructure/RequestData.cs | 38 +++++++++ .../Infrastructure/TestData.cs | 42 ---------- .../Infrastructure/TestExtensions.cs | 26 +++++++ .../MAuthAspNetCoreTests.cs | 18 ++--- .../MAuthAuthenticatorTests.cs | 78 +++++++++---------- .../MAuthCoreExtensionsTests.cs | 63 +++++++++------ tests/Medidata.MAuth.Tests/MAuthOwinTests.cs | 30 ++++--- .../MAuthSigningHandlerTests.cs | 8 +- .../Medidata.MAuth.Tests/MAuthWebApiTests.cs | 21 +++-- .../Medidata.MAuth.Tests.csproj | 26 +++---- .../Mocks/RequestData/DELETE.json | 7 ++ .../Mocks/RequestData/GET.json | 7 ++ .../Mocks/RequestData/POST.json | 8 ++ .../Mocks/RequestData/POSTWithBinaryData.json | 8 ++ .../Mocks/RequestData/PUT.json | 8 ++ .../Mocks/Requests/DELETE.txt | 2 - .../Mocks/Requests/GET.txt | 2 - .../Mocks/Requests/POST.txt | 3 - .../Mocks/Requests/PUT.txt | 3 - .../UtilityExtensionsTest.cs | 12 +-- 20 files changed, 238 insertions(+), 172 deletions(-) create mode 100644 tests/Medidata.MAuth.Tests/Infrastructure/RequestData.cs delete mode 100644 tests/Medidata.MAuth.Tests/Infrastructure/TestData.cs create mode 100644 tests/Medidata.MAuth.Tests/Mocks/RequestData/DELETE.json create mode 100644 tests/Medidata.MAuth.Tests/Mocks/RequestData/GET.json create mode 100644 tests/Medidata.MAuth.Tests/Mocks/RequestData/POST.json create mode 100644 tests/Medidata.MAuth.Tests/Mocks/RequestData/POSTWithBinaryData.json create mode 100644 tests/Medidata.MAuth.Tests/Mocks/RequestData/PUT.json delete mode 100644 tests/Medidata.MAuth.Tests/Mocks/Requests/DELETE.txt delete mode 100644 tests/Medidata.MAuth.Tests/Mocks/Requests/GET.txt delete mode 100644 tests/Medidata.MAuth.Tests/Mocks/Requests/POST.txt delete mode 100644 tests/Medidata.MAuth.Tests/Mocks/Requests/PUT.txt diff --git a/tests/Medidata.MAuth.Tests/Infrastructure/RequestData.cs b/tests/Medidata.MAuth.Tests/Infrastructure/RequestData.cs new file mode 100644 index 0000000..2f31944 --- /dev/null +++ b/tests/Medidata.MAuth.Tests/Infrastructure/RequestData.cs @@ -0,0 +1,38 @@ +using System; +using System.Net.Http; +using System.Runtime.Serialization; +using Medidata.MAuth.Core; + +namespace Medidata.MAuth.Tests.Infrastructure +{ + [DataContract] + internal class RequestData + { + [DataMember] + public Uri Url { get; set; } + + [DataMember] + public string Method { get; set; } + + [DataMember] + public DateTimeOffset SignedTime { get; set; } + + [DataMember] + public string Base64Content { get; set; } + + [DataMember] + public Guid ApplicationUuid { get; set; } + + [DataMember] + public string Payload { get; set; } + + [IgnoreDataMember] + public long SignedTimeUnixSeconds => SignedTime.ToUnixTimeSeconds(); + + [IgnoreDataMember] + public string MAuthHeader => $"MWS {ApplicationUuidString}:{Payload}"; + + [IgnoreDataMember] + public string ApplicationUuidString => ApplicationUuid.ToHyphenString(); + } +} diff --git a/tests/Medidata.MAuth.Tests/Infrastructure/TestData.cs b/tests/Medidata.MAuth.Tests/Infrastructure/TestData.cs deleted file mode 100644 index 1a19a36..0000000 --- a/tests/Medidata.MAuth.Tests/Infrastructure/TestData.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System; -using System.Net.Http; -using System.Threading.Tasks; -using Medidata.MAuth.Core; - -namespace Medidata.MAuth.Tests.Infrastructure -{ - internal class TestData - { - public HttpMethod Method { get; private set; } - - public string Payload { get; private set; } - - public DateTimeOffset SignedTime { get; private set; } - - public string Content { get; private set; } - - public long SignedTimeUnixSeconds => SignedTime.ToUnixTimeSeconds(); - - public HttpRequestMessage Request => new HttpRequestMessage(Method, "http://localhost:29999/") - { - Content = Content != null ? new StringContent(Content) : null - }; - - public string MAuthHeader => $"MWS {TestExtensions.ClientUuid}:{Payload}"; - - public static async Task For(string method) - { - var lines = - (await TestExtensions.GetStringFromResource($"Medidata.MAuth.Tests.Mocks.Requests.{method}.txt")) - .Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries); - - return new TestData() - { - Method = new HttpMethod(method), - Payload = lines[0], - SignedTime = DateTimeOffset.Parse(lines[1]), - Content = lines.Length >= 3 ? lines[2] : null - }; - } - } -} diff --git a/tests/Medidata.MAuth.Tests/Infrastructure/TestExtensions.cs b/tests/Medidata.MAuth.Tests/Infrastructure/TestExtensions.cs index e343c29..d948788 100644 --- a/tests/Medidata.MAuth.Tests/Infrastructure/TestExtensions.cs +++ b/tests/Medidata.MAuth.Tests/Infrastructure/TestExtensions.cs @@ -1,8 +1,11 @@ using System; using System.IO; +using System.Net.Http; using System.Reflection; +using System.Text; using System.Threading.Tasks; using Medidata.MAuth.Core; +using Newtonsoft.Json; namespace Medidata.MAuth.Tests.Infrastructure { @@ -57,9 +60,32 @@ public static Task GetStringFromResource(string resourceName) } } + public static async Task FromResource(this string requestDataName) => + JsonConvert.DeserializeObject( + await GetStringFromResource($"Medidata.MAuth.Tests.Mocks.RequestData.{requestDataName}.json") + ); + private static Task GetKeyFromResource(string keyName) { return GetStringFromResource($"Medidata.MAuth.Tests.Mocks.Keys.{keyName}.pem"); } + + public static HttpRequestMessage ToHttpRequestMessage(this RequestData data) + { + var result = new HttpRequestMessage(new HttpMethod(data.Method), data.Url) + { + Content = !string.IsNullOrEmpty(data.Base64Content) ? + new ByteArrayContent(Convert.FromBase64String(data.Base64Content)) : + null, + }; + + result.Headers.Add(Constants.MAuthHeaderKey, $"MWS {data.ApplicationUuidString}:{data.Payload}"); + result.Headers.Add(Constants.MAuthTimeHeaderKey, data.SignedTimeUnixSeconds.ToString()); + + return result; + } + + public static string ToStringContent(this string base64Content) => + base64Content == null ? null : Encoding.UTF8.GetString(Convert.FromBase64String(base64Content)); } } diff --git a/tests/Medidata.MAuth.Tests/MAuthAspNetCoreTests.cs b/tests/Medidata.MAuth.Tests/MAuthAspNetCoreTests.cs index 44d865c..d2ab9be 100644 --- a/tests/Medidata.MAuth.Tests/MAuthAspNetCoreTests.cs +++ b/tests/Medidata.MAuth.Tests/MAuthAspNetCoreTests.cs @@ -21,7 +21,7 @@ public class MAuthAspNetCoreTests public async Task MAuthMiddleware_WithValidRequest_WillAuthenticate(string method) { // Arrange - var testData = await TestData.For(method); + var testData = await method.FromResource(); using (var server = new TestServer(new WebHostBuilder().Configure(app => { @@ -39,7 +39,7 @@ public async Task MAuthMiddleware_WithValidRequest_WillAuthenticate(string metho { // Act var response = await server.CreateClient().SendAsync( - await testData.Request.Sign(TestExtensions.ClientOptions(testData.SignedTime))); + await testData.ToHttpRequestMessage().Sign(TestExtensions.ClientOptions(testData.SignedTime))); // Assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); @@ -54,7 +54,7 @@ public async Task MAuthMiddleware_WithValidRequest_WillAuthenticate(string metho public async Task MAuthMiddleware_WithoutMAuthHeader_WillNotAuthenticate(string method) { // Arrange - var testData = await TestData.For(method); + var testData = await method.FromResource(); using (var server = new TestServer(new WebHostBuilder().Configure(app => { @@ -70,7 +70,7 @@ public async Task MAuthMiddleware_WithoutMAuthHeader_WillNotAuthenticate(string }))) { // Act - var response = await server.CreateClient().SendAsync(testData.Request); + var response = await server.CreateClient().SendAsync(testData.ToHttpRequestMessage()); // Assert Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); @@ -85,7 +85,7 @@ public async Task MAuthMiddleware_WithoutMAuthHeader_WillNotAuthenticate(string public async Task MAuthMiddleware_WithEnabledExceptions_WillThrowException(string method) { // Arrange - var testData = await TestData.For(method); + var testData = await method.FromResource(); using (var server = new TestServer(new WebHostBuilder().Configure(app => { @@ -101,7 +101,7 @@ public async Task MAuthMiddleware_WithEnabledExceptions_WillThrowException(strin { // Act, Assert var ex = await Assert.ThrowsAsync( - () => server.CreateClient().SendAsync(testData.Request)); + () => server.CreateClient().SendAsync(testData.ToHttpRequestMessage())); Assert.Equal("The request has invalid MAuth authentication headers.", ex.Message); Assert.NotNull(ex.InnerException); @@ -116,7 +116,7 @@ public async Task MAuthMiddleware_WithEnabledExceptions_WillThrowException(strin public async Task MAuthMiddleware_WithNonSeekableBodyStream_WillRestoreBodyStream(string method) { // Arrange - var testData = await TestData.For(method); + var testData = await method.FromResource(); var canSeek = false; var body = string.Empty; using (var server = new TestServer(new WebHostBuilder().Configure(app => @@ -140,11 +140,11 @@ public async Task MAuthMiddleware_WithNonSeekableBodyStream_WillRestoreBodyStrea { // Act var response = await server.CreateClient().SendAsync( - await testData.Request.Sign(TestExtensions.ClientOptions(testData.SignedTime))); + await testData.ToHttpRequestMessage().Sign(TestExtensions.ClientOptions(testData.SignedTime))); // Assert Assert.True(canSeek); - Assert.Equal(testData.Content ?? string.Empty, body); + Assert.Equal(testData.Base64Content.ToStringContent() ?? string.Empty, body); } } } diff --git a/tests/Medidata.MAuth.Tests/MAuthAuthenticatorTests.cs b/tests/Medidata.MAuth.Tests/MAuthAuthenticatorTests.cs index 2c3a6a3..b64edcf 100644 --- a/tests/Medidata.MAuth.Tests/MAuthAuthenticatorTests.cs +++ b/tests/Medidata.MAuth.Tests/MAuthAuthenticatorTests.cs @@ -8,49 +8,46 @@ namespace Medidata.MAuth.Tests { - public class MAuthAuthenticatorTests + public static class MAuthAuthenticatorTests { [Theory] [InlineData(null, "private key")] [InlineData("http://localhost", null)] - public void MAuthAuthenticator_WithInvalidOptions_WillThrowException(string mauthServiceUrl, string privateKey) - { - // Assert + public static void MAuthAuthenticator_WithInvalidOptions_WillThrowException( + string mauthServiceUrl, string privateKey) => Assert.Throws(() => new MAuthAuthenticator(new MAuthTestOptions() { ApplicationUuid = TestExtensions.ClientUuid, MAuthServiceUrl = mauthServiceUrl != null ? new Uri(mauthServiceUrl) : null, PrivateKey = privateKey })); - } [Fact] - public void MAuthAuthenticator_WithDefaultUuid_WillThrowException() - { + public static void MAuthAuthenticator_WithDefaultUuid_WillThrowException() => Assert.Throws(() => new MAuthAuthenticator(new MAuthTestOptions() - { - ApplicationUuid = default(Guid) - })); - } + { + ApplicationUuid = default(Guid) + })); [Theory] [InlineData("GET")] [InlineData("DELETE")] [InlineData("POST")] [InlineData("PUT")] - public async Task AuthenticateRequest_WithValidRequest_WillAuthenticate(string method) + public static async Task AuthenticateRequest_WithValidRequest_WillAuthenticate(string method) { // Arrange - var testData = await TestData.For(method); + var testData = await method.FromResource(); var authenticator = new MAuthAuthenticator(TestExtensions.ServerOptions); - var signedRequest = await testData.Request.AddAuthenticationInfo(new PrivateKeyAuthenticationInfo() - { - ApplicationUuid = TestExtensions.ClientUuid, - PrivateKey = TestExtensions.ClientPrivateKey, - SignedTime = testData.SignedTime - }); + var signedRequest = await testData.ToHttpRequestMessage() + .AddAuthenticationInfo(new PrivateKeyAuthenticationInfo() + { + ApplicationUuid = testData.ApplicationUuid, + PrivateKey = TestExtensions.ClientPrivateKey, + SignedTime = testData.SignedTime + }); // Act var isAuthenticated = await authenticator.AuthenticateRequest(signedRequest); @@ -65,20 +62,22 @@ public async Task AuthenticateRequest_WithValidRequest_WillAuthenticate(string m [InlineData(MAuthServiceRetryPolicy.RetryOnce)] [InlineData(MAuthServiceRetryPolicy.RetryTwice)] [InlineData(MAuthServiceRetryPolicy.Agressive)] - public async Task AuthenticateRequest_WithNumberOfAttempts_WillAuthenticate(MAuthServiceRetryPolicy policy) + public static async Task AuthenticateRequest_WithNumberOfAttempts_WillAuthenticate( + MAuthServiceRetryPolicy policy) { // Arrange - var testData = await TestData.For("GET"); + var testData = await "GET".FromResource(); var authenticator = new MAuthAuthenticator(TestExtensions.GetServerOptionsWithAttempts( policy, shouldSucceedWithin: true)); - var signedRequest = await testData.Request.AddAuthenticationInfo(new PrivateKeyAuthenticationInfo() - { - ApplicationUuid = TestExtensions.ClientUuid, - PrivateKey = TestExtensions.ClientPrivateKey, - SignedTime = testData.SignedTime - }); + var signedRequest = await testData.ToHttpRequestMessage() + .AddAuthenticationInfo(new PrivateKeyAuthenticationInfo() + { + ApplicationUuid = testData.ApplicationUuid, + PrivateKey = TestExtensions.ClientPrivateKey, + SignedTime = testData.SignedTime + }); // Act var isAuthenticated = await authenticator.AuthenticateRequest(signedRequest); @@ -92,21 +91,22 @@ public async Task AuthenticateRequest_WithNumberOfAttempts_WillAuthenticate(MAut [InlineData(MAuthServiceRetryPolicy.RetryOnce)] [InlineData(MAuthServiceRetryPolicy.RetryTwice)] [InlineData(MAuthServiceRetryPolicy.Agressive)] - public async Task AuthenticateRequest_AfterNumberOfAttempts_WillThrowExceptionWithRequestFailure( + public static async Task AuthenticateRequest_AfterNumberOfAttempts_WillThrowExceptionWithRequestFailure( MAuthServiceRetryPolicy policy) { // Arrange - var testData = await TestData.For("GET"); + var testData = await "GET".FromResource(); var authenticator = new MAuthAuthenticator(TestExtensions.GetServerOptionsWithAttempts( policy, shouldSucceedWithin: false)); - var signedRequest = await testData.Request.AddAuthenticationInfo(new PrivateKeyAuthenticationInfo() - { - ApplicationUuid = TestExtensions.ClientUuid, - PrivateKey = TestExtensions.ClientPrivateKey, - SignedTime = testData.SignedTime - }); + var signedRequest = await testData.ToHttpRequestMessage() + .AddAuthenticationInfo(new PrivateKeyAuthenticationInfo() + { + ApplicationUuid = testData.ApplicationUuid, + PrivateKey = TestExtensions.ClientPrivateKey, + SignedTime = testData.SignedTime + }); // Act var exception = (await Assert.ThrowsAsync( @@ -125,14 +125,14 @@ public async Task AuthenticateRequest_AfterNumberOfAttempts_WillThrowExceptionWi [InlineData("DELETE")] [InlineData("POST")] [InlineData("PUT")] - public async Task SignRequest_WithValidRequest_WillSignProperly(string method) + public static async Task SignRequest_WithValidRequest_WillSignProperly(string method) { // Arrange - var testData = await TestData.For(method); - var expectedMAuthHeader = $"MWS {TestExtensions.ClientUuid.ToHyphenString()}:{testData.Payload}"; + var testData = await method.FromResource(); + var expectedMAuthHeader = testData.MAuthHeader; // Act - var actual = await testData.Request.Sign(TestExtensions.ClientOptions(testData.SignedTime)); + var actual = await testData.ToHttpRequestMessage().Sign(TestExtensions.ClientOptions(testData.SignedTime)); // Assert Assert.Equal(expectedMAuthHeader, actual.Headers.GetFirstValueOrDefault(Constants.MAuthHeaderKey)); diff --git a/tests/Medidata.MAuth.Tests/MAuthCoreExtensionsTests.cs b/tests/Medidata.MAuth.Tests/MAuthCoreExtensionsTests.cs index 85cca9b..f5113b0 100644 --- a/tests/Medidata.MAuth.Tests/MAuthCoreExtensionsTests.cs +++ b/tests/Medidata.MAuth.Tests/MAuthCoreExtensionsTests.cs @@ -10,34 +10,34 @@ namespace Medidata.MAuth.Tests { - public class MAuthCoreExtensionsTests + public static class MAuthCoreExtensionsTests { [Theory] [InlineData("GET")] [InlineData("DELETE")] [InlineData("POST")] [InlineData("PUT")] - public async Task CalculatePayload_WithRequestAndAuthInfo_WillReturnCorrectPayload(string method) + public static async Task CalculatePayload_WithRequestAndAuthInfo_WillReturnCorrectPayload(string method) { // Arrange - var testData = await TestData.For(method); + var testData = await method.FromResource(); var authInfo = new PrivateKeyAuthenticationInfo() { - ApplicationUuid = TestExtensions.ClientUuid, + ApplicationUuid = testData.ApplicationUuid, SignedTime = testData.SignedTime, PrivateKey = TestExtensions.ClientPrivateKey }; // Act - var result = await testData.Request.CalculatePayload(authInfo); + var result = await testData.ToHttpRequestMessage().CalculatePayload(authInfo); // Assert Assert.Equal(testData.Payload, result); } [Fact] - public async Task Verify_WithCorrectlySignedData_WillVerifyTheDataAsValid() + public static async Task Verify_WithCorrectlySignedData_WillVerifyTheDataAsValid() { // Arrange var signature = "This is a signature."; @@ -60,49 +60,68 @@ public async Task Verify_WithCorrectlySignedData_WillVerifyTheDataAsValid() [InlineData("DELETE")] [InlineData("POST")] [InlineData("PUT")] - public async Task GetSignature_WithRequest_WillReturnTheCorrectSignature(string method) + public static async Task GetSignature_WithRequest_WillReturnTheCorrectSignature(string method) { // Arrange - var testData = await TestData.For(method); + var testData = await method.FromResource(); var expectedSignature = - ($"{method}\n/\n{testData.Content}\n{TestExtensions.ClientUuid.ToHyphenString()}\n" + + ($"{method}\n/\n{testData.Base64Content.ToStringContent()}\n" + + $"{testData.ApplicationUuidString}\n" + $"{testData.SignedTime.ToUnixTimeSeconds()}") .AsSHA512Hash(); var authInfo = new PrivateKeyAuthenticationInfo() { - ApplicationUuid = TestExtensions.ClientUuid, + ApplicationUuid = testData.ApplicationUuid, SignedTime = testData.SignedTime }; // Act - var result = await testData.Request.GetSignature(authInfo); + var result = await testData.ToHttpRequestMessage().GetSignature(authInfo); // Assert Assert.Equal(expectedSignature, result); } + [Fact] + public static async Task CalculatePayload_WithBinaryContent_WillCalculateTheProperPayload() + { + // Arrange + var testData = await "POSTWithBinaryData".FromResource(); + + // Act + var result = await testData.ToHttpRequestMessage().CalculatePayload(new PrivateKeyAuthenticationInfo() + { + ApplicationUuid = testData.ApplicationUuid, + SignedTime = testData.SignedTime, + PrivateKey = TestExtensions.ClientPrivateKey + }); + + // Assert + Assert.Equal(testData.Payload, result); + } + [Theory] [InlineData("GET")] [InlineData("DELETE")] [InlineData("POST")] [InlineData("PUT")] - public async Task GetAuthenticationInfo_WithSignedRequest_WillReturnCorrectAuthInfo(string method) + public static async Task GetAuthenticationInfo_WithSignedRequest_WillReturnCorrectAuthInfo(string method) { // Arrange - var testData = await TestData.For(method); - var request = new HttpRequestMessage(testData.Method, TestExtensions.TestUri); + var testData = await method.FromResource(); + var request = new HttpRequestMessage(new HttpMethod(testData.Method), TestExtensions.TestUri); request.Headers.Add( - Constants.MAuthHeaderKey, $"MWS {TestExtensions.ClientUuid.ToHyphenString()}:{testData.Payload}"); + Constants.MAuthHeaderKey, testData.MAuthHeader); request.Headers.Add(Constants.MAuthTimeHeaderKey, testData.SignedTimeUnixSeconds.ToString()); // Act var actual = request.GetAuthenticationInfo(); // Assert - Assert.Equal(TestExtensions.ClientUuid, actual.ApplicationUuid); + Assert.Equal(testData.ApplicationUuid, actual.ApplicationUuid); Assert.Equal(Convert.FromBase64String(testData.Payload), actual.Payload); Assert.Equal(testData.SignedTime, actual.SignedTime); } @@ -112,21 +131,21 @@ public async Task GetAuthenticationInfo_WithSignedRequest_WillReturnCorrectAuthI [InlineData("DELETE")] [InlineData("POST")] [InlineData("PUT")] - public async Task AddAuthenticationInfo_WithRequestAndAuthInfo_WillAddCorrectInformation(string method) + public static async Task AddAuthenticationInfo_WithRequestAndAuthInfo_WillAddCorrectInformation(string method) { // Arrange - var testData = await TestData.For(method); - var expectedMAuthHeader = $"MWS {TestExtensions.ClientUuid.ToHyphenString()}:{testData.Payload}"; + var testData = await method.FromResource(); + var expectedMAuthHeader = testData.MAuthHeader; var authInfo = new PrivateKeyAuthenticationInfo() { - ApplicationUuid = TestExtensions.ClientUuid, + ApplicationUuid = testData.ApplicationUuid, SignedTime = testData.SignedTime, PrivateKey = TestExtensions.ClientPrivateKey }; // Act - var actual = await testData.Request.AddAuthenticationInfo(authInfo); + var actual = await testData.ToHttpRequestMessage().AddAuthenticationInfo(authInfo); // Assert Assert.Equal(expectedMAuthHeader, actual.Headers.GetFirstValueOrDefault(Constants.MAuthHeaderKey)); @@ -140,7 +159,7 @@ public async Task AddAuthenticationInfo_WithRequestAndAuthInfo_WillAddCorrectInf [InlineData("LinuxLineEnding.pem")] [InlineData("WindowsLineEnding.pem")] [InlineData("NoLineEnding.pem")] - public void AsCipherParameters_WithDifferentLineEndingKeys_WillReadTheKeysSuccessfully(string keyFilename) + public static void AsCipherParameters_WithDifferentLineEnding_WillReadTheKeysSuccessfully(string keyFilename) { // Arrange var keyPath = $"Mocks\\Keys\\{keyFilename}"; diff --git a/tests/Medidata.MAuth.Tests/MAuthOwinTests.cs b/tests/Medidata.MAuth.Tests/MAuthOwinTests.cs index c744972..8795587 100644 --- a/tests/Medidata.MAuth.Tests/MAuthOwinTests.cs +++ b/tests/Medidata.MAuth.Tests/MAuthOwinTests.cs @@ -12,17 +12,17 @@ namespace Medidata.MAuth.Tests { - public class MAuthOwinTests + public static class MAuthOwinTests { [Theory] [InlineData("GET")] [InlineData("DELETE")] [InlineData("POST")] [InlineData("PUT")] - public async Task MAuthMiddleware_WithValidRequest_WillAuthenticate(string method) + public static async Task MAuthMiddleware_WithValidRequest_WillAuthenticate(string method) { // Arrange - var testData = await TestData.For(method); + var testData = await method.FromResource(); using (var server = TestServer.Create(app => { @@ -38,8 +38,7 @@ public async Task MAuthMiddleware_WithValidRequest_WillAuthenticate(string metho })) { // Act - var response = await server.HttpClient.SendAsync( - await testData.Request.Sign(TestExtensions.ClientOptions(testData.SignedTime))); + var response = await server.HttpClient.SendAsync(testData.ToHttpRequestMessage()); // Assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); @@ -51,10 +50,10 @@ public async Task MAuthMiddleware_WithValidRequest_WillAuthenticate(string metho [InlineData("DELETE")] [InlineData("POST")] [InlineData("PUT")] - public async Task MAuthMiddleware_WithoutMAuthHeader_WillNotAuthenticate(string method) + public static async Task MAuthMiddleware_WithoutMAuthHeader_WillNotAuthenticate(string method) { // Arrange - var testData = await TestData.For(method); + var testData = await method.FromResource(); using (var server = TestServer.Create(app => { @@ -70,7 +69,7 @@ public async Task MAuthMiddleware_WithoutMAuthHeader_WillNotAuthenticate(string })) { // Act - var response = await server.HttpClient.SendAsync(testData.Request); + var response = await server.HttpClient.SendAsync(new HttpRequestMessage(HttpMethod.Get, testData.Url)); // Assert Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); @@ -82,10 +81,10 @@ public async Task MAuthMiddleware_WithoutMAuthHeader_WillNotAuthenticate(string [InlineData("DELETE")] [InlineData("POST")] [InlineData("PUT")] - public async Task MAuthMiddleware_WithEnabledExceptions_WillThrowException(string method) + public static async Task MAuthMiddleware_WithEnabledExceptions_WillThrowException(string method) { // Arrange - var testData = await TestData.For(method); + var testData = await method.FromResource(); using (var server = TestServer.Create(app => { @@ -103,7 +102,7 @@ public async Task MAuthMiddleware_WithEnabledExceptions_WillThrowException(strin { // Act, Assert var ex = await Assert.ThrowsAsync( - () => server.HttpClient.SendAsync(testData.Request)); + () => server.HttpClient.SendAsync(new HttpRequestMessage(HttpMethod.Get, testData.Url))); Assert.Equal("The request has invalid MAuth authentication headers.", ex.Message); Assert.NotNull(ex.InnerException); @@ -115,10 +114,10 @@ public async Task MAuthMiddleware_WithEnabledExceptions_WillThrowException(strin [InlineData("DELETE")] [InlineData("POST")] [InlineData("PUT")] - public async Task MAuthMiddleware_WithNonSeekableBodyStream_WillRestoreBodyStream(string method) + public static async Task MAuthMiddleware_WithNonSeekableBodyStream_WillRestoreBodyStream(string method) { // Arrange - var testData = await TestData.For(method); + var testData = await method.FromResource(); var canSeek = false; var body = string.Empty; @@ -142,12 +141,11 @@ public async Task MAuthMiddleware_WithNonSeekableBodyStream_WillRestoreBodyStrea })) { // Act - var response = await new HttpClient().SendAsync( - await testData.Request.Sign(TestExtensions.ClientOptions(testData.SignedTime))); + var response = await new HttpClient().SendAsync(testData.ToHttpRequestMessage()); // Assert Assert.True(canSeek); - Assert.Equal(testData.Content ?? string.Empty, body); + Assert.Equal(testData.Base64Content.ToStringContent() ?? string.Empty, body); } } } diff --git a/tests/Medidata.MAuth.Tests/MAuthSigningHandlerTests.cs b/tests/Medidata.MAuth.Tests/MAuthSigningHandlerTests.cs index cdacc55..cd3a306 100644 --- a/tests/Medidata.MAuth.Tests/MAuthSigningHandlerTests.cs +++ b/tests/Medidata.MAuth.Tests/MAuthSigningHandlerTests.cs @@ -6,24 +6,24 @@ namespace Medidata.MAuth.Tests { - public class MAuthSigningHandlerTests + public static class MAuthSigningHandlerTests { [Theory] [InlineData("GET")] [InlineData("DELETE")] [InlineData("POST")] [InlineData("PUT")] - public async Task SendAsync_WithValidRequest_WillSignProperly(string method) + public static async Task SendAsync_WithValidRequest_WillSignProperly(string method) { // Arrange - var testData = await TestData.For(method); + var testData = await method.FromResource(); var actual = new AssertSigningHandler(); var signingHandler = new MAuthSigningHandler(TestExtensions.ClientOptions(testData.SignedTime), actual); // Act using (var client = new HttpClient(signingHandler)) { - await client.SendAsync(testData.Request); + await client.SendAsync(testData.ToHttpRequestMessage()); } // Assert diff --git a/tests/Medidata.MAuth.Tests/MAuthWebApiTests.cs b/tests/Medidata.MAuth.Tests/MAuthWebApiTests.cs index 5e46bb4..a8927a7 100644 --- a/tests/Medidata.MAuth.Tests/MAuthWebApiTests.cs +++ b/tests/Medidata.MAuth.Tests/MAuthWebApiTests.cs @@ -8,17 +8,17 @@ namespace Medidata.MAuth.Tests { - public class MAuthWebApiTests + public static class MAuthWebApiTests { [Theory] [InlineData("GET")] [InlineData("DELETE")] [InlineData("POST")] [InlineData("PUT")] - public async Task MAuthAuthenticatingHandler_WithValidRequest_WillAuthenticate(string method) + public static async Task MAuthAuthenticatingHandler_WithValidRequest_WillAuthenticate(string method) { // Arrange - var testData = await TestData.For(method); + var testData = await method.FromResource(); var actual = new AssertSigningHandler(); var handler = new MAuthAuthenticatingHandler(new MAuthWebApiOptions() @@ -32,8 +32,7 @@ public async Task MAuthAuthenticatingHandler_WithValidRequest_WillAuthenticate(s using (var server = new HttpClient(handler)) { // Act - var response = await server.SendAsync( - await testData.Request.Sign(TestExtensions.ClientOptions(testData.SignedTime))); + var response = await server.SendAsync(testData.ToHttpRequestMessage()); // Assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); @@ -47,10 +46,10 @@ public async Task MAuthAuthenticatingHandler_WithValidRequest_WillAuthenticate(s [InlineData("DELETE")] [InlineData("POST")] [InlineData("PUT")] - public async Task MAuthAuthenticatingHandler_WithoutMAuthHeader_WillNotAuthenticate(string method) + public static async Task MAuthAuthenticatingHandler_WithoutMAuthHeader_WillNotAuthenticate(string method) { // Arrange - var testData = await TestData.For(method); + var testData = await method.FromResource(); var handler = new MAuthAuthenticatingHandler(new MAuthWebApiOptions() { @@ -63,7 +62,7 @@ public async Task MAuthAuthenticatingHandler_WithoutMAuthHeader_WillNotAuthentic using (var server = new HttpClient(handler)) { // Act - var response = await server.SendAsync(testData.Request); + var response = await server.SendAsync(new HttpRequestMessage(HttpMethod.Get, testData.Url)); // Assert Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); @@ -75,10 +74,10 @@ public async Task MAuthAuthenticatingHandler_WithoutMAuthHeader_WillNotAuthentic [InlineData("DELETE")] [InlineData("POST")] [InlineData("PUT")] - public async Task MAuthAuthenticatingHandler_WithEnabledExceptions_WillThrowException(string method) + public static async Task MAuthAuthenticatingHandler_WithEnabledExceptions_WillThrowException(string method) { // Arrange - var testData = await TestData.For(method); + var testData = await method.FromResource(); var handler = new MAuthAuthenticatingHandler(new MAuthWebApiOptions() { @@ -93,7 +92,7 @@ public async Task MAuthAuthenticatingHandler_WithEnabledExceptions_WillThrowExce { // Act, Assert var ex = await Assert.ThrowsAsync( - () => server.SendAsync(testData.Request)); + () => server.SendAsync(new HttpRequestMessage(HttpMethod.Get, testData.Url))); Assert.Equal("The request has invalid MAuth authentication headers.", ex.Message); Assert.NotNull(ex.InnerException); diff --git a/tests/Medidata.MAuth.Tests/Medidata.MAuth.Tests.csproj b/tests/Medidata.MAuth.Tests/Medidata.MAuth.Tests.csproj index 209daca..9c39df1 100644 --- a/tests/Medidata.MAuth.Tests/Medidata.MAuth.Tests.csproj +++ b/tests/Medidata.MAuth.Tests/Medidata.MAuth.Tests.csproj @@ -11,6 +11,13 @@ true + + + + + + + @@ -18,19 +25,11 @@ - - - - - - Always - - - Always - - - Always - + + + + + PreserveNewest @@ -62,6 +61,7 @@ + diff --git a/tests/Medidata.MAuth.Tests/Mocks/RequestData/DELETE.json b/tests/Medidata.MAuth.Tests/Mocks/RequestData/DELETE.json new file mode 100644 index 0000000..e674ac3 --- /dev/null +++ b/tests/Medidata.MAuth.Tests/Mocks/RequestData/DELETE.json @@ -0,0 +1,7 @@ +{ + "Url": "http://localhost:29999/", + "Method": "DELETE", + "ApplicationUuid": "192cce84-8466-490e-b03e-074f82da3ee2", + "SignedTime": "2016-08-01 05:40:38 +0000", + "Payload": "C6vv/XIurgTnbp3YMPcejteTrVfXtb3NY/2A9NFmiMh85uDQ9rnZr1fXPdmX5tQX2rUh5g3KT65ky3c4gi0/fwKJbFLCv+AoTtNl1jTwam4ZBp76/8pd1WSEnXBMyKu9qpCpnEhxQZLJkBTjmg1gyin4/r+slxDfktwSYPUkkeK41ewgwudI/t76qZOE9kX2VZpqHAgGBKRACbOpclmkdtMQ3Fbg/pSWrPN5ve34+TCNZbcqPI7E0dRfAzcAOD5DNftVcv2jKy3vJ68J0HnvdDIj03xVemjMRewDveD4OG4DGjP6HF4MouYy0QnbWIE+EVvUFRy81xhneTR10yDcYA==" +} \ No newline at end of file diff --git a/tests/Medidata.MAuth.Tests/Mocks/RequestData/GET.json b/tests/Medidata.MAuth.Tests/Mocks/RequestData/GET.json new file mode 100644 index 0000000..49f5f8f --- /dev/null +++ b/tests/Medidata.MAuth.Tests/Mocks/RequestData/GET.json @@ -0,0 +1,7 @@ +{ + "Url": "http://localhost:29999/", + "Method": "GET", + "ApplicationUuid": "192cce84-8466-490e-b03e-074f82da3ee2", + "SignedTime": "2016-08-01 03:22:47 +0000", + "Payload": "hg1RmUN/PNfiOpGRieEd77k9QnUluHag5UP7v/3azj8WHNmG9aHPZjPvwzDgCLCPFTthtaWOk5LSgHjQUcr/qWcg5o+Z+dbvzfbZpqkrwkzxrPLdzdZkulXSXNs+xEBFs1dQxLBL58jJ3BOvWPscWGYzd8IQThJ6rjNZiD+/lMGyDBm0BJgOHcBJ0AThywdEvOMXYQqR3daDM8OY2souleMzU1t0A1naq67TqTMAi5vEVCXvJ4AJhoNvrjATpzg/hM7ozXy91NgO0nVqJErcJBu3qX8UU4sqsQOP26ROTNHed/cBMdjzQZ/Bm/jMtWRtPmGozNzW12utRzh/Twzagg==" +} \ No newline at end of file diff --git a/tests/Medidata.MAuth.Tests/Mocks/RequestData/POST.json b/tests/Medidata.MAuth.Tests/Mocks/RequestData/POST.json new file mode 100644 index 0000000..b639f9a --- /dev/null +++ b/tests/Medidata.MAuth.Tests/Mocks/RequestData/POST.json @@ -0,0 +1,8 @@ +{ + "Url": "http://localhost:29999/", + "Method": "POST", + "ApplicationUuid": "192cce84-8466-490e-b03e-074f82da3ee2", + "SignedTime": "2016-08-01 03:31:54 +0000", + "Base64Content": "VGhlIHJlcXVlc3QgYm9keSBmb3IgdGhlIFBPU1QgbWVzc2FnZS4=", + "Payload": "cdsjH35jR0IR77riAxMkYOWT8ZNrZzlF336HM274sFvUwV57vZ0200/sO4f2NXkwru9iiLIDAoo7ZKI8atWt96cEGVXE+5EkN8BJa0iLkhaqZ9fEqj6F6YiB6QH6JJa2RiAW4xZmvFFVjjc6crxkk9MxB8qv/l2Ta08JMZg6npfjQG6OQ0DDPckkYWKHXq2f8dfwoWe/jhBBrzT9TdMmxO74GT/e5FffcBIQFVw6Cm1DBoQFETU61SMtI/4AS5hewGMbHjvCdIRzV7Wg3GDnLsNCXqk/pNV0vWLL+jXd4Zqx8VUhFDUGq7yn9ZjslBhkca80DoQmX7Zgd/4BGUzTxg==" +} \ No newline at end of file diff --git a/tests/Medidata.MAuth.Tests/Mocks/RequestData/POSTWithBinaryData.json b/tests/Medidata.MAuth.Tests/Mocks/RequestData/POSTWithBinaryData.json new file mode 100644 index 0000000..f551516 --- /dev/null +++ b/tests/Medidata.MAuth.Tests/Mocks/RequestData/POSTWithBinaryData.json @@ -0,0 +1,8 @@ +{ + "Url": "http://localhost:29999/", + "Method": "POST", + "ApplicationUuid": "192cce84-8466-490e-b03e-074f82da3ee2", + "SignedTime": "2018-10-02 08:21:03 +0000", + "Base64Content": "N3q8ryccAAPP2NhAnAoAAAAAAABUAAAAAAAAAJp51s8AJhvKRmda8ne4fYbYQdsFNc2DpXwSpQXbkL0vFNNxcpaoin2EVnGNaiKYq549w1XvzKXD3XbQa2rmXszZWApBl1bI/FsLDKGC0VHA+Y6actTa9q0WzOvPT7/aMG+3/N3IbuV6O9dsvLNbWeoADUnubbql0yh6JA15cgda8pWI/9o6LnMsEPHBctImUxDUvnAdxMll37Vx9jnjKVTZ3FUqN6kJ6LpZgYlX3pFsgT8ABjgdhg4dIE7xwUdom4LWsylukG/JYGNuCi58JLtx5H8I1mUgnjpXDSL1Z6xRSpypddIQjv+3MpHD5iQlYTkhfwmczvSQZG+aSkOk6A5BL67QV4ozo03RH2nP3QqTQnwEWhmyvWV5AQGWukryjLbhilhIaN7oqS/B9Jhve666xIhfg8Ev7F+lrHgvtue1cnbaCVFXuyZJs0jYfRds4wy6Ytkh8dE=", + "Payload": "pXO9EecWIU1Qf0diqYhTypEfSnT822YFviS4K0Jq3OfZjpDb1fL5b8ePDgD9BXLLM1Sp8+wh90RyE3QkMnfuQL1pHD+ODnPfglIQFvOAtuqVEVHN3ztQ4l8LZcPD1pX3PC+8Aj3WzgbCaMDg6trArkZKFNE2IWuwuLvaWGHfANBCfF/VVINAtZ8ZUSDJrYT9vkfdFvQDsEYDwtdlt9fY6EvhNRtILXXafchtk0c9eC3VC1jBlWwcK+v1OM3YKKEa9oqR9wv7bjxS2sBfkVA6Av4cm1O6uUCYJoxbrKtmfU6sBHhBW55B+NLLoNajfxU+quaaoxmX/x3KaTW3QFVUYQ==" +} \ No newline at end of file diff --git a/tests/Medidata.MAuth.Tests/Mocks/RequestData/PUT.json b/tests/Medidata.MAuth.Tests/Mocks/RequestData/PUT.json new file mode 100644 index 0000000..86dfcc2 --- /dev/null +++ b/tests/Medidata.MAuth.Tests/Mocks/RequestData/PUT.json @@ -0,0 +1,8 @@ +{ + "Url": "http://localhost:29999/", + "Method": "PUT", + "ApplicationUuid": "192cce84-8466-490e-b03e-074f82da3ee2", + "SignedTime": "2016-08-01 05:38:19 +0000", + "Base64Content": "VGhlIHJlcXVlc3QgYm9keSBmb3IgdGhlIFBVVCBtZXNzYWdlLg==", + "Payload": "h++GyB+btZfl0yRbhnIMqVJqytxFakYKpwvcVmI6ofTMSp5HjVSn54wwEVoCFEz1Esvc9rEwHlruavR1qxFSj7FBzwTM6eKiJywTSeNqDqf1SYmjppl7giz7KAGRY2bmxoyV0g63a5TncbbSmBKJSngYs1x1kskFILt8gDeEKHZHNxLqgPwXuzPpNUiwCvtxypIsC6YEHml59TRAXjsHJHC8HxxOWQW+io9Pb6w1adgI9nzekyxgQX8+LVZRn9mBLiux+6O5N5mY7V1yONeMifHwVhTMouyJDwGBda1/0E7IUlFv2wsxJIO4O/ulkwbk1XBECUdIe7ITtnrC6zY1Fg==" +} \ No newline at end of file diff --git a/tests/Medidata.MAuth.Tests/Mocks/Requests/DELETE.txt b/tests/Medidata.MAuth.Tests/Mocks/Requests/DELETE.txt deleted file mode 100644 index 83064de..0000000 --- a/tests/Medidata.MAuth.Tests/Mocks/Requests/DELETE.txt +++ /dev/null @@ -1,2 +0,0 @@ -C6vv/XIurgTnbp3YMPcejteTrVfXtb3NY/2A9NFmiMh85uDQ9rnZr1fXPdmX5tQX2rUh5g3KT65ky3c4gi0/fwKJbFLCv+AoTtNl1jTwam4ZBp76/8pd1WSEnXBMyKu9qpCpnEhxQZLJkBTjmg1gyin4/r+slxDfktwSYPUkkeK41ewgwudI/t76qZOE9kX2VZpqHAgGBKRACbOpclmkdtMQ3Fbg/pSWrPN5ve34+TCNZbcqPI7E0dRfAzcAOD5DNftVcv2jKy3vJ68J0HnvdDIj03xVemjMRewDveD4OG4DGjP6HF4MouYy0QnbWIE+EVvUFRy81xhneTR10yDcYA== -2016-08-01 5:40:38 +0000 \ No newline at end of file diff --git a/tests/Medidata.MAuth.Tests/Mocks/Requests/GET.txt b/tests/Medidata.MAuth.Tests/Mocks/Requests/GET.txt deleted file mode 100644 index 17f402c..0000000 --- a/tests/Medidata.MAuth.Tests/Mocks/Requests/GET.txt +++ /dev/null @@ -1,2 +0,0 @@ -hg1RmUN/PNfiOpGRieEd77k9QnUluHag5UP7v/3azj8WHNmG9aHPZjPvwzDgCLCPFTthtaWOk5LSgHjQUcr/qWcg5o+Z+dbvzfbZpqkrwkzxrPLdzdZkulXSXNs+xEBFs1dQxLBL58jJ3BOvWPscWGYzd8IQThJ6rjNZiD+/lMGyDBm0BJgOHcBJ0AThywdEvOMXYQqR3daDM8OY2souleMzU1t0A1naq67TqTMAi5vEVCXvJ4AJhoNvrjATpzg/hM7ozXy91NgO0nVqJErcJBu3qX8UU4sqsQOP26ROTNHed/cBMdjzQZ/Bm/jMtWRtPmGozNzW12utRzh/Twzagg== -2016-08-01 3:22:47 +0000 \ No newline at end of file diff --git a/tests/Medidata.MAuth.Tests/Mocks/Requests/POST.txt b/tests/Medidata.MAuth.Tests/Mocks/Requests/POST.txt deleted file mode 100644 index 7d4bc05..0000000 --- a/tests/Medidata.MAuth.Tests/Mocks/Requests/POST.txt +++ /dev/null @@ -1,3 +0,0 @@ -cdsjH35jR0IR77riAxMkYOWT8ZNrZzlF336HM274sFvUwV57vZ0200/sO4f2NXkwru9iiLIDAoo7ZKI8atWt96cEGVXE+5EkN8BJa0iLkhaqZ9fEqj6F6YiB6QH6JJa2RiAW4xZmvFFVjjc6crxkk9MxB8qv/l2Ta08JMZg6npfjQG6OQ0DDPckkYWKHXq2f8dfwoWe/jhBBrzT9TdMmxO74GT/e5FffcBIQFVw6Cm1DBoQFETU61SMtI/4AS5hewGMbHjvCdIRzV7Wg3GDnLsNCXqk/pNV0vWLL+jXd4Zqx8VUhFDUGq7yn9ZjslBhkca80DoQmX7Zgd/4BGUzTxg== -2016-08-01 3:31:54 +0000 -The request body for the POST message. \ No newline at end of file diff --git a/tests/Medidata.MAuth.Tests/Mocks/Requests/PUT.txt b/tests/Medidata.MAuth.Tests/Mocks/Requests/PUT.txt deleted file mode 100644 index 66cc82a..0000000 --- a/tests/Medidata.MAuth.Tests/Mocks/Requests/PUT.txt +++ /dev/null @@ -1,3 +0,0 @@ -h++GyB+btZfl0yRbhnIMqVJqytxFakYKpwvcVmI6ofTMSp5HjVSn54wwEVoCFEz1Esvc9rEwHlruavR1qxFSj7FBzwTM6eKiJywTSeNqDqf1SYmjppl7giz7KAGRY2bmxoyV0g63a5TncbbSmBKJSngYs1x1kskFILt8gDeEKHZHNxLqgPwXuzPpNUiwCvtxypIsC6YEHml59TRAXjsHJHC8HxxOWQW+io9Pb6w1adgI9nzekyxgQX8+LVZRn9mBLiux+6O5N5mY7V1yONeMifHwVhTMouyJDwGBda1/0E7IUlFv2wsxJIO4O/ulkwbk1XBECUdIe7ITtnrC6zY1Fg== -2016-08-01 5:38:19 +0000 -The request body for the PUT message. \ No newline at end of file diff --git a/tests/Medidata.MAuth.Tests/UtilityExtensionsTest.cs b/tests/Medidata.MAuth.Tests/UtilityExtensionsTest.cs index 4d67295..43d6d48 100644 --- a/tests/Medidata.MAuth.Tests/UtilityExtensionsTest.cs +++ b/tests/Medidata.MAuth.Tests/UtilityExtensionsTest.cs @@ -6,14 +6,14 @@ namespace Medidata.MAuth.Tests { - public class UtilityExtensionsTest + public static class UtilityExtensionsTest { [Fact] - public async Task TryParseAuthenticationHeader_WithValidAuthHeader_WillSucceed() + public static async Task TryParseAuthenticationHeader_WithValidAuthHeader_WillSucceed() { // Arrange - var request = await TestData.For("GET"); - var expected = (TestExtensions.ClientUuid, request.Payload); + var request = await "GET".FromResource(); + var expected = (request.ApplicationUuid, request.Payload); // Act var result = request.MAuthHeader.TryParseAuthenticationHeader(out var actual); @@ -24,7 +24,7 @@ public async Task TryParseAuthenticationHeader_WithValidAuthHeader_WillSucceed() } [Fact] - public void TryParseAuthenticationHeader_WithInvalidAuthHeader_WillFail() + public static void TryParseAuthenticationHeader_WithInvalidAuthHeader_WillFail() { // Arrange var invalid = "invalid"; @@ -37,7 +37,7 @@ public void TryParseAuthenticationHeader_WithInvalidAuthHeader_WillFail() } [Fact] - public void ParseAuthenticationHeader_WithInvalidAuthHeader_WillThrowException() + public static void ParseAuthenticationHeader_WithInvalidAuthHeader_WillThrowException() { // Arrange var invalid = "invalid"; From cf6831c65bdf2771d50c4a23a7f2600dd4d838e3 Mon Sep 17 00:00:00 2001 From: Laszlo Schreck Date: Wed, 3 Oct 2018 13:46:30 +0900 Subject: [PATCH 3/9] Bump up version --- version.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.props b/version.props index 152c914..6045642 100644 --- a/version.props +++ b/version.props @@ -1,6 +1,6 @@  - 3.0.3 + 3.0.4 From 8146b34b847c44e8f11d04cc1569776c8d703b7b Mon Sep 17 00:00:00 2001 From: Laszlo Schreck Date: Wed, 3 Oct 2018 14:02:48 +0900 Subject: [PATCH 4/9] Remove Task.Run() from Verify We don't gain too much by having it on a separate thread. --- src/Medidata.MAuth.Core/MAuthAuthenticator.cs | 2 +- src/Medidata.MAuth.Core/MAuthCoreExtensions.cs | 4 ++-- .../Medidata.MAuth.Tests/Infrastructure/MAuthServerHandler.cs | 2 +- tests/Medidata.MAuth.Tests/MAuthCoreExtensionsTests.cs | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Medidata.MAuth.Core/MAuthAuthenticator.cs b/src/Medidata.MAuth.Core/MAuthAuthenticator.cs index 527cd0b..c93ecc2 100644 --- a/src/Medidata.MAuth.Core/MAuthAuthenticator.cs +++ b/src/Medidata.MAuth.Core/MAuthAuthenticator.cs @@ -35,7 +35,7 @@ public async Task AuthenticateRequest(HttpRequestMessage request) var authInfo = request.GetAuthenticationInfo(); var appInfo = await GetApplicationInfo(authInfo.ApplicationUuid); - return await authInfo.Payload.Verify(await request.GetSignature(authInfo), appInfo.PublicKey); + return authInfo.Payload.Verify(await request.GetSignature(authInfo), appInfo.PublicKey); } catch (ArgumentException ex) { diff --git a/src/Medidata.MAuth.Core/MAuthCoreExtensions.cs b/src/Medidata.MAuth.Core/MAuthCoreExtensions.cs index e68ddb8..1a48dc5 100644 --- a/src/Medidata.MAuth.Core/MAuthCoreExtensions.cs +++ b/src/Medidata.MAuth.Core/MAuthCoreExtensions.cs @@ -54,13 +54,13 @@ public static async Task CalculatePayload( /// If the signed data matches the signature, it returns ; otherwise it /// returns . /// - public static Task Verify(this byte[] signedData, byte[] signature, string publicKey) + public static bool Verify(this byte[] signedData, byte[] signature, string publicKey) { Pkcs1Encoding.StrictLengthEnabled = false; var cipher = CipherUtilities.GetCipher("RSA/ECB/PKCS1Padding"); cipher.Init(false, publicKey.AsCipherParameters()); - return Task.Run(() => cipher.DoFinal(signedData).SequenceEqual(signature)); + return cipher.DoFinal(signedData).SequenceEqual(signature); } /// diff --git a/tests/Medidata.MAuth.Tests/Infrastructure/MAuthServerHandler.cs b/tests/Medidata.MAuth.Tests/Infrastructure/MAuthServerHandler.cs index 66bfee6..34e8876 100644 --- a/tests/Medidata.MAuth.Tests/Infrastructure/MAuthServerHandler.cs +++ b/tests/Medidata.MAuth.Tests/Infrastructure/MAuthServerHandler.cs @@ -25,7 +25,7 @@ protected override async Task SendAsync( var authInfo = request.GetAuthenticationInfo(); - if (!await authInfo.Payload.Verify( + if (!authInfo.Payload.Verify( await request.GetSignature(authInfo), TestExtensions.ServerPublicKey )) diff --git a/tests/Medidata.MAuth.Tests/MAuthCoreExtensionsTests.cs b/tests/Medidata.MAuth.Tests/MAuthCoreExtensionsTests.cs index f5113b0..96f2f81 100644 --- a/tests/Medidata.MAuth.Tests/MAuthCoreExtensionsTests.cs +++ b/tests/Medidata.MAuth.Tests/MAuthCoreExtensionsTests.cs @@ -37,7 +37,7 @@ public static async Task CalculatePayload_WithRequestAndAuthInfo_WillReturnCorre } [Fact] - public static async Task Verify_WithCorrectlySignedData_WillVerifyTheDataAsValid() + public static void Verify_WithCorrectlySignedData_WillVerifyTheDataAsValid() { // Arrange var signature = "This is a signature."; @@ -49,7 +49,7 @@ public static async Task Verify_WithCorrectlySignedData_WillVerifyTheDataAsValid var signedData = signer.ProcessBlock(unsignedData, 0, unsignedData.Length); // Act - var result = await signedData.Verify(Encoding.UTF8.GetBytes(signature), TestExtensions.ClientPublicKey); + var result = signedData.Verify(Encoding.UTF8.GetBytes(signature), TestExtensions.ClientPublicKey); // Assert Assert.True(result); From bcaf29048e743a64cbcb0fa94d70f0bc5142df95 Mon Sep 17 00:00:00 2001 From: Laszlo Schreck Date: Wed, 3 Oct 2018 15:28:01 +0900 Subject: [PATCH 5/9] Fix ASP.NET Core tests --- .../Infrastructure/TestExtensions.cs | 2 ++ tests/Medidata.MAuth.Tests/MAuthAspNetCoreTests.cs | 13 +++++++------ tests/Medidata.MAuth.Tests/MAuthOwinTests.cs | 6 ++++-- tests/Medidata.MAuth.Tests/MAuthWebApiTests.cs | 6 ++++-- 4 files changed, 17 insertions(+), 10 deletions(-) diff --git a/tests/Medidata.MAuth.Tests/Infrastructure/TestExtensions.cs b/tests/Medidata.MAuth.Tests/Infrastructure/TestExtensions.cs index d948788..fccf61a 100644 --- a/tests/Medidata.MAuth.Tests/Infrastructure/TestExtensions.cs +++ b/tests/Medidata.MAuth.Tests/Infrastructure/TestExtensions.cs @@ -87,5 +87,7 @@ public static HttpRequestMessage ToHttpRequestMessage(this RequestData data) public static string ToStringContent(this string base64Content) => base64Content == null ? null : Encoding.UTF8.GetString(Convert.FromBase64String(base64Content)); + + public static HttpMethod ToHttpMethod(this string method) => new HttpMethod(method); } } diff --git a/tests/Medidata.MAuth.Tests/MAuthAspNetCoreTests.cs b/tests/Medidata.MAuth.Tests/MAuthAspNetCoreTests.cs index d2ab9be..1d1a95c 100644 --- a/tests/Medidata.MAuth.Tests/MAuthAspNetCoreTests.cs +++ b/tests/Medidata.MAuth.Tests/MAuthAspNetCoreTests.cs @@ -1,5 +1,6 @@ using System.IO; using System.Net; +using System.Net.Http; using System.Threading.Tasks; using Medidata.MAuth.AspNetCore; using Medidata.MAuth.Core; @@ -38,8 +39,7 @@ public async Task MAuthMiddleware_WithValidRequest_WillAuthenticate(string metho }))) { // Act - var response = await server.CreateClient().SendAsync( - await testData.ToHttpRequestMessage().Sign(TestExtensions.ClientOptions(testData.SignedTime))); + var response = await server.CreateClient().SendAsync(testData.ToHttpRequestMessage()); // Assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); @@ -70,7 +70,8 @@ public async Task MAuthMiddleware_WithoutMAuthHeader_WillNotAuthenticate(string }))) { // Act - var response = await server.CreateClient().SendAsync(testData.ToHttpRequestMessage()); + var response = await server.CreateClient().SendAsync( + new HttpRequestMessage(testData.Method.ToHttpMethod(), testData.Url)); // Assert Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); @@ -101,7 +102,8 @@ public async Task MAuthMiddleware_WithEnabledExceptions_WillThrowException(strin { // Act, Assert var ex = await Assert.ThrowsAsync( - () => server.CreateClient().SendAsync(testData.ToHttpRequestMessage())); + () => server.CreateClient().SendAsync( + new HttpRequestMessage(testData.Method.ToHttpMethod(), testData.Url))); Assert.Equal("The request has invalid MAuth authentication headers.", ex.Message); Assert.NotNull(ex.InnerException); @@ -139,8 +141,7 @@ public async Task MAuthMiddleware_WithNonSeekableBodyStream_WillRestoreBodyStrea }))) { // Act - var response = await server.CreateClient().SendAsync( - await testData.ToHttpRequestMessage().Sign(TestExtensions.ClientOptions(testData.SignedTime))); + var response = await server.CreateClient().SendAsync(testData.ToHttpRequestMessage()); // Assert Assert.True(canSeek); diff --git a/tests/Medidata.MAuth.Tests/MAuthOwinTests.cs b/tests/Medidata.MAuth.Tests/MAuthOwinTests.cs index 8795587..33863d1 100644 --- a/tests/Medidata.MAuth.Tests/MAuthOwinTests.cs +++ b/tests/Medidata.MAuth.Tests/MAuthOwinTests.cs @@ -69,7 +69,8 @@ public static async Task MAuthMiddleware_WithoutMAuthHeader_WillNotAuthenticate( })) { // Act - var response = await server.HttpClient.SendAsync(new HttpRequestMessage(HttpMethod.Get, testData.Url)); + var response = await server.HttpClient.SendAsync( + new HttpRequestMessage(testData.Method.ToHttpMethod(), testData.Url)); // Assert Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); @@ -102,7 +103,8 @@ public static async Task MAuthMiddleware_WithEnabledExceptions_WillThrowExceptio { // Act, Assert var ex = await Assert.ThrowsAsync( - () => server.HttpClient.SendAsync(new HttpRequestMessage(HttpMethod.Get, testData.Url))); + () => server.HttpClient.SendAsync( + new HttpRequestMessage(testData.Method.ToHttpMethod(), testData.Url))); Assert.Equal("The request has invalid MAuth authentication headers.", ex.Message); Assert.NotNull(ex.InnerException); diff --git a/tests/Medidata.MAuth.Tests/MAuthWebApiTests.cs b/tests/Medidata.MAuth.Tests/MAuthWebApiTests.cs index a8927a7..4004b0b 100644 --- a/tests/Medidata.MAuth.Tests/MAuthWebApiTests.cs +++ b/tests/Medidata.MAuth.Tests/MAuthWebApiTests.cs @@ -62,7 +62,8 @@ public static async Task MAuthAuthenticatingHandler_WithoutMAuthHeader_WillNotAu using (var server = new HttpClient(handler)) { // Act - var response = await server.SendAsync(new HttpRequestMessage(HttpMethod.Get, testData.Url)); + var response = await server.SendAsync( + new HttpRequestMessage(testData.Method.ToHttpMethod(), testData.Url)); // Assert Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); @@ -92,7 +93,8 @@ public static async Task MAuthAuthenticatingHandler_WithEnabledExceptions_WillTh { // Act, Assert var ex = await Assert.ThrowsAsync( - () => server.SendAsync(new HttpRequestMessage(HttpMethod.Get, testData.Url))); + () => server.SendAsync( + new HttpRequestMessage(testData.Method.ToHttpMethod(), testData.Url))); Assert.Equal("The request has invalid MAuth authentication headers.", ex.Message); Assert.NotNull(ex.InnerException); From cdd9f59e3ee764ad6737583ede428956c2504060 Mon Sep 17 00:00:00 2001 From: Laszlo Schreck Date: Wed, 3 Oct 2018 15:33:51 +0900 Subject: [PATCH 6/9] Update with v3.0.4 --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a317e8..5f2f621 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # Changes in Medidata.MAuth +## v3.0.4 +- **[Core]** Fixed an issue with HTTP requests having binary content (the authentication was failing in this case) + ## v3.0.3 - **[Core]** Fixed concurrency and memory issues with the `MAuthRequestRetrier` From bd78b06245d5c83a2ac2225fb732bde6fb36a649 Mon Sep 17 00:00:00 2001 From: Laszlo Schreck Date: Wed, 3 Oct 2018 17:36:31 +0900 Subject: [PATCH 7/9] Clarify the test --- tests/Medidata.MAuth.Tests/MAuthCoreExtensionsTests.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/Medidata.MAuth.Tests/MAuthCoreExtensionsTests.cs b/tests/Medidata.MAuth.Tests/MAuthCoreExtensionsTests.cs index 96f2f81..15f8fa5 100644 --- a/tests/Medidata.MAuth.Tests/MAuthCoreExtensionsTests.cs +++ b/tests/Medidata.MAuth.Tests/MAuthCoreExtensionsTests.cs @@ -66,9 +66,11 @@ public static async Task GetSignature_WithRequest_WillReturnTheCorrectSignature( var testData = await method.FromResource(); var expectedSignature = - ($"{method}\n/\n{testData.Base64Content.ToStringContent()}\n" + + ($"{testData.Method}\n" + + $"{testData.Url.AbsolutePath}\n" + + $"{testData.Base64Content.ToStringContent()}\n" + $"{testData.ApplicationUuidString}\n" + - $"{testData.SignedTime.ToUnixTimeSeconds()}") + $"{testData.SignedTimeUnixSeconds}") .AsSHA512Hash(); var authInfo = new PrivateKeyAuthenticationInfo() From 69dac850ca9fff81d2798a3752e8c7301610c7ce Mon Sep 17 00:00:00 2001 From: Laszlo Schreck Date: Fri, 5 Oct 2018 15:12:24 +0900 Subject: [PATCH 8/9] Restore constants and other refactoring --- .../MAuthCoreExtensions.cs | 30 ++++++++----------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/src/Medidata.MAuth.Core/MAuthCoreExtensions.cs b/src/Medidata.MAuth.Core/MAuthCoreExtensions.cs index 1a48dc5..3217da7 100644 --- a/src/Medidata.MAuth.Core/MAuthCoreExtensions.cs +++ b/src/Medidata.MAuth.Core/MAuthCoreExtensions.cs @@ -8,7 +8,6 @@ using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; -using static Medidata.MAuth.Core.Constants; using Newtonsoft.Json.Linq; using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Encodings; @@ -76,10 +75,11 @@ public static bool Verify(this byte[] signedData, byte[] signature, string publi public static async Task GetSignature(this HttpRequestMessage request, AuthenticationInfo authInfo) => new byte[][] { - request.Method.Method.ToBytes(), NewLine, - request.RequestUri.AbsolutePath.ToBytes(), NewLine, - (request.Content != null ? await request.Content.ReadAsByteArrayAsync() : new byte[] { }), NewLine, - authInfo.ApplicationUuid.ToHyphenString().ToBytes(), NewLine, + request.Method.Method.ToBytes(), Constants.NewLine, + request.RequestUri.AbsolutePath.ToBytes(), Constants.NewLine, + (request.Content != null ? await request.Content.ReadAsByteArrayAsync() : new byte[] { }), + Constants.NewLine, + authInfo.ApplicationUuid.ToHyphenString().ToBytes(), Constants.NewLine, authInfo.SignedTime.ToUnixTimeSeconds().ToString().ToBytes() } .Concat() @@ -129,8 +129,8 @@ public async static Task AddAuthenticationInfo( $"MWS {authInfo.ApplicationUuid.ToHyphenString()}:" + $"{await request.CalculatePayload(authInfo)}"; - request.Headers.Add(MAuthHeaderKey, authHeader); - request.Headers.Add(MAuthTimeHeaderKey, authInfo.SignedTime.ToUnixTimeSeconds().ToString()); + request.Headers.Add(Constants.MAuthHeaderKey, authHeader); + request.Headers.Add(Constants.MAuthTimeHeaderKey, authInfo.SignedTime.ToUnixTimeSeconds().ToString()); return request; } @@ -170,7 +170,7 @@ public async static Task FromResponse(this HttpContent content) /// The date and time to be converted. /// The total seconds elapsed from the Unix epoch (1970-01-01 00:00:00). public static long ToUnixTimeSeconds(this DateTimeOffset value) => - (long)(value - UnixEpoch).TotalSeconds; + (long)(value - Constants.UnixEpoch).TotalSeconds; /// /// Converts a value that is a Unix time in seconds to a UTC . @@ -178,7 +178,7 @@ public static long ToUnixTimeSeconds(this DateTimeOffset value) => /// The Unix time seconds to be converted. /// The equivalent of the Unix time. public static DateTimeOffset FromUnixTimeSeconds(this long value) => - UnixEpoch.AddSeconds(value); + Constants.UnixEpoch.AddSeconds(value); /// @@ -197,14 +197,10 @@ public static string ToHyphenString(this Guid uuid) => /// The collection of the HTTP headers to search in. /// The key to search in the headers collection. /// The value if found; otherwise a default value for the given type. - public static TValue GetFirstValueOrDefault(this HttpHeaders headers, string key) - { - IEnumerable values; - - return headers.TryGetValues(key, out values) ? + public static TValue GetFirstValueOrDefault(this HttpHeaders headers, string key) => + headers.TryGetValues(key, out IEnumerable values) ? (TValue)Convert.ChangeType(values.First(), typeof(TValue)) : default(TValue); - } /// /// Provides an SHA512 hash value of a string. @@ -264,10 +260,10 @@ private static string RemoveLineBreaks(this string key) => key.Replace("\r", string.Empty).Replace("\n", string.Empty); private static string InsertLineBreakAfterBegin(this string key) => - Regex.Replace(key, KeyNormalizeLinesStartRegexPattern, "${begin}\n"); + Regex.Replace(key, Constants.KeyNormalizeLinesStartRegexPattern, "${begin}\n"); private static string InsertLineBreakBeforeEnd(this string key) => - Regex.Replace(key, KeyNormalizeLinesEndRegexPattern, "\n${end}"); + Regex.Replace(key, Constants.KeyNormalizeLinesEndRegexPattern, "\n${end}"); private static byte[] ToBytes(this string value) => Encoding.UTF8.GetBytes(value); From 44be350a92bc60e1fa0ecc9c138082f54b256bdc Mon Sep 17 00:00:00 2001 From: Laszlo Schreck Date: Fri, 5 Oct 2018 15:16:54 +0900 Subject: [PATCH 9/9] Optimize hash methods --- src/Medidata.MAuth.Core/MAuthCoreExtensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Medidata.MAuth.Core/MAuthCoreExtensions.cs b/src/Medidata.MAuth.Core/MAuthCoreExtensions.cs index 3217da7..86a35fd 100644 --- a/src/Medidata.MAuth.Core/MAuthCoreExtensions.cs +++ b/src/Medidata.MAuth.Core/MAuthCoreExtensions.cs @@ -208,7 +208,7 @@ public static TValue GetFirstValueOrDefault(this HttpHeaders headers, st /// The value for calculating the hash. /// The SHA512 hash of the input value as a hex-encoded byte array. public static byte[] AsSHA512Hash(this string value) => - Hex.Encode(SHA512.Create().ComputeHash(Encoding.UTF8.GetBytes(value))); + AsSHA512Hash(Encoding.UTF8.GetBytes(value)); public static byte[] AsSHA512Hash(this byte[] value) => Hex.Encode(SHA512.Create().ComputeHash(value));