Custom auth implementation

This commit is contained in:
Max 2024-07-13 16:29:27 +02:00
parent 89cb9fbe1e
commit 487fd518e7
13 changed files with 82 additions and 57 deletions

@ -1 +1 @@
Subproject commit 03daea46e78dfa97d3e4f85fa8035fef5c5ed446 Subproject commit 5341179e9421b7d8c4e54ce4962fc856cef4d6ed

View File

@ -4,4 +4,13 @@
<MudText Typo="Typo.h4">Mud text!</MudText> <MudText Typo="Typo.h4">Mud text!</MudText>
<AuthorizeView Roles="test">
<NotAuthorized>
<span>Not autorized for role: 'test'</span>
</NotAuthorized>
<Authorized>
<span>Role: 'test' found!</span>
</Authorized>
</AuthorizeView>
Welcome to your new app. Welcome to your new app.

View File

@ -0,0 +1,7 @@
@page "/TestAdmin"
@attribute [Authorize(Roles = "Admin")]
<h3>TestAdmin</h3>
@code {
}

View File

@ -3,4 +3,11 @@
<RouteView RouteData="routeData" DefaultLayout="typeof(Layout.MainLayout)"/> <RouteView RouteData="routeData" DefaultLayout="typeof(Layout.MainLayout)"/>
<FocusOnNavigate RouteData="routeData" Selector="h1"/> <FocusOnNavigate RouteData="routeData" Selector="h1"/>
</Found> </Found>
<NotFound>
<LayoutView Layout="@typeof(EmptyLayout)">
@*TODO: Manage not found*@
<PageTitle>Not found!</PageTitle>
<p>Page not found!</p>
</LayoutView>
</NotFound>
</Router> </Router>

View File

@ -1,14 +1,19 @@
@using System.Net.Http @using System.Net.Http
@using System.Net.Http.Json @using System.Net.Http.Json
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.Forms @using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing @using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web @using Microsoft.AspNetCore.Components.Web
@using static Microsoft.AspNetCore.Components.Web.RenderMode
@using Microsoft.AspNetCore.Components.Web.Virtualization @using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.JSInterop @using Microsoft.JSInterop
@using static Microsoft.AspNetCore.Components.Web.RenderMode
@*SharpRSS*@ @*SharpRSS*@
@using SharpRSS.Blazor @using SharpRSS.Blazor
@using SharpRSS.Blazor.Components @using SharpRSS.Blazor.Components
@using SharpRSS.Blazor.Components.Layout
@*MudBlazor*@ @*MudBlazor*@
@using MudBlazor @using MudBlazor
@using MudBlazor.Components @using MudBlazor.Components
@*Authorize for the whole application*@
@attribute [Authorize]

View File

@ -4,9 +4,9 @@ using MudBlazor.Services;
using SharpRSS.Blazor.Components; using SharpRSS.Blazor.Components;
using SharpRSS.Business; using SharpRSS.Business;
using SharpRSS.Data; using SharpRSS.Data;
using SharpRSS.Data.Domains.Configuration;
var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);
builder.UseSRSS(); builder.UseSRSS();
builder.Services.AddBlazoredLocalStorage(); builder.Services.AddBlazoredLocalStorage();
@ -20,15 +20,22 @@ builder.Services.AddHttpContextAccessor(); // HttpContext accessor
/* /*
* HSTS config * HSTS config
*/ */
builder.Services.AddHsts(options => var hstsConfig = new HstsConfiguration();
var configSection = builder.Configuration.GetSection($"HTTP:{HstsConfiguration.Hsts}");
configSection.Bind(hstsConfig);
if (hstsConfig.EnableHsts)
{ {
options.Preload = true; builder.Services.AddHsts(options =>
options.IncludeSubDomains = true; {
options.MaxAge = TimeSpan.FromDays(60); // For DEV = 60 days, PROD = 1 year options.Preload = hstsConfig.Preload;
}); options.IncludeSubDomains = hstsConfig.IncludeSubdomains;
options.MaxAge = TimeSpan.FromSeconds(hstsConfig.MaxAgeSeconds);
});
}
var app = builder.Build(); var app = builder.Build();
//TODO: Move to migrations
var contextFactory = app.Services.GetService<IDbContextFactory<SRSSContext>>(); var contextFactory = app.Services.GetService<IDbContextFactory<SRSSContext>>();
if (contextFactory != null) if (contextFactory != null)
{ {
@ -42,14 +49,15 @@ else
if (!app.Environment.IsDevelopment()) if (!app.Environment.IsDevelopment())
{ {
app.UseDeveloperExceptionPage();
app.UseExceptionHandler("/Error", createScopeForErrors: true); app.UseExceptionHandler("/Error", createScopeForErrors: true);
app.UseHsts();
} }
app.UseHttpsRedirection(); app.UseHttpsRedirection();
app.UseStaticFiles(); app.UseStaticFiles();
app.UseAntiforgery(); app.UseAntiforgery();
app.UseAuthentication();
app.UseAuthorization();
app.MapRazorComponents<App>() app.MapRazorComponents<App>()
.AddInteractiveServerRenderMode(); .AddInteractiveServerRenderMode();

View File

@ -42,5 +42,15 @@
"Properties": { "Properties": {
"Application": "SharpRSS" "Application": "SharpRSS"
} }
},
"HTTP":
{
"HSTS":
{
"EnableHSTS": true,
"MaxAgeSeconds": 300,
"IncludeSubdomains": true,
"Preload": true
}
} }
} }

View File

@ -1,40 +0,0 @@
using DotBased.Logging;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Http;
using SharpRSS.Business.Services;
namespace SharpRSS.Business.Auth;
public class SRSSAuthenticationStateProvider : AuthenticationStateProvider
{
public SRSSAuthenticationStateProvider(IHttpContextAccessor contextAccessor, AuthService authService)
{
_logger = LogService.RegisterLogger(typeof(SRSSAuthenticationStateProvider));
if (contextAccessor.HttpContext != null)
_httpContext = contextAccessor.HttpContext;
else
{
var ex = new ApplicationException("HttpContext is null! Cannot setup authentication state provider!");
_logger.Fatal(ex, "Failed to initialize authentication state provider!");
throw ex;
}
_authService = authService;
}
/*
* Services
*/
private readonly ILogger _logger;
private readonly HttpContext _httpContext;
private readonly AuthService _authService;
/*
* Consts
*/
private const string AuthIdName = "srss_auth_id";
public override Task<AuthenticationState> GetAuthenticationStateAsync()
{
_logger.Debug("Getting authentication state...");
throw new NotImplementedException();
}
}

View File

@ -1,17 +1,17 @@
using DotBased.ASP.Auth;
using DotBased.ASP.Auth.Scheme;
using DotBased.Logging; using DotBased.Logging;
using DotBased.Logging.Serilog; using DotBased.Logging.Serilog;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Diagnostics;
using Serilog; using Serilog;
using SharpRSS.Business.Auth;
using SharpRSS.Business.Services;
using SharpRSS.Core.Configuration; using SharpRSS.Core.Configuration;
using SharpRSS.Data; using SharpRSS.Data;
using AuthService = SharpRSS.Business.Services.AuthService;
namespace SharpRSS.Business; namespace SharpRSS.Business;
@ -68,7 +68,14 @@ public static class DependencyInjection
/* /*
* Authentication * Authentication
*/ */
builder.Services.AddScoped<AuthenticationStateProvider, SRSSAuthenticationStateProvider>(); builder.Services.UseBasedAuth(options =>
{
options.AllowRegistration = false;
options.AuthenticationStateMaxAgeBeforeExpire = TimeSpan.FromDays(7);
options.LoginPath = "/auth/login";
options.LogoutPath = "/auth/logout";
});
builder.Services.AddCascadingAuthenticationState();
//TODO: Auth, Settings //TODO: Auth, Settings
return builder; return builder;

View File

@ -7,6 +7,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\DotBased\DotBased.ASP.Auth\DotBased.ASP.Auth.csproj" />
<ProjectReference Include="..\DotBased\DotBased.Logging.Serilog\DotBased.Logging.Serilog.csproj" /> <ProjectReference Include="..\DotBased\DotBased.Logging.Serilog\DotBased.Logging.Serilog.csproj" />
<ProjectReference Include="..\DotBased\DotBased\DotBased.csproj" /> <ProjectReference Include="..\DotBased\DotBased\DotBased.csproj" />
<ProjectReference Include="..\SharpRSS.Core\SharpRSS.Core.csproj" /> <ProjectReference Include="..\SharpRSS.Core\SharpRSS.Core.csproj" />
@ -36,4 +37,8 @@
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" /> <PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Folder Include="Auth\" />
</ItemGroup>
</Project> </Project>

View File

@ -5,7 +5,7 @@ public class HstsConfiguration
public const string Hsts = "HSTS"; public const string Hsts = "HSTS";
public bool EnableHsts { get; set; } public bool EnableHsts { get; set; }
public long MaxAgeSeconds { get; set; } public double MaxAgeSeconds { get; set; }
public bool IncludeSubdomains { get; set; } public bool IncludeSubdomains { get; set; }
public bool Preload { get; set; } public bool Preload { get; set; }
} }

View File

@ -17,6 +17,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotBased", "DotBased\DotBas
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotBased.Logging.Serilog", "DotBased\DotBased.Logging.Serilog\DotBased.Logging.Serilog.csproj", "{49F07625-B92C-439B-AC3E-7DEB26EA15D4}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotBased.Logging.Serilog", "DotBased\DotBased.Logging.Serilog\DotBased.Logging.Serilog.csproj", "{49F07625-B92C-439B-AC3E-7DEB26EA15D4}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotBased.ASP.Auth", "DotBased\DotBased.ASP.Auth\DotBased.ASP.Auth.csproj", "{18CEAA37-B46A-4543-9E7B-5BF12CFF9172}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -47,6 +49,10 @@ Global
{49F07625-B92C-439B-AC3E-7DEB26EA15D4}.Debug|Any CPU.Build.0 = Debug|Any CPU {49F07625-B92C-439B-AC3E-7DEB26EA15D4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{49F07625-B92C-439B-AC3E-7DEB26EA15D4}.Release|Any CPU.ActiveCfg = Release|Any CPU {49F07625-B92C-439B-AC3E-7DEB26EA15D4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{49F07625-B92C-439B-AC3E-7DEB26EA15D4}.Release|Any CPU.Build.0 = Release|Any CPU {49F07625-B92C-439B-AC3E-7DEB26EA15D4}.Release|Any CPU.Build.0 = Release|Any CPU
{18CEAA37-B46A-4543-9E7B-5BF12CFF9172}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{18CEAA37-B46A-4543-9E7B-5BF12CFF9172}.Debug|Any CPU.Build.0 = Debug|Any CPU
{18CEAA37-B46A-4543-9E7B-5BF12CFF9172}.Release|Any CPU.ActiveCfg = Release|Any CPU
{18CEAA37-B46A-4543-9E7B-5BF12CFF9172}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@ -57,5 +63,6 @@ Global
GlobalSection(NestedProjects) = preSolution GlobalSection(NestedProjects) = preSolution
{F2BA5122-C9EE-4E65-B3EF-987D797AEAB0} = {A73E4832-235F-4032-825E-3A928199A5DF} {F2BA5122-C9EE-4E65-B3EF-987D797AEAB0} = {A73E4832-235F-4032-825E-3A928199A5DF}
{49F07625-B92C-439B-AC3E-7DEB26EA15D4} = {A73E4832-235F-4032-825E-3A928199A5DF} {49F07625-B92C-439B-AC3E-7DEB26EA15D4} = {A73E4832-235F-4032-825E-3A928199A5DF}
{18CEAA37-B46A-4543-9E7B-5BF12CFF9172} = {A73E4832-235F-4032-825E-3A928199A5DF}
EndGlobalSection EndGlobalSection
EndGlobal EndGlobal

View File

@ -12,7 +12,7 @@ git submodule update --init --recursive
## Submodule commit ## Submodule commit
cd <repository> cd <repository-dir>
git add . git add .