Skip to content

Commit 7a391f5

Browse files
authored
Merge pull request #17 from Project-MONAI/nds_addbasiceauth
fix for basic auth
2 parents 0f62381 + d13f616 commit 7a391f5

6 files changed

+153
-2
lines changed

src/Authentication/Middleware/BasicAuthorizationMiddleware.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
using Microsoft.Extensions.Logging;
2323
using Microsoft.Extensions.Options;
2424
using Monai.Deploy.Security.Authentication.Configurations;
25-
using Monai.Deploy.Security.Authentication.Extensions;
2625

2726
namespace Monai.Deploy.Security.Authentication.Middleware
2827
{
@@ -49,7 +48,8 @@ public BasicAuthorizationMiddleware(
4948
public async Task InvokeAsync(HttpContext httpContext)
5049
{
5150

52-
if (_options.Value.BasicAuthEnabled(_logger) is false)
51+
if ((_options.Value.BypassAuthentication.HasValue && _options.Value.BypassAuthentication.Value is true)
52+
|| _options.Value.BasicAuthEnabled(_logger) is false)
5353
{
5454
await _next(httpContext).ConfigureAwait(false);
5555
return;
@@ -70,6 +70,7 @@ public async Task InvokeAsync(HttpContext httpContext)
7070
var identity = new ClaimsIdentity(claims, "Basic");
7171
var claimsPrincipal = new ClaimsPrincipal(identity);
7272
httpContext.User = claimsPrincipal;
73+
await _next(httpContext).ConfigureAwait(false);
7374
return;
7475
}
7576
}
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
/*
2+
* Copyright 2022 MONAI Consortium
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
using System.Net;
18+
using System.Text;
19+
using Microsoft.AspNetCore.Authentication.JwtBearer;
20+
using Microsoft.AspNetCore.TestHost;
21+
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
22+
using Monai.Deploy.Security.Authentication.Configurations;
23+
using Monai.Deploy.Security.Authentication.Extensions;
24+
25+
namespace Monai.Deploy.Security.Authentication.Tests
26+
{
27+
public partial class BasicAuthorizationMiddlewareTest
28+
{
29+
30+
31+
[Fact]
32+
public async Task GivenConfigurationFileToBypassAuthentication_ExpectToBypassAuthentication()
33+
{
34+
using var host = await new HostBuilder().ConfigureWebHost(SetupWebServer("test.basicbypass.json")).StartAsync().ConfigureAwait(false);
35+
36+
var server = host.GetTestServer();
37+
server.BaseAddress = new Uri("https://example.com/");
38+
39+
var client = server.CreateClient();
40+
var responseMessage = await client.GetAsync("api/Test").ConfigureAwait(false);
41+
42+
Assert.True(responseMessage.IsSuccessStatusCode);
43+
}
44+
45+
46+
47+
[Fact]
48+
public async Task GivenConfigurationFileWithBasicConfigured_WhenUserIsNotAuthenticated_ExpectToDenyRequest()
49+
{
50+
using var host = await new HostBuilder().ConfigureWebHost(SetupWebServer("test.basic.json")).StartAsync().ConfigureAwait(false);
51+
52+
var server = host.GetTestServer();
53+
server.BaseAddress = new Uri("https://example.com/");
54+
55+
var client = server.CreateClient();
56+
var responseMessage = await client.GetAsync("api/Test").ConfigureAwait(false);
57+
58+
Assert.Equal(HttpStatusCode.Unauthorized, responseMessage.StatusCode);
59+
}
60+
61+
[Fact]
62+
public async Task GivenConfigurationFileWithBasicConfigured_WhenUserIsAuthenticated_ExpectToAllowRequest()
63+
{
64+
using var host = await new HostBuilder().ConfigureWebHost(SetupWebServer("test.basic.json")).StartAsync().ConfigureAwait(false);
65+
66+
var server = host.GetTestServer();
67+
server.BaseAddress = new Uri("https://example.com/");
68+
69+
var client = server.CreateClient();
70+
client.DefaultRequestHeaders.Add("Authorization", $"Basic {Convert.ToBase64String(Encoding.UTF8.GetBytes("user:pass"))}");
71+
var responseMessage = await client.GetAsync("api/Test").ConfigureAwait(false);
72+
73+
Assert.Equal(HttpStatusCode.OK, responseMessage.StatusCode);
74+
}
75+
76+
[Fact]
77+
public async Task GivenConfigurationFileWithBasicConfigured_WhenHeaderIsInvalid_ExpectToDenyRequest()
78+
{
79+
using var host = await new HostBuilder().ConfigureWebHost(SetupWebServer("test.basic.json")).StartAsync().ConfigureAwait(false);
80+
81+
var server = host.GetTestServer();
82+
server.BaseAddress = new Uri("https://example.com/");
83+
84+
var client = server.CreateClient();
85+
client.DefaultRequestHeaders.Add("Authorization", $"BasicBad {Convert.ToBase64String(Encoding.UTF8.GetBytes("user:pass"))}");
86+
var responseMessage = await client.GetAsync("api/Test").ConfigureAwait(false);
87+
88+
Assert.Equal(HttpStatusCode.Unauthorized, responseMessage.StatusCode);
89+
}
90+
91+
private static Action<IWebHostBuilder> SetupWebServer(string configFile) => webBuilder =>
92+
{
93+
webBuilder
94+
.ConfigureAppConfiguration((builderContext, config) =>
95+
{
96+
config.Sources.Clear();
97+
config.AddJsonFile(configFile, optional: false);
98+
_ = config.Build();
99+
})
100+
.ConfigureLogging((hostContext, logging) =>
101+
{
102+
logging.AddDebug();
103+
logging.AddConsole();
104+
})
105+
.ConfigureServices((hostContext, services) =>
106+
{
107+
services.AddOptions<AuthenticationOptions>().Bind(hostContext.Configuration.GetSection("MonaiDeployAuthentication"));
108+
109+
services.AddControllers();
110+
services.AddMonaiAuthentication();
111+
112+
services.Configure<JwtBearerOptions>(JwtBearerDefaults.AuthenticationScheme, op =>
113+
{
114+
var config = new OpenIdConnectConfiguration()
115+
{
116+
Issuer = Guid.NewGuid().ToString(),
117+
};
118+
119+
config.SigningKeys.Add(EndpointAuthorizationMiddlewareTest.MockJwtTokenHandler.SecurityKey);
120+
op.Configuration = config;
121+
});
122+
})
123+
.Configure(app =>
124+
{
125+
app.UseHttpsRedirection();
126+
app.UseRouting();
127+
app.UseAuthentication();
128+
app.UseAuthorization();
129+
app.UseEndpointAuthorizationMiddleware();
130+
app.UseEndpoints(endpoints =>
131+
{
132+
endpoints.MapControllers();
133+
});
134+
})
135+
.UseTestServer();
136+
};
137+
}
138+
}

src/Authentication/Tests/EndpointAuthorizationMiddlewareTest.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ public async Task GivenConfigurationFileWithBasicConfigured_WhenUserIsAuthentica
165165

166166
Assert.Equal(HttpStatusCode.OK, responseMessage.StatusCode);
167167
}
168+
168169
[Fact]
169170
public async Task GivenConfigurationFileWithBasicConfigured_WhenHeaderIsInvalid_ExpectToDenyRequest()
170171
{

src/Authentication/Tests/MockJwtTokenHandler.cs

100644100755
File mode changed.

src/Authentication/Tests/Monai.Deploy.Security.Authentication.Tests.csproj

100644100755
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,4 +57,6 @@
5757
</None>
5858
</ItemGroup>
5959

60+
<ProjectExtensions><VisualStudio><UserProperties test_1basic_1json__JsonSchema="BasicAuthorizationMiddlewareTestBasicAuthorizationMiddlewareTestBasicAuthorizationMiddlewareTest" /></VisualStudio></ProjectExtensions>
61+
6062
</Project>
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"MonaiDeployAuthentication": {
3+
"BypassAuthentication": true,
4+
"basicAuth": {
5+
"userName": "user",
6+
"password": "pass"
7+
}
8+
}
9+
}

0 commit comments

Comments
 (0)