Allow user identity password and lockout configuration to be customized. Included additional environment information in System Info.

This commit is contained in:
Shaun Walker
2022-03-04 10:41:45 -05:00
parent 1cdc80e09b
commit 5adecc307f
12 changed files with 445 additions and 150 deletions

View File

@ -5,6 +5,7 @@ using Oqtane.Shared;
using System;
using Microsoft.AspNetCore.Hosting;
using Oqtane.Infrastructure;
using Microsoft.AspNetCore.Http.Features;
namespace Oqtane.Controllers
{
@ -20,62 +21,76 @@ namespace Oqtane.Controllers
_configManager = configManager;
}
// GET: api/<controller>
// GET: api/<controller>?type=x
[HttpGet]
[Authorize(Roles = RoleNames.Host)]
public Dictionary<string, string> Get()
public Dictionary<string, object> Get(string type)
{
Dictionary<string, string> systeminfo = new Dictionary<string, string>();
Dictionary<string, object> systeminfo = new Dictionary<string, object>();
systeminfo.Add("clrversion", Environment.Version.ToString());
systeminfo.Add("osversion", Environment.OSVersion.ToString());
systeminfo.Add("machinename", Environment.MachineName);
systeminfo.Add("serverpath", _environment.ContentRootPath);
systeminfo.Add("servertime", DateTime.UtcNow.ToString());
systeminfo.Add("installationid", _configManager.GetInstallationId());
systeminfo.Add("runtime", _configManager.GetSetting("Runtime", "Server"));
systeminfo.Add("rendermode", _configManager.GetSetting("RenderMode", "ServerPrerendered"));
systeminfo.Add("detailederrors", _configManager.GetSetting("DetailedErrors", "false"));
systeminfo.Add("logginglevel", _configManager.GetSetting("Logging:LogLevel:Default", "Information"));
systeminfo.Add("notificationlevel", _configManager.GetSetting("Logging:LogLevel:Notify", "Error"));
systeminfo.Add("swagger", _configManager.GetSetting("UseSwagger", "true"));
systeminfo.Add("packageservice", _configManager.GetSetting("PackageService", "true"));
switch (type.ToLower())
{
case "environment":
systeminfo.Add("CLRVersion", Environment.Version.ToString());
systeminfo.Add("OSVersion", Environment.OSVersion.ToString());
systeminfo.Add("MachineName", Environment.MachineName);
systeminfo.Add("WorkingSet", Environment.WorkingSet.ToString());
systeminfo.Add("TickCount", Environment.TickCount64.ToString());
systeminfo.Add("ContentRootPath", _environment.ContentRootPath);
systeminfo.Add("WebRootPath", _environment.WebRootPath);
systeminfo.Add("ServerTime", DateTime.UtcNow.ToString());
var feature = HttpContext.Features.Get<IHttpConnectionFeature>();
systeminfo.Add("IPAddress", feature?.LocalIpAddress?.ToString());
break;
case "configuration":
systeminfo.Add("InstallationId", _configManager.GetInstallationId());
systeminfo.Add("Runtime", _configManager.GetSetting("Runtime", "Server"));
systeminfo.Add("RenderMode", _configManager.GetSetting("RenderMode", "ServerPrerendered"));
systeminfo.Add("DetailedErrors", _configManager.GetSetting("DetailedErrors", "false"));
systeminfo.Add("Logging:LogLevel:Default", _configManager.GetSetting("Logging:LogLevel:Default", "Information"));
systeminfo.Add("Logging:LogLevel:Notify", _configManager.GetSetting("Logging:LogLevel:Notify", "Error"));
systeminfo.Add("UseSwagger", _configManager.GetSetting("UseSwagger", "true"));
systeminfo.Add("PackageService", _configManager.GetSetting("PackageService", "true"));
systeminfo.Add("Password:RequiredLength", _configManager.GetSetting("Password:RequiredLength", "6"));
systeminfo.Add("Password:RequiredUniqueChars", _configManager.GetSetting("Password:RequiredUniqueChars", "1"));
systeminfo.Add("Password:RequireDigit", _configManager.GetSetting("Password:RequireDigit", "true"));
systeminfo.Add("Password:RequireUppercase", _configManager.GetSetting("Password:RequireUppercase", "true"));
systeminfo.Add("Password:RequireLowercase", _configManager.GetSetting("Password:RequireLowercase", "true"));
systeminfo.Add("Password:RequireNonAlphanumeric", _configManager.GetSetting("Password:RequireNonAlphanumeric", "true"));
systeminfo.Add("Lockout:MaxFailedAccessAttempts", _configManager.GetSetting("Lockout:MaxFailedAccessAttempts", "5"));
systeminfo.Add("Lockout:DefaultLockoutTimeSpan", _configManager.GetSetting("Lockout:DefaultLockoutTimeSpan", "00:05:00"));
break;
}
return systeminfo;
}
// GET: api/<controller>
[HttpGet("{key}/{value}")]
[Authorize(Roles = RoleNames.Host)]
public object Get(string key, object value)
{
return _configManager.GetSetting(key, value);
}
// POST: api/<controller>
[HttpPost]
[Authorize(Roles = RoleNames.Host)]
public void Post([FromBody] Dictionary<string, string> settings)
public void Post([FromBody] Dictionary<string, object> settings)
{
foreach(KeyValuePair<string, string> kvp in settings)
foreach(KeyValuePair<string, object> kvp in settings)
{
switch (kvp.Key)
{
case "runtime":
_configManager.AddOrUpdateSetting("Runtime", kvp.Value, false);
break;
case "rendermode":
_configManager.AddOrUpdateSetting("RenderMode", kvp.Value, false);
break;
case "detailederrors":
_configManager.AddOrUpdateSetting("DetailedErrors", kvp.Value, false);
break;
case "logginglevel":
_configManager.AddOrUpdateSetting("Logging:LogLevel:Default", kvp.Value, false);
break;
case "notificationlevel":
_configManager.AddOrUpdateSetting("Logging:LogLevel:Notify", kvp.Value, false);
break;
case "swagger":
_configManager.AddOrUpdateSetting("UseSwagger", kvp.Value, false);
break;
case "packageservice":
_configManager.AddOrUpdateSetting("PackageService", kvp.Value, false);
break;
}
_configManager.AddOrUpdateSetting(kvp.Key, kvp.Value, false);
}
}
// PUT: api/<controller>
[HttpPut("{key}/{value}")]
[Authorize(Roles = RoleNames.Host)]
public void Put(string key, object value)
{
_configManager.AddOrUpdateSetting(key, value, false);
}
}
}

View File

@ -397,7 +397,7 @@ namespace Oqtane.Controllers
user = _users.GetUser(user.Username);
string token = await _identityUserManager.GeneratePasswordResetTokenAsync(identityuser);
string url = HttpContext.Request.Scheme + "://" + _alias.Name + "/reset?name=" + user.Username + "&token=" + WebUtility.UrlEncode(token);
string body = "Dear " + user.DisplayName + ",\n\nYou attempted 3 times unsuccessfully to log in to your account and it is now locked out. Please wait 10 minutes and then try again... or use the link below to reset your password:\n\n" + url +
string body = "Dear " + user.DisplayName + ",\n\nYou attempted multiple times unsuccessfully to log in to your account and it is now locked out. Please wait a few minutes and then try again... or use the link below to reset your password:\n\n" + url +
"\n\nPlease note that the link is only valid for 24 hours so if you are unable to take action within that time period, you should initiate another password reset on the site." +
"\n\nThank You!";
var notification = new Notification(loginUser.SiteId, user, "User Lockout", body);

View File

@ -10,6 +10,7 @@ using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.OpenApi.Models;
@ -129,26 +130,36 @@ namespace Microsoft.Extensions.DependencyInjection
return services;
}
public static IServiceCollection ConfigureOqtaneIdentityOptions(this IServiceCollection services)
public static IServiceCollection ConfigureOqtaneIdentityOptions(this IServiceCollection services, IConfigurationRoot Configuration)
{
// default settings
services.Configure<IdentityOptions>(options =>
{
// Password settings
options.Password.RequireDigit = false;
options.Password.RequireDigit = true;
options.Password.RequiredLength = 6;
options.Password.RequireNonAlphanumeric = false;
options.Password.RequireUppercase = false;
options.Password.RequireLowercase = false;
options.Password.RequireNonAlphanumeric = true;
options.Password.RequireUppercase = true;
options.Password.RequireLowercase = true;
options.Password.RequiredUniqueChars = 1;
// Lockout settings
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(10);
options.Lockout.MaxFailedAccessAttempts = 3;
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
options.Lockout.MaxFailedAccessAttempts = 5;
options.Lockout.AllowedForNewUsers = false;
// SignIn settings
options.SignIn.RequireConfirmedEmail = true;
options.SignIn.RequireConfirmedPhoneNumber = false;
// User settings
options.User.RequireUniqueEmail = false;
options.User.AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+";
});
// overrides defined in appsettings
services.Configure<IdentityOptions>(Configuration);
return services;
}

View File

@ -100,7 +100,7 @@ namespace Oqtane.Infrastructure
switch (action)
{
case "set":
jsonObj[currentSection] = value;
jsonObj[currentSection] = JToken.FromObject(value);
break;
case "remove":
if (jsonObj.Property(currentSection) != null)

View File

@ -86,7 +86,7 @@ namespace Oqtane
.AddDefaultTokenProviders()
.AddClaimsPrincipalFactory<ClaimsPrincipalFactory<IdentityUser>>(); // role claims
services.ConfigureOqtaneIdentityOptions();
services.ConfigureOqtaneIdentityOptions(Configuration);
services.AddAuthentication(Constants.AuthenticationScheme)
.AddCookie(Constants.AuthenticationScheme);