Add authentication options (password requirements, etc) to settings

This commit is contained in:
Pat Hartl 2023-03-20 00:15:22 -05:00
parent 0931c36000
commit bbacc5f941
5 changed files with 97 additions and 13 deletions

View file

@ -173,7 +173,7 @@ namespace LANCommander.Controllers.Api
var refreshToken = GenerateRefreshToken();
user.RefreshToken = refreshToken;
user.RefreshTokenExpiration = DateTime.Now.AddDays(Settings.TokenLifetime);
user.RefreshTokenExpiration = DateTime.Now.AddDays(Settings.Authentication.TokenLifetime);
await UserManager.UpdateAsync(user);
@ -190,10 +190,10 @@ namespace LANCommander.Controllers.Api
private JwtSecurityToken GetToken(List<Claim> authClaims)
{
var authSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Settings.TokenSecret));
var authSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Settings.Authentication.TokenSecret));
var token = new JwtSecurityToken(
expires: DateTime.Now.AddDays(Settings.TokenLifetime),
expires: DateTime.Now.AddDays(Settings.Authentication.TokenLifetime),
claims: authClaims,
signingCredentials: new SigningCredentials(authSigningKey, SecurityAlgorithms.HmacSha256)
);
@ -220,7 +220,7 @@ namespace LANCommander.Controllers.Api
ValidateAudience = false,
ValidateIssuer = false,
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Settings.TokenSecret)),
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Settings.Authentication.TokenSecret)),
ValidateLifetime = false
};

View file

@ -2,12 +2,23 @@
{
public class LANCommanderSettings
{
public int Port { get; set; }
public bool Beacon { get; set; }
public string TokenSecret { get; set; }
public int TokenLifetime { get; set; }
public string DatabaseConnectionString { get; set; }
public string IGDBClientId { get; set; }
public string IGDBClientSecret { get; set; }
public int Port { get; set; } = 1337;
public bool Beacon { get; set; } = true;
public string DatabaseConnectionString { get; set; } = "";
public string IGDBClientId { get; set; } = "";
public string IGDBClientSecret { get; set; } = "";
public LANCommanderAuthenticationSettings Authentication { get; set; } = new LANCommanderAuthenticationSettings();
}
public class LANCommanderAuthenticationSettings
{
public string TokenSecret { get; set; } = "";
public int TokenLifetime { get; set; } = 30;
public bool PasswordRequireNonAlphanumeric { get; set; }
public bool PasswordRequireLowercase { get; set; }
public bool PasswordRequireUppercase { get; set; }
public bool PasswordRequireDigit { get; set; }
public int PasswordRequiredLength { get; set; } = 8;
}
}

View file

@ -0,0 +1,67 @@
@page "/Settings/Authentication"
@using LANCommander.Models;
@layout SettingsLayout
@inject SettingService SettingService
@inject IMessageService MessageService
<PageHeader Title="Authentication" />
<div style="padding: 0 24px;">
<Form Model="Settings" Layout="@FormLayout.Vertical">
<FormItem Label="Token Secret">
<Input @bind-Value="context.Authentication.TokenSecret" />
</FormItem>
<FormItem Label="Token Lifetime">
<AntDesign.InputNumber @bind-Value="context.Authentication.TokenLifetime" Formatter="FormatTokenLifetime" Min="1" />
</FormItem>
<Divider Text="Password Requirements" />
<FormItem Label="Require non-alphanumeric characters">
<Switch @bind-Checked="@context.Authentication.PasswordRequireNonAlphanumeric" />
</FormItem>
<FormItem Label="Require Lowercase characters">
<Switch @bind-Checked="context.Authentication.PasswordRequireLowercase" />
</FormItem>
<FormItem Label="Require Uppercase characters">
<Switch @bind-Checked="context.Authentication.PasswordRequireUppercase" />
</FormItem>
<FormItem Label="Require digits">
<Switch @bind-Checked="context.Authentication.PasswordRequireDigit" />
</FormItem>
<FormItem Label="Minimum Length">
<AntDesign.InputNumber @bind-Value="context.Authentication.PasswordRequiredLength" Min="1" />
</FormItem>
<FormItem>
<Button OnClick="Save" Type="@ButtonType.Primary">Save</Button>
</FormItem>
</Form>
</div>
@code {
LANCommanderSettings Settings;
protected override async Task OnInitializedAsync()
{
Settings = SettingService.GetSettings();
}
private string FormatTokenLifetime(int value)
{
return value.ToString() + " days";
}
private void Save()
{
try
{
SettingService.SaveSettings(Settings);
MessageService.Success("Settings saved!");
}
catch
{
MessageService.Error("An unknown error occurred.");
}
}
}

View file

@ -6,6 +6,7 @@
<Menu Mode=@MenuMode.Inline Style="height: 100%">
<MenuItem RouterLink="/Settings/General">General</MenuItem>
<MenuItem RouterLink="/Settings/Users">Users</MenuItem>
<MenuItem RouterLink="/Settings/Authentication">Authentication</MenuItem>
</Menu>
</Sider>

View file

@ -46,8 +46,13 @@ builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddDefaultIdentity<User>((IdentityOptions options) =>
{
options.SignIn.RequireConfirmedAccount = false;
options.Password.RequireNonAlphanumeric = false;
options.SignIn.RequireConfirmedEmail = false;
options.Password.RequireNonAlphanumeric = settings.Authentication.PasswordRequireNonAlphanumeric;
options.Password.RequireLowercase = settings.Authentication.PasswordRequireLowercase;
options.Password.RequireUppercase = settings.Authentication.PasswordRequireUppercase;
options.Password.RequireDigit = settings.Authentication.PasswordRequireDigit;
options.Password.RequiredLength = settings.Authentication.PasswordRequiredLength;
})
.AddRoles<Role>()
.AddEntityFrameworkStores<LANCommander.Data.DatabaseContext>()
@ -69,7 +74,7 @@ builder.Services.AddAuthentication(options =>
ValidateAudience = false,
// ValidAudience = configuration["JWT:ValidAudience"],
// ValidIssuer = configuration["JWT:ValidIssuer"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(settings.TokenSecret))
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(settings.Authentication.TokenSecret))
};
});