Skip to content

Commit

Permalink
Add login session
Browse files Browse the repository at this point in the history
  • Loading branch information
oveldman committed Apr 11, 2024
1 parent 6eac22c commit 749573c
Show file tree
Hide file tree
Showing 13 changed files with 131 additions and 31 deletions.
17 changes: 13 additions & 4 deletions sources/Clients.Admin.Web/Layout/MainLayout.razor
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,22 @@

<main>
<div class="top-row px-4">
<RadzenComponents/>
<NavLink class="nav-link" href="Login">
Login
</NavLink>
<AuthorizeView>
<Authorized>
<NavLink class="nav-link" href="Logout">
Logout
</NavLink>
</Authorized>
<NotAuthorized>
<NavLink class="nav-link" href="Login">
Login
</NavLink>
</NotAuthorized>
</AuthorizeView>
</div>

<article class="content px-4">
<RadzenComponents/>
@Body
</article>
</main>
Expand Down
2 changes: 2 additions & 0 deletions sources/Clients.Admin.Web/Program.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using Blazored.LocalStorage;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using MadWorldNL.Clients.Admin.Web;
Expand All @@ -9,6 +10,7 @@
builder.RootComponents.Add<HeadOutlet>("head::after");

builder.Services.AddRadzenComponents();
builder.Services.AddBlazoredLocalStorage();

builder.AddIdentity();

Expand Down
Original file line number Diff line number Diff line change
@@ -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<LoginProxyResponse> GetAccessTokenAsync()
{
return await _localStorage.GetItemAsync<LoginProxyResponse>(AuthenticationResponseName)
?? new LoginProxyResponse();
}
}
Original file line number Diff line number Diff line change
@@ -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<LoginProxyResponse> 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();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ namespace MadWorldNL.Clients.Identity.Blazor.Shared.Authentications;
public interface IAuthenticationManager
{
Task<LoginProxyResponse> LoginAsync(LoginProxyRequest request);
Task LogoutAsync();
}
Original file line number Diff line number Diff line change
@@ -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<LoginProxyResponse> GetAccessTokenAsync();
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,44 @@
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using Microsoft.AspNetCore.Components.Authorization;

namespace MadWorldNL.Clients.Identity.Blazor.Shared.Authentications;

public class MyAuthenticationStateProvider : AuthenticationStateProvider
{
public override Task<AuthenticationState> GetAuthenticationStateAsync()
private readonly IAuthenticationStorage _authenticationStorage;

public MyAuthenticationStateProvider(IAuthenticationStorage authenticationStorage)
{
_authenticationStorage = authenticationStorage;
}

public override async Task<AuthenticationState> 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<Claim> ParseClaimsFromJwt(string jwt)
{
var handler = new JwtSecurityTokenHandler();
var token = handler.ReadJwtToken(jwt);
return token.Claims;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,19 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Blazored.LocalStorage" />
<PackageReference Include="Microsoft.AspNetCore.Components.Web" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" />
<PackageReference Include="Microsoft.Extensions.Http" />
<PackageReference Include="Radzen.Blazor" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Clients.Identity.Api.Contracts\Clients.Identity.Api.Contracts.csproj" />
</ItemGroup>

<ItemGroup>
<PackageVersion Update="Microsoft.AspNetCore.Components.Web" Version="8.0.3" />
</ItemGroup>

<ItemGroup>
<UpToDateCheckInput Remove="RadzenExtra\ErrorMessage.razor" />
<UpToDateCheckInput Remove="RadzenExtra\TestTest.razor" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public static void AddIdentity(this WebAssemblyHostBuilder builder)

builder.Services.AddScoped<IAuthenticationManager, AuthenticationManager>();
builder.Services.AddScoped<IAuthenticationService, AuthenticationService>();
builder.Services.AddScoped<IAuthenticationStorage, AuthenticationLocalStorage>();

builder.AddIdentityClients();
}
Expand Down
2 changes: 0 additions & 2 deletions sources/Clients.Identity.Blazor.Shared/Pages/Login.razor
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

<ErrorMessage Show="@_showError" Message="There was an error logging in. " />

@TempLoginMessage

<AuthorizeView>
<Authorized>
<h1>You are logged in</h1>
Expand Down
7 changes: 2 additions & 5 deletions sources/Clients.Identity.Blazor.Shared/Pages/Login.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -25,7 +24,5 @@ public async Task LoginAsync()
}

_showError = false;

TempLoginMessage = response.Expiration.ToString();
}
}
13 changes: 13 additions & 0 deletions sources/Clients.Identity.Blazor.Shared/Pages/Logout.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
@page "/Logout"
@using MadWorldNL.Clients.Identity.Blazor.Shared.Authentications
<h3>You are logged out now!</h3>

@code {
[Inject] public IAuthenticationManager AuthenticationManager { get; set; } = null!;

protected override async Task OnInitializedAsync()
{
await AuthenticationManager.LogoutAsync();
}

}
23 changes: 12 additions & 11 deletions sources/Directory.Packages.props
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<Project>
<ItemGroup>
<PackageVersion Include="Blazored.LocalStorage" Version="4.5.0" />
<PackageVersion Include="Google.Protobuf" Version="3.26.1" />
<PackageVersion Include="Grpc.AspNetCore" Version="2.62.0" />
<PackageVersion Include="Grpc.AspNetCore.Server.Reflection" Version="2.62.0" />
Expand All @@ -9,16 +10,16 @@
<PackageVersion Include="MadWorldNL.Common" Version="1.0.3" />
<PackageVersion Include="MadWorldNL.Common.AspNetCore" Version="1.0.3" />
<PackageVersion Include="MadWorldNL.Common.Grpc" Version="1.0.3" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.3" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="8.0.3" />
<PackageVersion Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="8.0.3" />
<PackageVersion Include="Microsoft.AspNetCore.Identity.UI" Version="8.0.3" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="8.0.3" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="8.0.3" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly" Version="8.0.3" />
<PackageVersion Include="Microsoft.AspNetCore.Components.Web" Version="8.0.2" />
<PackageVersion Include="Microsoft.AspNetCore.OpenApi" Version="8.0.3" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.3">
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.4" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="8.0.4" />
<PackageVersion Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="8.0.4" />
<PackageVersion Include="Microsoft.AspNetCore.Identity.UI" Version="8.0.4" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="8.0.4" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="8.0.4" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly" Version="8.0.4" />
<PackageVersion Include="Microsoft.AspNetCore.Components.Web" Version="8.0.4" />
<PackageVersion Include="Microsoft.AspNetCore.OpenApi" Version="8.0.4" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.4">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageVersion>
Expand All @@ -29,7 +30,7 @@
<PackageVersion Include="Microsoft.IdentityModel.Tokens" Version="7.5.1" />
<PackageVersion Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.2" />
<PackageVersion Include="Npgsql.EntityFrameworkCore.PostgreSQL.Design" Version="1.1.0" />
<PackageVersion Include="Radzen.Blazor" Version="4.29.2" />
<PackageVersion Include="Radzen.Blazor" Version="4.29.6" />
<PackageVersion Include="Respawn" Version="6.2.1" />
<PackageVersion Include="Shouldly" Version="4.2.1" />
<PackageVersion Include="Swashbuckle.AspNetCore" Version="6.5.0" />
Expand Down

0 comments on commit 749573c

Please sign in to comment.