diff --git a/build/version.props b/build/version.props
index 536a49b..030cf21 100644
--- a/build/version.props
+++ b/build/version.props
@@ -2,7 +2,7 @@
5
1
- 0
+ 1
$(VersionMajor).$(VersionMinor).$(VersionPatch)
diff --git a/samples/Sample.Dashboard.Auth/MyDashboardAuthenticationHandler.cs b/samples/Sample.Dashboard.Auth/MyDashboardAuthenticationHandler.cs
new file mode 100644
index 0000000..c4320b6
--- /dev/null
+++ b/samples/Sample.Dashboard.Auth/MyDashboardAuthenticationHandler.cs
@@ -0,0 +1,50 @@
+using System.Linq;
+using System.Security.Claims;
+using System.Text.Encodings.Web;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Authentication;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
+
+namespace Sample.Dashboard.Auth
+{
+ public class MyDashboardAuthenticationSchemeOptions : AuthenticationSchemeOptions
+ {
+
+ }
+
+ public class MyDashboardAuthenticationHandler : AuthenticationHandler
+ {
+ public MyDashboardAuthenticationHandler(IOptionsMonitor options,
+ ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock)
+ {
+ options.CurrentValue.ForwardChallenge = "";
+ }
+
+ protected override Task HandleAuthenticateAsync()
+ {
+ var testAuthHeaderPresent = Request.Headers["X-Base-Token"].Contains("xxx");
+
+ var authResult = testAuthHeaderPresent ? AuthenticatedTestUser() : AuthenticateResult.NoResult();
+
+ return Task.FromResult(authResult);
+ }
+
+ protected override Task HandleChallengeAsync(AuthenticationProperties properties)
+ {
+ Response.Headers["WWW-Authenticate"] = "MyDashboardScheme";
+
+ return base.HandleChallengeAsync(properties);
+ }
+
+ private AuthenticateResult AuthenticatedTestUser()
+ {
+ var claims = new[] { new Claim(ClaimTypes.Name, "My Dashboard user") };
+ var identity = new ClaimsIdentity(claims, "MyDashboardScheme");
+ var principal = new ClaimsPrincipal(identity);
+ var ticket = new AuthenticationTicket(principal, "MyDashboardScheme");
+
+ return AuthenticateResult.Success(ticket);
+ }
+ }
+}
diff --git a/samples/Sample.Dashboard.Auth/Startup.cs b/samples/Sample.Dashboard.Auth/Startup.cs
index e0335ae..0c2b00f 100644
--- a/samples/Sample.Dashboard.Auth/Startup.cs
+++ b/samples/Sample.Dashboard.Auth/Startup.cs
@@ -21,7 +21,7 @@ namespace Sample.Dashboard.Auth
.AddAuthorization()
.AddAuthentication(options =>
{
- options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
+ options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
@@ -36,7 +36,8 @@ namespace Sample.Dashboard.Auth
options.Scope.Clear();
options.Scope.Add("openid");
options.Scope.Add("profile");
- });
+ })
+ .AddScheme("MyDashboardScheme",null);
services.AddCors(x =>
{
@@ -45,13 +46,15 @@ namespace Sample.Dashboard.Auth
p.WithOrigins("http://localhost:8080").AllowCredentials().AllowAnyHeader().AllowAnyMethod();
});
});
-
+
services.AddCap(cap =>
{
cap.UseDashboard(d =>
{
d.UseChallengeOnAuth = true;
d.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
+ d.UseAuth = true;
+ d.DefaultAuthenticationScheme = "MyDashboardScheme";
});
cap.UseMySql(_configuration.GetValue("ConnectionString"));
cap.UseRabbitMQ(aa =>
@@ -76,16 +79,16 @@ namespace Sample.Dashboard.Auth
public void Configure(IApplicationBuilder app)
{
- app.UseAuthentication();
app.UseCors();
app.UseRouting();
+ app.UseAuthentication();
app.UseAuthorization();
app.UseCookiePolicy();
app.UseEndpoints(endpoints =>
{
- endpoints.MapControllers();
+ endpoints.MapControllers();
});
}
- }
+ }
}
\ No newline at end of file
diff --git a/src/DotNetCore.CAP.Dashboard/CAP.DashboardOptions.cs b/src/DotNetCore.CAP.Dashboard/CAP.DashboardOptions.cs
index 57daf1b..a9af5ae 100644
--- a/src/DotNetCore.CAP.Dashboard/CAP.DashboardOptions.cs
+++ b/src/DotNetCore.CAP.Dashboard/CAP.DashboardOptions.cs
@@ -13,16 +13,29 @@ namespace DotNetCore.CAP
}
public string PathMatch { get; set; }
-
+
///
/// The interval the /stats endpoint should be polled with.
///
public int StatsPollingInterval { get; set; }
+ ///
+ /// Enable authentication on dashboard request.
+ ///
+ public bool UseAuth { get; set; }
+
+ ///
+ /// Default scheme used for authentication. If no scheme is set, the DefaultScheme set up in AddAuthentication will be used.
+ ///
+ public string DefaultAuthenticationScheme { get; set; }
+
+ ///
+ /// Enable authentication challenge on dashboard request.
+ ///
public bool UseChallengeOnAuth { get; set; }
///
- /// Default ChallengeScheme used for Dashboard authentication. If no scheme is set, the DefaultScheme set up in AddAuthentication will be used.
+ /// Default scheme used for authentication challenge. If no scheme is set, the DefaultChallengeScheme set up in AddAuthentication will be used.
///
public string DefaultChallengeScheme { get; set; }
}
diff --git a/src/DotNetCore.CAP.Dashboard/UiMiddleware.cs b/src/DotNetCore.CAP.Dashboard/UiMiddleware.cs
index c8ab361..ead672f 100644
--- a/src/DotNetCore.CAP.Dashboard/UiMiddleware.cs
+++ b/src/DotNetCore.CAP.Dashboard/UiMiddleware.cs
@@ -47,11 +47,22 @@ namespace DotNetCore.CAP.Dashboard
if (httpMethod == "GET" && Regex.IsMatch(path, $"^/?{Regex.Escape(_options.PathMatch)}/?index.html$", RegexOptions.IgnoreCase))
{
+ if (_options.UseAuth)
+ {
+ var result = await httpContext.AuthenticateAsync(_options.DefaultAuthenticationScheme);
+
+ if (result.Succeeded && result.Principal != null)
+ {
+ httpContext.User = result.Principal;
+ }
+ }
+
var isAuthenticated = httpContext.User?.Identity?.IsAuthenticated;
if (isAuthenticated == false && _options.UseChallengeOnAuth)
{
await httpContext.ChallengeAsync(_options.DefaultChallengeScheme);
+
return;
}