diff --git a/sources/Clients.Admin.Web/Layout/MainLayout.razor b/sources/Clients.Admin.Web/Layout/MainLayout.razor
index 0fcaba5..ea00894 100644
--- a/sources/Clients.Admin.Web/Layout/MainLayout.razor
+++ b/sources/Clients.Admin.Web/Layout/MainLayout.razor
@@ -6,13 +6,22 @@
-
-
- Login
-
+
+
+
+ Logout
+
+
+
+
+ Login
+
+
+
+
@Body
diff --git a/sources/Clients.Admin.Web/Program.cs b/sources/Clients.Admin.Web/Program.cs
index 4c9cdca..8ec003d 100644
--- a/sources/Clients.Admin.Web/Program.cs
+++ b/sources/Clients.Admin.Web/Program.cs
@@ -1,3 +1,4 @@
+using Blazored.LocalStorage;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using MadWorldNL.Clients.Admin.Web;
@@ -9,6 +10,7 @@
builder.RootComponents.Add("head::after");
builder.Services.AddRadzenComponents();
+builder.Services.AddBlazoredLocalStorage();
builder.AddIdentity();
diff --git a/sources/Clients.Identity.Blazor.Shared/Authentications/AuthenticationLocalStorage.cs b/sources/Clients.Identity.Blazor.Shared/Authentications/AuthenticationLocalStorage.cs
new file mode 100644
index 0000000..9484314
--- /dev/null
+++ b/sources/Clients.Identity.Blazor.Shared/Authentications/AuthenticationLocalStorage.cs
@@ -0,0 +1,27 @@
+using Blazored.LocalStorage;
+using MadWorldNL.Clients.Identity.Api.Contracts.Authentications;
+
+namespace MadWorldNL.Clients.Identity.Blazor.Shared.Authentications;
+
+public class AuthenticationLocalStorage : IAuthenticationStorage
+{
+ private const string AuthenticationResponseName = "AuthenticationResponse";
+
+ private readonly ILocalStorageService _localStorage;
+
+ public AuthenticationLocalStorage(ILocalStorageService localStorage)
+ {
+ _localStorage = localStorage;
+ }
+
+ public async Task SetAccessTokenAsync(LoginProxyResponse response)
+ {
+ await _localStorage.SetItemAsync(AuthenticationResponseName, response);
+ }
+
+ public async Task GetAccessTokenAsync()
+ {
+ return await _localStorage.GetItemAsync(AuthenticationResponseName)
+ ?? new LoginProxyResponse();
+ }
+}
\ No newline at end of file
diff --git a/sources/Clients.Identity.Blazor.Shared/Authentications/AuthenticationManager.cs b/sources/Clients.Identity.Blazor.Shared/Authentications/AuthenticationManager.cs
index b4d427b..83e3327 100644
--- a/sources/Clients.Identity.Blazor.Shared/Authentications/AuthenticationManager.cs
+++ b/sources/Clients.Identity.Blazor.Shared/Authentications/AuthenticationManager.cs
@@ -1,18 +1,33 @@
using MadWorldNL.Clients.Identity.Api.Contracts.Authentications;
+using Microsoft.AspNetCore.Components.Authorization;
namespace MadWorldNL.Clients.Identity.Blazor.Shared.Authentications;
public class AuthenticationManager : IAuthenticationManager
{
private readonly IAuthenticationService _authenticationService;
+ private readonly IAuthenticationStorage _authenticationStorage;
+ private readonly AuthenticationStateProvider _authenticationStateProvider;
- public AuthenticationManager(IAuthenticationService authenticationService)
+ public AuthenticationManager(IAuthenticationService authenticationService, IAuthenticationStorage authenticationStorage, AuthenticationStateProvider authenticationStateProvider)
{
_authenticationService = authenticationService;
+ _authenticationStorage = authenticationStorage;
+ _authenticationStateProvider = authenticationStateProvider;
}
public async Task LoginAsync(LoginProxyRequest request)
{
- return await _authenticationService.LoginAsync(request);
+ var response = await _authenticationService.LoginAsync(request);
+ await _authenticationStorage.SetAccessTokenAsync(response);
+ await _authenticationStateProvider.GetAuthenticationStateAsync();
+
+ return response;
+ }
+
+ public async Task LogoutAsync()
+ {
+ await _authenticationStorage.SetAccessTokenAsync(new LoginProxyResponse());
+ await _authenticationStateProvider.GetAuthenticationStateAsync();
}
}
\ No newline at end of file
diff --git a/sources/Clients.Identity.Blazor.Shared/Authentications/IAuthenticationManager.cs b/sources/Clients.Identity.Blazor.Shared/Authentications/IAuthenticationManager.cs
index 225d6ad..cee5152 100644
--- a/sources/Clients.Identity.Blazor.Shared/Authentications/IAuthenticationManager.cs
+++ b/sources/Clients.Identity.Blazor.Shared/Authentications/IAuthenticationManager.cs
@@ -5,4 +5,5 @@ namespace MadWorldNL.Clients.Identity.Blazor.Shared.Authentications;
public interface IAuthenticationManager
{
Task LoginAsync(LoginProxyRequest request);
+ Task LogoutAsync();
}
\ No newline at end of file
diff --git a/sources/Clients.Identity.Blazor.Shared/Authentications/IAuthenticationStorage.cs b/sources/Clients.Identity.Blazor.Shared/Authentications/IAuthenticationStorage.cs
new file mode 100644
index 0000000..538a6cb
--- /dev/null
+++ b/sources/Clients.Identity.Blazor.Shared/Authentications/IAuthenticationStorage.cs
@@ -0,0 +1,9 @@
+using MadWorldNL.Clients.Identity.Api.Contracts.Authentications;
+
+namespace MadWorldNL.Clients.Identity.Blazor.Shared.Authentications;
+
+public interface IAuthenticationStorage
+{
+ Task SetAccessTokenAsync(LoginProxyResponse response);
+ Task GetAccessTokenAsync();
+}
\ No newline at end of file
diff --git a/sources/Clients.Identity.Blazor.Shared/Authentications/MyAuthenticationStateProvider.cs b/sources/Clients.Identity.Blazor.Shared/Authentications/MyAuthenticationStateProvider.cs
index 4c9c310..5fd75c2 100644
--- a/sources/Clients.Identity.Blazor.Shared/Authentications/MyAuthenticationStateProvider.cs
+++ b/sources/Clients.Identity.Blazor.Shared/Authentications/MyAuthenticationStateProvider.cs
@@ -1,3 +1,4 @@
+using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using Microsoft.AspNetCore.Components.Authorization;
@@ -5,11 +6,39 @@ namespace MadWorldNL.Clients.Identity.Blazor.Shared.Authentications;
public class MyAuthenticationStateProvider : AuthenticationStateProvider
{
- public override Task GetAuthenticationStateAsync()
+ private readonly IAuthenticationStorage _authenticationStorage;
+
+ public MyAuthenticationStateProvider(IAuthenticationStorage authenticationStorage)
+ {
+ _authenticationStorage = authenticationStorage;
+ }
+
+ public override async Task GetAuthenticationStateAsync()
{
- var state = new AuthenticationState(new ClaimsPrincipal());
+ var accessToken = await _authenticationStorage.GetAccessTokenAsync();
+
+ var identity = new ClaimsIdentity();
+ if (accessToken.IsSuccess)
+ {
+ identity = RetrieveUserFromJwt(accessToken.AccessToken);
+ }
+
+ var state = new AuthenticationState(new ClaimsPrincipal(identity));
NotifyAuthenticationStateChanged(Task.FromResult(state));
- return Task.FromResult(state);
+ return state;
+ }
+
+ private static ClaimsIdentity RetrieveUserFromJwt(string jwt)
+ {
+ var claims = ParseClaimsFromJwt(jwt).ToList();
+ return new ClaimsIdentity(claims, "jwt", "nameid", "role");
+ }
+
+ private static IEnumerable ParseClaimsFromJwt(string jwt)
+ {
+ var handler = new JwtSecurityTokenHandler();
+ var token = handler.ReadJwtToken(jwt);
+ return token.Claims;
}
}
\ No newline at end of file
diff --git a/sources/Clients.Identity.Blazor.Shared/Clients.Identity.Blazor.Shared.csproj b/sources/Clients.Identity.Blazor.Shared/Clients.Identity.Blazor.Shared.csproj
index 8ac321f..1bf6074 100644
--- a/sources/Clients.Identity.Blazor.Shared/Clients.Identity.Blazor.Shared.csproj
+++ b/sources/Clients.Identity.Blazor.Shared/Clients.Identity.Blazor.Shared.csproj
@@ -10,21 +10,19 @@
+
+
-
-
-
-
diff --git a/sources/Clients.Identity.Blazor.Shared/Extensions/WebAssemblyHostBuilderExtensions.cs b/sources/Clients.Identity.Blazor.Shared/Extensions/WebAssemblyHostBuilderExtensions.cs
index 97c0b65..59c75dc 100644
--- a/sources/Clients.Identity.Blazor.Shared/Extensions/WebAssemblyHostBuilderExtensions.cs
+++ b/sources/Clients.Identity.Blazor.Shared/Extensions/WebAssemblyHostBuilderExtensions.cs
@@ -20,6 +20,7 @@ public static void AddIdentity(this WebAssemblyHostBuilder builder)
builder.Services.AddScoped();
builder.Services.AddScoped();
+ builder.Services.AddScoped();
builder.AddIdentityClients();
}
diff --git a/sources/Clients.Identity.Blazor.Shared/Pages/Login.razor b/sources/Clients.Identity.Blazor.Shared/Pages/Login.razor
index 1335119..cc11791 100644
--- a/sources/Clients.Identity.Blazor.Shared/Pages/Login.razor
+++ b/sources/Clients.Identity.Blazor.Shared/Pages/Login.razor
@@ -2,8 +2,6 @@
-@TempLoginMessage
-
You are logged in
diff --git a/sources/Clients.Identity.Blazor.Shared/Pages/Login.razor.cs b/sources/Clients.Identity.Blazor.Shared/Pages/Login.razor.cs
index 235eb05..83b2af5 100644
--- a/sources/Clients.Identity.Blazor.Shared/Pages/Login.razor.cs
+++ b/sources/Clients.Identity.Blazor.Shared/Pages/Login.razor.cs
@@ -11,11 +11,10 @@ public partial class Login
private LoginProxyRequest _loginRequest = new();
private bool _showError = false;
- private string TempLoginMessage = string.Empty;
-
- public async Task LoginAsync()
+ private async Task LoginAsync()
{
var response = await AuthenticationManager.LoginAsync(_loginRequest);
+ StateHasChanged();
if (!response.IsSuccess)
{
@@ -25,7 +24,5 @@ public async Task LoginAsync()
}
_showError = false;
-
- TempLoginMessage = response.Expiration.ToString();
}
}
\ No newline at end of file
diff --git a/sources/Clients.Identity.Blazor.Shared/Pages/Logout.razor b/sources/Clients.Identity.Blazor.Shared/Pages/Logout.razor
new file mode 100644
index 0000000..ba456be
--- /dev/null
+++ b/sources/Clients.Identity.Blazor.Shared/Pages/Logout.razor
@@ -0,0 +1,13 @@
+@page "/Logout"
+@using MadWorldNL.Clients.Identity.Blazor.Shared.Authentications
+You are logged out now!
+
+@code {
+ [Inject] public IAuthenticationManager AuthenticationManager { get; set; } = null!;
+
+ protected override async Task OnInitializedAsync()
+ {
+ await AuthenticationManager.LogoutAsync();
+ }
+
+}
\ No newline at end of file
diff --git a/sources/Directory.Packages.props b/sources/Directory.Packages.props
index 5dbb194..c37da38 100644
--- a/sources/Directory.Packages.props
+++ b/sources/Directory.Packages.props
@@ -1,5 +1,6 @@
+
@@ -9,16 +10,16 @@
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
@@ -29,7 +30,7 @@
-
+