Login works now, as does logout
This commit is contained in:
@@ -6,6 +6,28 @@
|
|||||||
<MudSnackbarProvider />
|
<MudSnackbarProvider />
|
||||||
|
|
||||||
<MudLayout>
|
<MudLayout>
|
||||||
|
<MudAppBar>
|
||||||
|
<MudSpacer />
|
||||||
|
<AuthorizeView Context="authenticationState">
|
||||||
|
<Authorized>
|
||||||
|
@{
|
||||||
|
var user = authenticationState.User;
|
||||||
|
var displayName = string.Join(" ", new[]
|
||||||
|
{
|
||||||
|
user.FindFirst("given_name")?.Value,
|
||||||
|
user.FindFirst("family_name")?.Value
|
||||||
|
}.Where(value => !string.IsNullOrWhiteSpace(value)));
|
||||||
|
var classroom = user.FindFirst("classroom")?.Value
|
||||||
|
?? (user.IsInRole("ROLE_TEACHER") ? "Lehrer" : null);
|
||||||
|
}
|
||||||
|
<MudText>@displayName@(classroom is null ? string.Empty : $" ({classroom})")</MudText>
|
||||||
|
<form method="post" action="/logout">
|
||||||
|
<AntiforgeryToken />
|
||||||
|
<MudButton ButtonType="ButtonType.Submit" Color="Color.Inherit" Variant="Variant.Text">Logout</MudButton>
|
||||||
|
</form>
|
||||||
|
</Authorized>
|
||||||
|
</AuthorizeView>
|
||||||
|
</MudAppBar>
|
||||||
<MudMainContent>
|
<MudMainContent>
|
||||||
@Body
|
@Body
|
||||||
</MudMainContent>
|
</MudMainContent>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
@using System.Net.Http
|
@using System.Net.Http
|
||||||
@using System.Net.Http.Json
|
@using System.Net.Http.Json
|
||||||
|
@using Microsoft.AspNetCore.Components.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
|
||||||
@@ -9,4 +10,4 @@
|
|||||||
@using Wollmilchsau
|
@using Wollmilchsau
|
||||||
@using Wollmilchsau.Components
|
@using Wollmilchsau.Components
|
||||||
@using Wollmilchsau.Components.Layout
|
@using Wollmilchsau.Components.Layout
|
||||||
@using MudBlazor
|
@using MudBlazor
|
||||||
|
|||||||
+100
-1
@@ -1,14 +1,76 @@
|
|||||||
using Fluxor;
|
using Fluxor;
|
||||||
using JasperFx;
|
using JasperFx;
|
||||||
using Marten;
|
using Marten;
|
||||||
|
using Microsoft.AspNetCore.Authentication;
|
||||||
|
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||||
|
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
|
||||||
using MudBlazor.Services;
|
using MudBlazor.Services;
|
||||||
using System.Net.Http.Headers;
|
using System.Net.Http.Headers;
|
||||||
|
using System.Security.Claims;
|
||||||
|
using System.Text.Json;
|
||||||
using Wollmilchsau.Components;
|
using Wollmilchsau.Components;
|
||||||
using Wollmilchsau.Exceptions;
|
using Wollmilchsau.Exceptions;
|
||||||
using Wollmilchsau.Services.Ldap;
|
using Wollmilchsau.Services.Ldap;
|
||||||
|
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
|
var oidcConfiguration = builder.Configuration.GetRequiredSection("OIDC");
|
||||||
|
var oidcScopes = oidcConfiguration.GetSection("Scopes").Get<string[]>()
|
||||||
|
?? throw new ConfigurationException("OIDC:Scopes");
|
||||||
|
|
||||||
|
builder.Services.AddAuthentication(options =>
|
||||||
|
{
|
||||||
|
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
|
||||||
|
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
|
||||||
|
})
|
||||||
|
.AddCookie()
|
||||||
|
.AddOpenIdConnect(options =>
|
||||||
|
{
|
||||||
|
options.Authority = oidcConfiguration["Authority"] ?? throw new ConfigurationException("OIDC:Authority");
|
||||||
|
options.ClientId = oidcConfiguration["ClientId"] ?? throw new ConfigurationException("OIDC:ClientId");
|
||||||
|
options.ClientSecret = oidcConfiguration["ClientSecret"] ?? throw new ConfigurationException("OIDC:ClientSecret");
|
||||||
|
options.ResponseType = oidcConfiguration["ResponseType"] ?? throw new ConfigurationException("OIDC:ResponseType");
|
||||||
|
options.GetClaimsFromUserInfoEndpoint = true;
|
||||||
|
options.SaveTokens = true;
|
||||||
|
options.MapInboundClaims = false;
|
||||||
|
options.PushedAuthorizationBehavior = PushedAuthorizationBehavior.Disable;
|
||||||
|
options.Scope.Clear();
|
||||||
|
|
||||||
|
foreach (var scope in oidcScopes)
|
||||||
|
{
|
||||||
|
options.Scope.Add(scope);
|
||||||
|
}
|
||||||
|
|
||||||
|
options.Events.OnTokenValidated = context =>
|
||||||
|
{
|
||||||
|
AddUserClaims(
|
||||||
|
context.Principal?.Identity as ClaimsIdentity,
|
||||||
|
context.Principal?.FindAll("groups").Select(claim => claim.Value).ToArray() ?? [],
|
||||||
|
context.Principal?.FindFirst("klasse")?.Value);
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
};
|
||||||
|
options.Events.OnUserInformationReceived = context =>
|
||||||
|
{
|
||||||
|
var userInfo = context.User.RootElement;
|
||||||
|
var groups = userInfo.TryGetProperty("groups", out var groupsElement) && groupsElement.ValueKind == JsonValueKind.Array
|
||||||
|
? groupsElement.EnumerateArray()
|
||||||
|
.Where(group => group.ValueKind == JsonValueKind.String)
|
||||||
|
.Select(group => group.GetString())
|
||||||
|
.OfType<string>()
|
||||||
|
: [];
|
||||||
|
var classroom = userInfo.TryGetProperty("klasse", out var classroomElement) && classroomElement.ValueKind == JsonValueKind.String
|
||||||
|
? classroomElement.GetString()
|
||||||
|
: null;
|
||||||
|
|
||||||
|
AddUserClaims(context.Principal?.Identity as ClaimsIdentity, groups, classroom);
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
};
|
||||||
|
});
|
||||||
|
builder.Services.AddAuthorization();
|
||||||
|
builder.Services.AddCascadingAuthenticationState();
|
||||||
|
|
||||||
builder.Services.AddOptions<LdapOptions>()
|
builder.Services.AddOptions<LdapOptions>()
|
||||||
.BindConfiguration("LDAP")
|
.BindConfiguration("LDAP")
|
||||||
.ValidateDataAnnotations()
|
.ValidateDataAnnotations()
|
||||||
@@ -70,10 +132,47 @@ if (!app.Environment.IsDevelopment())
|
|||||||
app.UseStatusCodePagesWithReExecute("/not-found", createScopeForStatusCodePages: true);
|
app.UseStatusCodePagesWithReExecute("/not-found", createScopeForStatusCodePages: true);
|
||||||
app.UseHttpsRedirection();
|
app.UseHttpsRedirection();
|
||||||
|
|
||||||
|
app.UseAuthentication();
|
||||||
|
app.UseAuthorization();
|
||||||
|
|
||||||
app.UseAntiforgery();
|
app.UseAntiforgery();
|
||||||
|
|
||||||
app.MapStaticAssets();
|
app.MapStaticAssets();
|
||||||
|
app.MapPost("/logout", async (HttpContext context) =>
|
||||||
|
{
|
||||||
|
var authenticationResult = await context.AuthenticateAsync(CookieAuthenticationDefaults.AuthenticationScheme);
|
||||||
|
var properties = authenticationResult.Properties ?? new AuthenticationProperties();
|
||||||
|
properties.RedirectUri = "/";
|
||||||
|
|
||||||
|
return Results.SignOut(
|
||||||
|
properties,
|
||||||
|
[CookieAuthenticationDefaults.AuthenticationScheme, OpenIdConnectDefaults.AuthenticationScheme]);
|
||||||
|
})
|
||||||
|
.RequireAuthorization()
|
||||||
|
.WithMetadata(new Microsoft.AspNetCore.Antiforgery.RequireAntiforgeryTokenAttribute(true));
|
||||||
app.MapRazorComponents<App>()
|
app.MapRazorComponents<App>()
|
||||||
.AddInteractiveServerRenderMode();
|
.AddInteractiveServerRenderMode()
|
||||||
|
.RequireAuthorization();
|
||||||
|
|
||||||
return await app.RunJasperFxCommands(args);
|
return await app.RunJasperFxCommands(args);
|
||||||
|
|
||||||
|
static void AddUserClaims(ClaimsIdentity? identity, IEnumerable<string> groups, string? classroom)
|
||||||
|
{
|
||||||
|
if (identity is null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var group in groups.Where(group => !string.IsNullOrWhiteSpace(group)))
|
||||||
|
{
|
||||||
|
if (!identity.HasClaim(ClaimTypes.Role, group))
|
||||||
|
{
|
||||||
|
identity.AddClaim(new Claim(ClaimTypes.Role, group));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(classroom) && !identity.HasClaim("classroom", classroom))
|
||||||
|
{
|
||||||
|
identity.AddClaim(new Claim("classroom", classroom));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -31,10 +31,10 @@
|
|||||||
},
|
},
|
||||||
"OIDC": {
|
"OIDC": {
|
||||||
"Authority": "https://id.bs18.de/realms/master",
|
"Authority": "https://id.bs18.de/realms/master",
|
||||||
"ClientId": "WollmilchsauDev",
|
"ClientId": "wollmilchsaudev",
|
||||||
"ClientSecret": "WQlhc6lzngs0nkC1TQeRbw16qffHaeg4",
|
"ClientSecret": "WQlhc6lzngs0nkC1TQeRbw16qffHaeg4",
|
||||||
"ResponseType": "code",
|
"ResponseType": "code",
|
||||||
"Scopes": [ "openid", "profile" ]
|
"Scopes": [ "openid", "profile", "gruppen", "KlassenAttribut" ]
|
||||||
},
|
},
|
||||||
"MSGraph": {
|
"MSGraph": {
|
||||||
"ClientId": "c938782f-2779-45e6-8430-21238e69aa9e",
|
"ClientId": "c938782f-2779-45e6-8430-21238e69aa9e",
|
||||||
|
|||||||
Reference in New Issue
Block a user