From 5356ab0d7f74128d8fb8067225ded81f3ffdd0d4 Mon Sep 17 00:00:00 2001 From: Prajon Date: Tue, 19 Nov 2019 14:23:05 -0500 Subject: [PATCH 01/10] Fix texts in readme which was out of date --- README.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index d35bd4a..f1c7823 100644 --- a/README.md +++ b/README.md @@ -125,9 +125,8 @@ public async Task SignAndSendRequest(HttpRequestMessage req } } ``` -With the MAuth V2 protocol, there are two new options `MAuthVersion` and `DisableV1` added for Signing MAuth request. -`MAuthVersion` is passed either as `MAuthVersion.MWSV2` for signing with V2 protocol or `MAuthVersion.MWS` for continue -signing with V1 protocol. By default, `DisableV1` option is set to false (if not included). When we are ready to +With the release of support for MAuth V2 protocol, by default MAuth request signs with both V1 and V2 protocol. +Also by default, `DisableV1` option is set to false (if not included). When we are ready to disable all the V1 request, then we need to include this disable option as : `DisableV1 = true`. Signing with V2 protocol supports query string. @@ -140,8 +139,7 @@ The `MAuthSigningOptions` has the following properties to determine the required | ---- | ----------- | | **ApplicationUuid** | Determines the unique identifier of the client application used for the MAuth service authentication requests. This uuid needs to be registered with the MAuth Server in order for the authenticating server application to be able to authenticate the signed request. | | **PrivateKey** | Determines the RSA private key of the client for signing a request. This key must be in a PEM ASN.1 format. The value of this property can be set as a valid path to a readable key file as well. | -| **MAuthVersion** | Determines the MAuth version of the request used for signing. This is enumeration value which is `MAuthVersion.MWSV2` for V2 requests. | -| **DisableV1** | Determines the boolean value which controls whether to disable the signing requests with `MAuthVersion.MWS` requests or not. If not supplied, this value is `false`. | +| **DisableV1** | Determines the boolean value which controls whether to disable the signing requests with V1 protocol or not. If not supplied, this value is `false`. | ### Authenticating Incoming Requests with the OWIN and ASP.NET Core Middlewares From 08db2de326c4968c1e11387fec1f62317ebd4129 Mon Sep 17 00:00:00 2001 From: Prajon Date: Fri, 6 Dec 2019 15:31:51 -0500 Subject: [PATCH 02/10] Refactor log message to same as ruby, java and python --- src/Medidata.MAuth.Core/MAuthAuthenticator.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Medidata.MAuth.Core/MAuthAuthenticator.cs b/src/Medidata.MAuth.Core/MAuthAuthenticator.cs index e20b1b7..251ef6d 100644 --- a/src/Medidata.MAuth.Core/MAuthAuthenticator.cs +++ b/src/Medidata.MAuth.Core/MAuthAuthenticator.cs @@ -45,13 +45,15 @@ public async Task AuthenticateRequest(HttpRequestMessage request) logger.LogInformation("Initiating Authentication of the request."); var version = request.GetAuthHeaderValue().GetVersionFromAuthenticationHeader(); - logger.LogInformation("Authentication is for the {version}.",version); - if (options.DisableV1 && version == MAuthVersion.MWS) throw new InvalidVersionException($"Authentication with {version} version is disabled."); var mAuthCore = MAuthCoreFactory.Instantiate(version); var authInfo = GetAuthenticationInfo(request, version); + var logMessage = "Mauth-client attempting to authenticate request from app with mauth app uuid" + + $" {authInfo.ApplicationUuid} using version {version}"; + logger.LogInformation(logMessage); + var appInfo = await GetApplicationInfo(authInfo.ApplicationUuid, version).ConfigureAwait(false); var signature = await mAuthCore.GetSignature(request, authInfo).ConfigureAwait(false); From a039bea549c47fef63855625fdaab61929ac3f02 Mon Sep 17 00:00:00 2001 From: Prajon Date: Fri, 6 Dec 2019 15:42:36 -0500 Subject: [PATCH 03/10] Removing commented code --- tests/Medidata.MAuth.Tests/MAuthAuthenticatorTests.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tests/Medidata.MAuth.Tests/MAuthAuthenticatorTests.cs b/tests/Medidata.MAuth.Tests/MAuthAuthenticatorTests.cs index 01ecfec..1737bbf 100644 --- a/tests/Medidata.MAuth.Tests/MAuthAuthenticatorTests.cs +++ b/tests/Medidata.MAuth.Tests/MAuthAuthenticatorTests.cs @@ -41,11 +41,6 @@ public static async Task AuthenticateRequest_WithValidMWSRequest_WillAuthenticat { // Arrange var testData = await method.FromResource(); - - //var testOptions = TestExtensions.ServerOptions; - //testOptions.MAuthServerHandler = new MAuthServerHandler() - // { AuthenticateOnlyV1 = true }; - var authenticator = new MAuthAuthenticator(TestExtensions.ServerOptions, NullLogger.Instance); var mAuthCore = new MAuthCore(); From e7c4990b543bd5265d61a5e9006dfb8d595fdd8c Mon Sep 17 00:00:00 2001 From: Prajon Date: Thu, 5 Dec 2019 16:14:06 -0500 Subject: [PATCH 04/10] Update aspnetcore version to 2.1 LTS fix mix-match of versions --- CHANGELOG.md | 3 +++ README.md | 2 +- .../Medidata.MAuth.AspNetCore.csproj | 8 ++++---- tests/Medidata.MAuth.Tests/Medidata.MAuth.Tests.csproj | 10 +++++----- version.props | 2 +- 5 files changed, 14 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0914269..6ad36ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # Changes in Medidata.MAuth +## v4.0.2 +- **[AspNetCore]** Update aspnetcore version to aspnetcore2.1 LTS. + ## v4.0.1 - **[Core]** Fixed default sigining with both MWS and MWSV2 instead of option selected by consuming application. - **[Core]** Fixed an issue related to token request path which is same for both MWS and MWSV2 protocol. diff --git a/README.md b/README.md index f1c7823..182bd2d 100644 --- a/README.md +++ b/README.md @@ -317,7 +317,7 @@ in your project in order to make Medidata.MAuth work for you. ##### Is there an .NET Standard/Core support? Yes, for signing outgoing requests you can use the library with any framework which implements -the **.NET Standard 2.0** and onwards; additionally we support the **ASP.NET Core App 2.0** and onwards with a middleware +the **.NET Standard 2.0** and onwards; additionally we support the **ASP.NET Core App 2.1** and onwards with a middleware for authenticating the incoming requests. ##### What Cryptographic provider is used for the encryption/decryption? diff --git a/src/Medidata.MAuth.AspNetCore/Medidata.MAuth.AspNetCore.csproj b/src/Medidata.MAuth.AspNetCore/Medidata.MAuth.AspNetCore.csproj index ed52a73..d17e2de 100644 --- a/src/Medidata.MAuth.AspNetCore/Medidata.MAuth.AspNetCore.csproj +++ b/src/Medidata.MAuth.AspNetCore/Medidata.MAuth.AspNetCore.csproj @@ -2,7 +2,7 @@ - netcoreapp2.0 + netcoreapp2.1 This package contains an ASP.NET Core middleware to validate signed http requests with the Medidata MAuth protocol. The middleware communicates with an MAuth server in order to confirm the validity of the request authentication header. Include this package in your ASP.NET Core web api if you want to authenticate the api requests signed with the MAuth protocol. Medidata.MAuth.AspNetCore Medidata.MAuth.AspNetCore @@ -14,9 +14,9 @@ all runtime; build; native; contentfiles; analyzers - - - + + + diff --git a/tests/Medidata.MAuth.Tests/Medidata.MAuth.Tests.csproj b/tests/Medidata.MAuth.Tests/Medidata.MAuth.Tests.csproj index 53d5bf3..f704377 100644 --- a/tests/Medidata.MAuth.Tests/Medidata.MAuth.Tests.csproj +++ b/tests/Medidata.MAuth.Tests/Medidata.MAuth.Tests.csproj @@ -5,7 +5,7 @@ Copyright © Medidata Solutions, Inc. 2017 Medidata.MAuth.Tests Medidata Solutions, Inc. - net461;netcoreapp2.0 + net461;netcoreapp2.1 Medidata.MAuth.Tests Medidata.MAuth.Tests true @@ -60,16 +60,16 @@ - + - - + + - + diff --git a/version.props b/version.props index 4716aab..3891445 100644 --- a/version.props +++ b/version.props @@ -1,6 +1,6 @@  - 4.0.1 + 4.0.2 From d01096d91794d7caa0184eb2c80fc394f1bffd05 Mon Sep 17 00:00:00 2001 From: Prajon Date: Tue, 10 Dec 2019 19:10:24 -0500 Subject: [PATCH 05/10] Update "MEL" library to "2.1." to remove any dependency on "netcore 2.2". -ALso remove "MEL.Logging" and "MEL.Debug" which are not used --- src/Medidata.MAuth.Core/Medidata.MAuth.Core.csproj | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Medidata.MAuth.Core/Medidata.MAuth.Core.csproj b/src/Medidata.MAuth.Core/Medidata.MAuth.Core.csproj index acbc03e..8707773 100644 --- a/src/Medidata.MAuth.Core/Medidata.MAuth.Core.csproj +++ b/src/Medidata.MAuth.Core/Medidata.MAuth.Core.csproj @@ -15,9 +15,7 @@ runtime; build; native; contentfiles; analyzers - - - + From 441231607db38ee8a1d2e00fbaac6457e1a1e9a0 Mon Sep 17 00:00:00 2001 From: Prajon Date: Fri, 17 Jan 2020 11:16:22 -0500 Subject: [PATCH 06/10] Added logic to fall back to V1 authentication when V2 authentication fails --- CHANGELOG.md | 1 + src/Medidata.MAuth.Core/MAuthAuthenticator.cs | 31 +++++++---- .../MAuthRequestRetrier.cs | 3 +- .../MAuthAuthenticatorTests.cs | 51 +++++++++++++++++++ .../Medidata.MAuth.Tests.csproj | 1 + 5 files changed, 75 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ad36ce..336b97a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## v4.0.2 - **[AspNetCore]** Update aspnetcore version to aspnetcore2.1 LTS. +- **[Core]** Fallback to V1 protocol when V2 athentication fails. ## v4.0.1 - **[Core]** Fixed default sigining with both MWS and MWSV2 instead of option selected by consuming application. diff --git a/src/Medidata.MAuth.Core/MAuthAuthenticator.cs b/src/Medidata.MAuth.Core/MAuthAuthenticator.cs index 251ef6d..c1abb47 100644 --- a/src/Medidata.MAuth.Core/MAuthAuthenticator.cs +++ b/src/Medidata.MAuth.Core/MAuthAuthenticator.cs @@ -48,16 +48,17 @@ public async Task AuthenticateRequest(HttpRequestMessage request) if (options.DisableV1 && version == MAuthVersion.MWS) throw new InvalidVersionException($"Authentication with {version} version is disabled."); - var mAuthCore = MAuthCoreFactory.Instantiate(version); - var authInfo = GetAuthenticationInfo(request, version); var logMessage = "Mauth-client attempting to authenticate request from app with mauth app uuid" + - $" {authInfo.ApplicationUuid} using version {version}"; + $" {options.ApplicationUuid} using version {version}"; logger.LogInformation(logMessage); - - var appInfo = await GetApplicationInfo(authInfo.ApplicationUuid, version).ConfigureAwait(false); - var signature = await mAuthCore.GetSignature(request, authInfo).ConfigureAwait(false); - - return mAuthCore.Verify(authInfo.Payload, signature, appInfo.PublicKey); + var authenticated = await Authenticate(request, version).ConfigureAwait(false); + if (version == MAuthVersion.MWSV2 && !authenticated && !options.DisableV1) + { + // fall back to V1 authentication + authenticated = await Authenticate(request, MAuthVersion.MWS).ConfigureAwait(false); + logger.LogWarning("Completed successful authentication attempt after fallback to v1"); + } + return authenticated; } catch (ArgumentException ex) { @@ -91,10 +92,20 @@ public async Task AuthenticateRequest(HttpRequestMessage request) } } - private Task GetApplicationInfo(Guid applicationUuid, MAuthVersion version) => + private async Task Authenticate(HttpRequestMessage request, MAuthVersion version) + { + var authInfo = GetAuthenticationInfo(request, version); + var appInfo = await GetApplicationInfo(authInfo.ApplicationUuid).ConfigureAwait(false); + + var mAuthCore = MAuthCoreFactory.Instantiate(version); + var signature = await mAuthCore.GetSignature(request, authInfo).ConfigureAwait(false); + return mAuthCore.Verify(authInfo.Payload, signature, appInfo.PublicKey); + } + + private Task GetApplicationInfo(Guid applicationUuid) => cache.GetOrCreateAsync(applicationUuid, async entry => { - var retrier = new MAuthRequestRetrier(options, version); + var retrier = new MAuthRequestRetrier(options); var response = await retrier.GetSuccessfulResponse( applicationUuid, CreateRequest, diff --git a/src/Medidata.MAuth.Core/MAuthRequestRetrier.cs b/src/Medidata.MAuth.Core/MAuthRequestRetrier.cs index ac60a3a..bac3f16 100644 --- a/src/Medidata.MAuth.Core/MAuthRequestRetrier.cs +++ b/src/Medidata.MAuth.Core/MAuthRequestRetrier.cs @@ -1,7 +1,6 @@ using System; using System.Net.Http; using System.Threading.Tasks; -using Medidata.MAuth.Core.Models; namespace Medidata.MAuth.Core { @@ -9,7 +8,7 @@ internal class MAuthRequestRetrier { private readonly HttpClient client; - public MAuthRequestRetrier(MAuthOptionsBase options, MAuthVersion version) + public MAuthRequestRetrier(MAuthOptionsBase options) { var signingHandler = new MAuthSigningHandler(options: new MAuthSigningOptions() { diff --git a/tests/Medidata.MAuth.Tests/MAuthAuthenticatorTests.cs b/tests/Medidata.MAuth.Tests/MAuthAuthenticatorTests.cs index 1737bbf..d89a620 100644 --- a/tests/Medidata.MAuth.Tests/MAuthAuthenticatorTests.cs +++ b/tests/Medidata.MAuth.Tests/MAuthAuthenticatorTests.cs @@ -6,7 +6,10 @@ using Medidata.MAuth.Core.Exceptions; using Medidata.MAuth.Core.Models; using Medidata.MAuth.Tests.Infrastructure; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Logging.Internal; +using Moq; using Xunit; namespace Medidata.MAuth.Tests @@ -340,5 +343,53 @@ public static async Task GetAuthenticationInfo_WithSignedRequest_ForMWSVersion_W Assert.Equal(Convert.FromBase64String(testData.Payload), actual.Payload); Assert.Equal(testData.SignedTime, actual.SignedTime); } + + [Fact] + public static async Task AuthenticateRequest_WithDefaultRequest_WhenV2Fails_FallBackToV1AndAuthenticate() + { + // Arrange + var testData = await "GET".FromResource(); + var mockLogger = new Mock(); + + var authenticator = new MAuthAuthenticator(TestExtensions.ServerOptions, mockLogger.Object); + var requestData = testData.ToDefaultHttpRequestMessage(); + + // Act + var isAuthenticated = await authenticator.AuthenticateRequest(requestData); + + // Assert + Assert.True(isAuthenticated); + mockLogger.Verify(x => x.Log( + LogLevel.Warning, It.IsAny(), + It.Is(v => v.ToString() + .Contains("Completed successful authentication attempt after fallback to v1")), + It.IsAny(), It.IsAny>() + )); + } + + [Fact] + public static async Task AuthenticateRequest_WithDefaultRequest_AndDisableV1_WhenV2Fails_NotFallBackToV1() + { + // Arrange + var testData = await "GET".FromResource(); + var mockLogger = new Mock(); + var testOptions = TestExtensions.ServerOptions; + testOptions.DisableV1 = true; + + var authenticator = new MAuthAuthenticator(testOptions, mockLogger.Object); + var requestData = testData.ToDefaultHttpRequestMessage(); + + // Act + var isAuthenticated = await authenticator.AuthenticateRequest(requestData); + + // Assert + Assert.False(isAuthenticated); + mockLogger.Verify(x => x.Log( + LogLevel.Warning, It.IsAny(), + It.Is(v => v.ToString() + .Contains("Completed successful authentication attempt after fallback to v1")), + It.IsAny(), It.IsAny>() + ), Times.Never); + } } } diff --git a/tests/Medidata.MAuth.Tests/Medidata.MAuth.Tests.csproj b/tests/Medidata.MAuth.Tests/Medidata.MAuth.Tests.csproj index f704377..d0b83dc 100644 --- a/tests/Medidata.MAuth.Tests/Medidata.MAuth.Tests.csproj +++ b/tests/Medidata.MAuth.Tests/Medidata.MAuth.Tests.csproj @@ -71,6 +71,7 @@ + all From 2237d5b4b30ea17b7e6794ab0dd2758875d2e64e Mon Sep 17 00:00:00 2001 From: Prajon Date: Fri, 17 Jan 2020 15:22:01 -0500 Subject: [PATCH 07/10] Updated nits feedback --- src/Medidata.MAuth.Core/MAuthAuthenticator.cs | 4 ++-- tests/Medidata.MAuth.Tests/MAuthAuthenticatorTests.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Medidata.MAuth.Core/MAuthAuthenticator.cs b/src/Medidata.MAuth.Core/MAuthAuthenticator.cs index c1abb47..97c342a 100644 --- a/src/Medidata.MAuth.Core/MAuthAuthenticator.cs +++ b/src/Medidata.MAuth.Core/MAuthAuthenticator.cs @@ -52,11 +52,11 @@ public async Task AuthenticateRequest(HttpRequestMessage request) $" {options.ApplicationUuid} using version {version}"; logger.LogInformation(logMessage); var authenticated = await Authenticate(request, version).ConfigureAwait(false); - if (version == MAuthVersion.MWSV2 && !authenticated && !options.DisableV1) + if (!authenticated && version == MAuthVersion.MWSV2 && !options.DisableV1) { // fall back to V1 authentication authenticated = await Authenticate(request, MAuthVersion.MWS).ConfigureAwait(false); - logger.LogWarning("Completed successful authentication attempt after fallback to v1"); + logger.LogWarning("Completed successful authentication attempt after fallback to V1"); } return authenticated; } diff --git a/tests/Medidata.MAuth.Tests/MAuthAuthenticatorTests.cs b/tests/Medidata.MAuth.Tests/MAuthAuthenticatorTests.cs index d89a620..89a95cc 100644 --- a/tests/Medidata.MAuth.Tests/MAuthAuthenticatorTests.cs +++ b/tests/Medidata.MAuth.Tests/MAuthAuthenticatorTests.cs @@ -362,7 +362,7 @@ public static async Task AuthenticateRequest_WithDefaultRequest_WhenV2Fails_Fall mockLogger.Verify(x => x.Log( LogLevel.Warning, It.IsAny(), It.Is(v => v.ToString() - .Contains("Completed successful authentication attempt after fallback to v1")), + .Contains("Completed successful authentication attempt after fallback to V1")), It.IsAny(), It.IsAny>() )); } @@ -387,7 +387,7 @@ public static async Task AuthenticateRequest_WithDefaultRequest_AndDisableV1_Whe mockLogger.Verify(x => x.Log( LogLevel.Warning, It.IsAny(), It.Is(v => v.ToString() - .Contains("Completed successful authentication attempt after fallback to v1")), + .Contains("Completed successful authentication attempt after fallback to V1")), It.IsAny(), It.IsAny>() ), Times.Never); } From ca180f3a792d10f241fad79db105bcc2f61fbfb3 Mon Sep 17 00:00:00 2001 From: Prajon Date: Fri, 17 Jan 2020 15:37:21 -0500 Subject: [PATCH 08/10] Updated to to pass mAuthCore instantiation instead of version to GetAuthenticationInfo(..) method --- src/Medidata.MAuth.Core/MAuthAuthenticator.cs | 9 ++++----- .../Infrastructure/MAuthServerHandler.cs | 2 +- tests/Medidata.MAuth.Tests/MAuthAuthenticatorTests.cs | 6 ++++-- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/Medidata.MAuth.Core/MAuthAuthenticator.cs b/src/Medidata.MAuth.Core/MAuthAuthenticator.cs index 97c342a..ff6a42a 100644 --- a/src/Medidata.MAuth.Core/MAuthAuthenticator.cs +++ b/src/Medidata.MAuth.Core/MAuthAuthenticator.cs @@ -94,10 +94,10 @@ public async Task AuthenticateRequest(HttpRequestMessage request) private async Task Authenticate(HttpRequestMessage request, MAuthVersion version) { - var authInfo = GetAuthenticationInfo(request, version); + var mAuthCore = MAuthCoreFactory.Instantiate(version); + var authInfo = GetAuthenticationInfo(request, mAuthCore); var appInfo = await GetApplicationInfo(authInfo.ApplicationUuid).ConfigureAwait(false); - var mAuthCore = MAuthCoreFactory.Instantiate(version); var signature = await mAuthCore.GetSignature(request, authInfo).ConfigureAwait(false); return mAuthCore.Verify(authInfo.Payload, signature, appInfo.PublicKey); } @@ -130,11 +130,10 @@ private HttpRequestMessage CreateRequest(Guid applicationUuid) => /// Extracts the authentication information from a . /// /// The request that has the authentication information. - /// Enum value of the MAuthVersion. + /// Instantiation of mAuthCore class. /// The authentication information with the payload from the request. - internal PayloadAuthenticationInfo GetAuthenticationInfo(HttpRequestMessage request, MAuthVersion version) + internal PayloadAuthenticationInfo GetAuthenticationInfo(HttpRequestMessage request, IMAuthCore mAuthCore) { - var mAuthCore = MAuthCoreFactory.Instantiate(version); var headerKeys = mAuthCore.GetHeaderKeys(); var authHeader = request.Headers.GetFirstValueOrDefault(headerKeys.mAuthHeaderKey); diff --git a/tests/Medidata.MAuth.Tests/Infrastructure/MAuthServerHandler.cs b/tests/Medidata.MAuth.Tests/Infrastructure/MAuthServerHandler.cs index 9bb4410..c0b4e8c 100644 --- a/tests/Medidata.MAuth.Tests/Infrastructure/MAuthServerHandler.cs +++ b/tests/Medidata.MAuth.Tests/Infrastructure/MAuthServerHandler.cs @@ -29,7 +29,7 @@ protected override async Task SendAsync( var authenticator = new MAuthAuthenticator(TestExtensions.ServerOptions, NullLogger.Instance); - var authInfo = authenticator.GetAuthenticationInfo(request, version); + var authInfo = authenticator.GetAuthenticationInfo(request, mAuthCore); if (!mAuthCore.Verify(authInfo.Payload, await mAuthCore.GetSignature(request, authInfo), diff --git a/tests/Medidata.MAuth.Tests/MAuthAuthenticatorTests.cs b/tests/Medidata.MAuth.Tests/MAuthAuthenticatorTests.cs index 89a95cc..a780d2d 100644 --- a/tests/Medidata.MAuth.Tests/MAuthAuthenticatorTests.cs +++ b/tests/Medidata.MAuth.Tests/MAuthAuthenticatorTests.cs @@ -312,9 +312,10 @@ public static async Task GetAuthenticationInfo_WithSignedRequest_ForMWSV2Version var version = MAuthVersion.MWSV2; var testOptions = TestExtensions.ServerOptions; var authenticator = new MAuthAuthenticator(testOptions, NullLogger.Instance); + var mAuthCore = MAuthCoreFactory.Instantiate(version); // Act - var actual = authenticator.GetAuthenticationInfo(testData.ToHttpRequestMessage(version), version); + var actual = authenticator.GetAuthenticationInfo(testData.ToHttpRequestMessage(version), mAuthCore); // Assert Assert.Equal(testData.ApplicationUuid, actual.ApplicationUuid); @@ -334,9 +335,10 @@ public static async Task GetAuthenticationInfo_WithSignedRequest_ForMWSVersion_W var version = MAuthVersion.MWS; var testOptions = TestExtensions.ServerOptions; var authenticator = new MAuthAuthenticator(testOptions, NullLogger.Instance); + var mAuthCore = MAuthCoreFactory.Instantiate(version); // Act - var actual = authenticator.GetAuthenticationInfo(testData.ToHttpRequestMessage(version), version); + var actual = authenticator.GetAuthenticationInfo(testData.ToHttpRequestMessage(version), mAuthCore); // Assert Assert.Equal(testData.ApplicationUuid, actual.ApplicationUuid); From e7ba136d6976a30959e0f835f0eeb5867c7b204a Mon Sep 17 00:00:00 2001 From: Prajon Date: Tue, 21 Jan 2020 08:53:20 -0500 Subject: [PATCH 09/10] Moving LogInformation(...) into Authenticate(..) method so that it gets logged when eith V2 or fall back V1 is authenticated --- src/Medidata.MAuth.Core/MAuthAuthenticator.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Medidata.MAuth.Core/MAuthAuthenticator.cs b/src/Medidata.MAuth.Core/MAuthAuthenticator.cs index ff6a42a..271b3ef 100644 --- a/src/Medidata.MAuth.Core/MAuthAuthenticator.cs +++ b/src/Medidata.MAuth.Core/MAuthAuthenticator.cs @@ -48,9 +48,6 @@ public async Task AuthenticateRequest(HttpRequestMessage request) if (options.DisableV1 && version == MAuthVersion.MWS) throw new InvalidVersionException($"Authentication with {version} version is disabled."); - var logMessage = "Mauth-client attempting to authenticate request from app with mauth app uuid" + - $" {options.ApplicationUuid} using version {version}"; - logger.LogInformation(logMessage); var authenticated = await Authenticate(request, version).ConfigureAwait(false); if (!authenticated && version == MAuthVersion.MWSV2 && !options.DisableV1) { @@ -94,6 +91,10 @@ public async Task AuthenticateRequest(HttpRequestMessage request) private async Task Authenticate(HttpRequestMessage request, MAuthVersion version) { + var logMessage = "Mauth-client attempting to authenticate request from app with mauth app uuid" + + $" {options.ApplicationUuid} using version {version}"; + logger.LogInformation(logMessage); + var mAuthCore = MAuthCoreFactory.Instantiate(version); var authInfo = GetAuthenticationInfo(request, mAuthCore); var appInfo = await GetApplicationInfo(authInfo.ApplicationUuid).ConfigureAwait(false); From 440f91f5a5d1188bce3594c40b115be124e82c8a Mon Sep 17 00:00:00 2001 From: Prajon Date: Wed, 22 Jan 2020 08:41:29 -0500 Subject: [PATCH 10/10] Updated the method to be static and updated the unit tests and references --- src/Medidata.MAuth.Core/MAuthAuthenticator.cs | 16 ++++++++++------ .../Infrastructure/MAuthServerHandler.cs | 6 +----- .../MAuthAuthenticatorTests.cs | 6 ++---- 3 files changed, 13 insertions(+), 15 deletions(-) diff --git a/src/Medidata.MAuth.Core/MAuthAuthenticator.cs b/src/Medidata.MAuth.Core/MAuthAuthenticator.cs index 271b3ef..9cb1bf7 100644 --- a/src/Medidata.MAuth.Core/MAuthAuthenticator.cs +++ b/src/Medidata.MAuth.Core/MAuthAuthenticator.cs @@ -123,37 +123,41 @@ private Task GetApplicationInfo(Guid applicationUuid) => return result; }); - private HttpRequestMessage CreateRequest(Guid applicationUuid) => - new HttpRequestMessage(HttpMethod.Get, new Uri(options.MAuthServiceUrl, - $"{Constants.MAuthTokenRequestPath}{applicationUuid.ToHyphenString()}.json")); - /// /// Extracts the authentication information from a . /// /// The request that has the authentication information. /// Instantiation of mAuthCore class. /// The authentication information with the payload from the request. - internal PayloadAuthenticationInfo GetAuthenticationInfo(HttpRequestMessage request, IMAuthCore mAuthCore) + internal static PayloadAuthenticationInfo GetAuthenticationInfo(HttpRequestMessage request, IMAuthCore mAuthCore) { var headerKeys = mAuthCore.GetHeaderKeys(); var authHeader = request.Headers.GetFirstValueOrDefault(headerKeys.mAuthHeaderKey); if (authHeader == null) + { throw new ArgumentNullException(nameof(authHeader), "The MAuth header is missing from the request."); + } var signedTime = request.Headers.GetFirstValueOrDefault(headerKeys.mAuthTimeHeaderKey); if (signedTime == default(long)) + { throw new ArgumentException("Invalid MAuth signed time header value.", nameof(signedTime)); + } var (uuid, payload) = authHeader.ParseAuthenticationHeader(); - return new PayloadAuthenticationInfo() + return new PayloadAuthenticationInfo { ApplicationUuid = uuid, Payload = Convert.FromBase64String(payload), SignedTime = signedTime.FromUnixTimeSeconds() }; } + + private HttpRequestMessage CreateRequest(Guid applicationUuid) => + new HttpRequestMessage(HttpMethod.Get, new Uri(options.MAuthServiceUrl, + $"{Constants.MAuthTokenRequestPath}{applicationUuid.ToHyphenString()}.json")); } } diff --git a/tests/Medidata.MAuth.Tests/Infrastructure/MAuthServerHandler.cs b/tests/Medidata.MAuth.Tests/Infrastructure/MAuthServerHandler.cs index c0b4e8c..3499c89 100644 --- a/tests/Medidata.MAuth.Tests/Infrastructure/MAuthServerHandler.cs +++ b/tests/Medidata.MAuth.Tests/Infrastructure/MAuthServerHandler.cs @@ -4,7 +4,6 @@ using System.Threading; using System.Threading.Tasks; using Medidata.MAuth.Core; -using Medidata.MAuth.Core.Models; using Microsoft.Extensions.Logging.Abstractions; using Newtonsoft.Json; @@ -26,10 +25,7 @@ protected override async Task SendAsync( if (currentNumberOfAttempts < SucceedAfterThisManyAttempts) return new HttpResponseMessage(HttpStatusCode.ServiceUnavailable); - - var authenticator = new MAuthAuthenticator(TestExtensions.ServerOptions, NullLogger.Instance); - - var authInfo = authenticator.GetAuthenticationInfo(request, mAuthCore); + var authInfo = MAuthAuthenticator.GetAuthenticationInfo(request, mAuthCore); if (!mAuthCore.Verify(authInfo.Payload, await mAuthCore.GetSignature(request, authInfo), diff --git a/tests/Medidata.MAuth.Tests/MAuthAuthenticatorTests.cs b/tests/Medidata.MAuth.Tests/MAuthAuthenticatorTests.cs index a780d2d..b112142 100644 --- a/tests/Medidata.MAuth.Tests/MAuthAuthenticatorTests.cs +++ b/tests/Medidata.MAuth.Tests/MAuthAuthenticatorTests.cs @@ -311,11 +311,10 @@ public static async Task GetAuthenticationInfo_WithSignedRequest_ForMWSV2Version var testData = await method.FromResourceV2(); var version = MAuthVersion.MWSV2; var testOptions = TestExtensions.ServerOptions; - var authenticator = new MAuthAuthenticator(testOptions, NullLogger.Instance); var mAuthCore = MAuthCoreFactory.Instantiate(version); // Act - var actual = authenticator.GetAuthenticationInfo(testData.ToHttpRequestMessage(version), mAuthCore); + var actual = MAuthAuthenticator.GetAuthenticationInfo(testData.ToHttpRequestMessage(version), mAuthCore); // Assert Assert.Equal(testData.ApplicationUuid, actual.ApplicationUuid); @@ -334,11 +333,10 @@ public static async Task GetAuthenticationInfo_WithSignedRequest_ForMWSVersion_W var testData = await method.FromResource(); var version = MAuthVersion.MWS; var testOptions = TestExtensions.ServerOptions; - var authenticator = new MAuthAuthenticator(testOptions, NullLogger.Instance); var mAuthCore = MAuthCoreFactory.Instantiate(version); // Act - var actual = authenticator.GetAuthenticationInfo(testData.ToHttpRequestMessage(version), mAuthCore); + var actual = MAuthAuthenticator.GetAuthenticationInfo(testData.ToHttpRequestMessage(version), mAuthCore); // Assert Assert.Equal(testData.ApplicationUuid, actual.ApplicationUuid);