diff --git a/Components/Pages/Home.razor b/Components/Pages/Home.razor index df05023..66bb9c9 100644 --- a/Components/Pages/Home.razor +++ b/Components/Pages/Home.razor @@ -1,7 +1,40 @@ @page "/" +@using Microsoft.AspNetCore.Components.Authorization +@inject AuthenticationStateProvider AuthStateProvider -Home +Zahlen-Analyse -

Hello, world!

+ + + Willkommen zurück, @context.User.Identity?.Name! + Deine Pocket-ID (Sub): @_userId + + + Abmelden + + + + Bitte melde dich an, um deine Workspaces zu verwalten. + + Mit Pocket-ID anmelden + + + -Welcome to your new app. +@code { + private string _userId = string.Empty; + + protected override async Task OnInitializedAsync() + { + var authState = await AuthStateProvider.GetAuthenticationStateAsync(); + var user = authState.User; + + if (user.Identity?.IsAuthenticated == true) + { + // Das ist der "sub"-Claim (Subject), den wir als OwnerId in RavenDB nutzen + _userId = user.FindFirst(c => c.Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier")?.Value + ?? user.FindFirst("sub")?.Value + ?? string.Empty; + } + } +} \ No newline at end of file diff --git a/Program.cs b/Program.cs index b383c02..2f5b8c9 100644 --- a/Program.cs +++ b/Program.cs @@ -1,6 +1,13 @@ using ZahlenAnalyse.Web.Components; using MudBlazor.Services; using Raven.Client.Documents; +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Authentication.Cookies; +using Microsoft.AspNetCore.Authentication.OpenIdConnect; +using Microsoft.IdentityModel.Tokens; +using DotNetEnv; + +Env.Load(); var builder = WebApplication.CreateBuilder(args); @@ -11,12 +18,43 @@ builder.Services.AddMudServices(); var store = new DocumentStore { - Urls = new[] { "http://localhost:8080" }, - Database = "ZahlenAnalyse" + Urls = new[] { builder.Configuration["RavenDb:Urls"] }, + Database = builder.Configuration["RavenDb:Database"] }; store.Initialize(); builder.Services.AddSingleton(store); +builder.Services.AddCascadingAuthenticationState(); + +builder.Services.AddAuthentication(options => + { + options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; + options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme; + }) + .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme) + .AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options => + { + var pocketIdConfig = builder.Configuration.GetSection("PocketId"); + + options.Authority = pocketIdConfig["Authority"]; + options.ClientId = pocketIdConfig["ClientId"]; + options.ClientSecret = pocketIdConfig["ClientSecret"]; + + options.ResponseType = "code"; + options.SaveTokens = true; + + // Wichtig für lokale Dev-Umgebungen ohne HTTPS-Zertifikatsprüfung (falls nötig) + // options.RequireHttpsMetadata = false; + + options.TokenValidationParameters = new TokenValidationParameters + { + NameClaimType = "name", + RoleClaimType = "roles" + }; + }); + +builder.Services.AddAuthorization(); + var app = builder.Build(); @@ -33,7 +71,29 @@ app.UseHttpsRedirection(); app.UseAntiforgery(); app.MapStaticAssets(); + +app.UseAuthentication(); +app.UseAuthorization(); + app.MapRazorComponents() .AddInteractiveServerRenderMode(); + +app.MapGet("/login", async (HttpContext context) => +{ + await context.ChallengeAsync(OpenIdConnectDefaults.AuthenticationScheme, new AuthenticationProperties + { + RedirectUri = "/" + }); +}); + +app.MapGet("/logout", async (HttpContext context) => +{ + await context.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme); + await context.SignOutAsync(OpenIdConnectDefaults.AuthenticationScheme, new AuthenticationProperties + { + RedirectUri = "/" + }); +}); + app.Run(); diff --git a/ZahlenAnalyse.Web.csproj b/ZahlenAnalyse.Web.csproj index cc1ec20..d776c60 100644 --- a/ZahlenAnalyse.Web.csproj +++ b/ZahlenAnalyse.Web.csproj @@ -8,6 +8,8 @@ + +