Skip to content

Commit

Permalink
Merge pull request #68 from mdsol/feature/inflate_private_key
Browse files Browse the repository at this point in the history
[MCC-655130] Inflate private key upon set in options classes.
  • Loading branch information
lschreck-mdsol authored Dec 24, 2020
2 parents 56bd48e + d5616fb commit 5e065a2
Show file tree
Hide file tree
Showing 11 changed files with 78 additions and 14 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Changes in Medidata.MAuth

## v5.0.1
- **[Core]** Inflate private key upon set in options classes.

## v5.0.0
- **[Core]** Added normalization of Uri AbsolutePath.
- **[Core]** Added unescape step in query_string encoding to remove `double encoding`.
Expand Down
4 changes: 0 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,6 @@ public async Task<HttpResponseMessage> SignAndSendRequest(HttpRequestMessage req
ApplicationUuid = new Guid("7c872d75-986b-4c61-bb17-f2569d42bfb0"),

// The following can be either a path to the key file or the contents of the file itself
// NOTE: if given a path, the file is read every time, no caching of the contents takes place
PrivateKey = "ClientPrivateKey.pem",

// Enumerations of signing protocols, if not provided defaults to `MAuthVersion.MWS`for sign-in.
Expand Down Expand Up @@ -168,7 +167,6 @@ public class Startup
options.AuthenticateRequestTimeoutSeconds = 3;
options.MAuthServiceRetryPolicy = MAuthServiceRetryPolicy.RetryOnce;
options.HideExceptionsAndReturnUnauthorized = true;
// NOTE: if given a path, the file is read every time, no caching of the contents takes place
options.PrivateKey = "ServerPrivateKey.pem";
options.Bypass = (request) => request.Uri.AbsolutePath.StartsWith("/allowed");

Expand Down Expand Up @@ -205,7 +203,6 @@ public class Startup
options.AuthenticateRequestTimeoutSeconds = 3;
options.MAuthServiceRetryPolicy = MAuthServiceRetryPolicy.RetryOnce;
options.HideExceptionsAndReturnUnauthorized = true;
// NOTE: if given a path, the file is read every time, no caching of the contents takes place
options.PrivateKey = "ServerPrivateKey.pem";
options.Bypass = (request) => request.Uri.AbsolutePath.StartsWith("/allowed");

Expand Down Expand Up @@ -269,7 +266,6 @@ public static class WebApiConfig
AuthenticateRequestTimeoutSeconds = 3,
MAuthServiceRetryPolicy = MAuthServiceRetryPolicy.RetryOnce,
HideExceptionsAndReturnUnauthorized = true,
// NOTE: if given a path, the file is read every time, no caching of the contents takes place
PrivateKey = "ServerPrivateKey.pem",

// when ready to disable authentication of V1 protococl
Expand Down
2 changes: 1 addition & 1 deletion src/Medidata.MAuth.Core/MAuthCore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public Task<HttpRequestMessage> Sign(HttpRequestMessage request, MAuthSigningOpt
{
ApplicationUuid = options.ApplicationUuid,
SignedTime = options.SignedTime ?? DateTimeOffset.UtcNow,
PrivateKey = options.PrivateKey.Dereference().NormalizeLines()
PrivateKey = options.PrivateKey
});
}

Expand Down
7 changes: 5 additions & 2 deletions src/Medidata.MAuth.Core/MAuthCoreExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -144,10 +144,13 @@ public static Stream Rewind(this Stream stream)
return stream;
}

public static string Dereference(this string keyPathOrKey) =>
public static string Inflate(this string keyPathOrKey) =>
keyPathOrKey?.Dereference().NormalizeLines();

private static string Dereference(this string keyPathOrKey) =>
keyPathOrKey.IsValidPath() ? File.ReadAllText(keyPathOrKey) : keyPathOrKey;

public static string NormalizeLines(this string key) =>
private static string NormalizeLines(this string key) =>
key.RemoveLineBreaks().InsertLineBreakAfterBegin().InsertLineBreakBeforeEnd();

private static bool IsValidPath(this string value) =>
Expand Down
2 changes: 1 addition & 1 deletion src/Medidata.MAuth.Core/MAuthCoreV2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public Task<HttpRequestMessage> Sign(
{
ApplicationUuid = options.ApplicationUuid,
SignedTime = options.SignedTime ?? DateTimeOffset.UtcNow,
PrivateKey = options.PrivateKey.Dereference().NormalizeLines()
PrivateKey = options.PrivateKey
});
}

Expand Down
11 changes: 9 additions & 2 deletions src/Medidata.MAuth.Core/Options/MAuthOptionsBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,18 @@ namespace Medidata.MAuth.Core
/// </summary>
public abstract class MAuthOptionsBase
{
private string _privateKey;

/// <summary>
/// Determines the RSA private key for the authentication requests. The value of this property can be set as a
/// valid path to a readable key file as well.
/// valid path to a readable key file as well. After set, this property will either contain an inflated
/// private key or `null`.
/// </summary>
public string PrivateKey { get; set; }
public string PrivateKey
{
get => _privateKey;
set => _privateKey = value.Inflate();
}

/// <summary>Determines the endpoint of the MAuth authentication service.</summary>
public Uri MAuthServiceUrl { get; set; }
Expand Down
11 changes: 9 additions & 2 deletions src/Medidata.MAuth.Core/Options/MAuthSigningOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,17 @@ namespace Medidata.MAuth.Core
/// </summary>
public class MAuthSigningOptions
{
private string _privateKey;

/// <summary>
/// Determines the RSA private key for the authentication requests. The value of this property can be set as a
/// valid path to a readable key file as well.</summary>
public string PrivateKey { get; set; }
/// valid path to a readable key file as well.After set, this property will either contain an inflated
/// private key or `null`.
/// </summary>
public string PrivateKey {
get => _privateKey;
set => _privateKey = value.Inflate();
}

/// <summary>Determines the unique identifier used for the MAuth service authentication requests.</summary>
public Guid ApplicationUuid { get; set; }
Expand Down
18 changes: 17 additions & 1 deletion tests/Medidata.MAuth.Tests/MAuthCoreTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -149,10 +149,26 @@ public static void AsCipherParameters_WithDifferentLineEnding_WillReadTheKeysSuc
var keyPath = $"Mocks\\Keys\\{keyFilename}";

// Act
var exception = Record.Exception(() => keyPath.Dereference().NormalizeLines().AsCipherParameters());
var exception = Record.Exception(() => keyPath.Inflate().AsCipherParameters());

// Assert
Assert.Null(exception);
}

[Theory]
[InlineData("LinuxLineEnding.pem")]
[InlineData("WindowsLineEnding.pem")]
[InlineData("NoLineEnding.pem")]
public static void MAuthSigningOptions_InflatesPrivateKey_OnSet(string keyFilename)
{
// Arrange
var expectedPrivateKeyContents = keyFilename.Inflate();

// Act
var signingOptions = new MAuthSigningOptions { PrivateKey = keyFilename };

// Assert
Assert.Equal(expectedPrivateKeyContents, signingOptions.PrivateKey);
}
}
}
16 changes: 16 additions & 0 deletions tests/Medidata.MAuth.Tests/MAuthOwinTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,22 @@ namespace Medidata.MAuth.Tests
{
public static class MAuthOwinTests
{
[Theory]
[InlineData("LinuxLineEnding.pem")]
[InlineData("WindowsLineEnding.pem")]
[InlineData("NoLineEnding.pem")]
public static void MAuthMiddlewareOptions_InflatesPrivateKey_OnSet(string keyFilename)
{
// Arrange
var expectedPrivateKeyContents = keyFilename.Inflate();

// Act
var signingOptions = new MAuthMiddlewareOptions { PrivateKey = keyFilename };

// Assert
Assert.Equal(expectedPrivateKeyContents, signingOptions.PrivateKey);
}

[Theory]
[InlineData("GET")]
[InlineData("DELETE")]
Expand Down
16 changes: 16 additions & 0 deletions tests/Medidata.MAuth.Tests/MAuthWebApiTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,22 @@ namespace Medidata.MAuth.Tests
{
public static class MAuthWebApiTests
{
[Theory]
[InlineData("LinuxLineEnding.pem")]
[InlineData("WindowsLineEnding.pem")]
[InlineData("NoLineEnding.pem")]
public static void MAuthWebApiOptions_InflatesPrivateKey_OnSet(string keyFilename)
{
// Arrange
var expectedPrivateKeyContents = keyFilename.Inflate();

// Act
var signingOptions = new MAuthWebApiOptions { PrivateKey = keyFilename };

// Assert
Assert.Equal(expectedPrivateKeyContents, signingOptions.PrivateKey);
}

[Theory]
[InlineData("GET")]
[InlineData("DELETE")]
Expand Down
2 changes: 1 addition & 1 deletion version.props
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project>
<PropertyGroup>
<Version>5.0.0</Version>
<Version>5.0.1</Version>
</PropertyGroup>
</Project>

0 comments on commit 5e065a2

Please sign in to comment.