Auth System
This commit is contained in:
13
FoodsharingSiegen.Contracts/StorageKeys.cs
Normal file
13
FoodsharingSiegen.Contracts/StorageKeys.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
namespace FoodsharingSiegen.Contracts
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Sammlung von StorageKeys (Browser LocalStorage)
|
||||||
|
/// </summary>
|
||||||
|
public static class StorageKeys
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The token key
|
||||||
|
/// </summary>
|
||||||
|
public const string TokenKey = "_token";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
<Router AppAssembly="@typeof(App).Assembly">
|
<Router AppAssembly="@typeof(App).Assembly">
|
||||||
<Found Context="routeData">
|
<Found Context="routeData">
|
||||||
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)"/>
|
<AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
|
||||||
|
</AuthorizeRouteView>
|
||||||
<FocusOnNavigate RouteData="@routeData" Selector="h1"/>
|
<FocusOnNavigate RouteData="@routeData" Selector="h1"/>
|
||||||
</Found>
|
</Found>
|
||||||
<NotFound>
|
<NotFound>
|
||||||
|
|||||||
133
FoodsharingSiegen.Server/Auth/AuthHelper.cs
Normal file
133
FoodsharingSiegen.Server/Auth/AuthHelper.cs
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
using System.IdentityModel.Tokens.Jwt;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using System.Text;
|
||||||
|
using Microsoft.IdentityModel.Tokens;
|
||||||
|
|
||||||
|
namespace FoodsharingSiegen.Server.Auth
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The auth helper class (a. beging, 04.04.2022)
|
||||||
|
/// </summary>
|
||||||
|
public static class AuthHelper
|
||||||
|
{
|
||||||
|
#region Public Method Decrypt
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Decrypts the crypted text (a. beging, 04.04.2022)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="cryptedText">The crypted text</param>
|
||||||
|
/// <returns>The string</returns>
|
||||||
|
public static string Decrypt(string cryptedText)
|
||||||
|
{
|
||||||
|
CreateAlgorithm(out var tripleDes);
|
||||||
|
|
||||||
|
var toEncryptArray = Convert.FromBase64String(cryptedText);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var cTransform = tripleDes.CreateDecryptor();
|
||||||
|
var resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
|
||||||
|
|
||||||
|
tripleDes.Clear();
|
||||||
|
|
||||||
|
return Encoding.UTF8.GetString(resultArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Public Method Encrypt
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Encrypts the plain text (a. beging, 04.04.2022)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="plainText">The plain text</param>
|
||||||
|
/// <returns>The string</returns>
|
||||||
|
public static string Encrypt(string plainText)
|
||||||
|
{
|
||||||
|
CreateAlgorithm(out var tripleDes);
|
||||||
|
|
||||||
|
var toEncryptArray = Encoding.UTF8.GetBytes(plainText );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var cTransform = tripleDes.CreateEncryptor();
|
||||||
|
|
||||||
|
var resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
|
||||||
|
|
||||||
|
tripleDes.Clear();
|
||||||
|
|
||||||
|
return Convert.ToBase64String(resultArray, 0, resultArray.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Public Method GetSigningKey
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the signing key (a. beging, 04.04.2022)
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The security key</returns>
|
||||||
|
public static SecurityKey GetSigningKey() => new SymmetricSecurityKey(Encoding.ASCII.GetBytes(SigningKey));
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Public Method ValidateToken
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Validates the token using the specified token (a. beging, 04.04.2022)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="token">The token</param>
|
||||||
|
/// <returns>A task containing the bool</returns>
|
||||||
|
public static async Task<bool> ValidateToken(string? token)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var tokenHandler = new JwtSecurityTokenHandler();
|
||||||
|
var result = await tokenHandler.ValidateTokenAsync(token, new TokenValidationParameters
|
||||||
|
{
|
||||||
|
ValidateIssuerSigningKey = true,
|
||||||
|
IssuerSigningKey = GetSigningKey(),
|
||||||
|
|
||||||
|
ValidateAudience = true,
|
||||||
|
ValidAudience = "FS-Siegen",
|
||||||
|
|
||||||
|
ValidateIssuer = true,
|
||||||
|
ValidIssuer = "FS-Siegen"
|
||||||
|
});
|
||||||
|
|
||||||
|
return result.IsValid;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Private Method CreateAlgorithm
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates the algorithm using the specified triple des (a. beging, 04.04.2022)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tripleDes">The triple des</param>
|
||||||
|
private static void CreateAlgorithm(out TripleDES tripleDes)
|
||||||
|
{
|
||||||
|
var md5 = MD5.Create();
|
||||||
|
var keyArray = md5.ComputeHash(Encoding.UTF8.GetBytes(SigningKey));
|
||||||
|
md5.Clear();
|
||||||
|
|
||||||
|
tripleDes = TripleDES.Create();
|
||||||
|
tripleDes.Key = keyArray;
|
||||||
|
tripleDes.Mode = CipherMode.ECB;
|
||||||
|
tripleDes.Padding = PaddingMode.PKCS7;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The signing key
|
||||||
|
/// </summary>
|
||||||
|
public const string SigningKey = "2uasw2§$%1nd47n9s43&%Zs3529s23&/%AW";
|
||||||
|
}
|
||||||
|
}
|
||||||
147
FoodsharingSiegen.Server/Auth/AuthService.cs
Normal file
147
FoodsharingSiegen.Server/Auth/AuthService.cs
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
using System.IdentityModel.Tokens.Jwt;
|
||||||
|
using System.Security.Claims;
|
||||||
|
using FoodsharingSiegen.Contracts;
|
||||||
|
using FoodsharingSiegen.Contracts.Entity;
|
||||||
|
using FoodsharingSiegen.Server.Data;
|
||||||
|
using FoodsharingSiegen.Server.Data.Service;
|
||||||
|
using FoodsharingSiegen.Server.Service;
|
||||||
|
using Microsoft.AspNetCore.Components.Authorization;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.IdentityModel.Tokens;
|
||||||
|
|
||||||
|
namespace FoodsharingSiegen.Server.Auth
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The auth service class (a. beging, 04.04.2022)
|
||||||
|
/// </summary>
|
||||||
|
/// <seealso cref="ServiceBase"/>
|
||||||
|
public class AuthService : ServiceBase
|
||||||
|
{
|
||||||
|
#region Public Properties
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the value of the user (ab)
|
||||||
|
/// </summary>
|
||||||
|
public User? User { get; set; }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Private Fields
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The authentication state provider
|
||||||
|
/// </summary>
|
||||||
|
private readonly AuthenticationStateProvider _authenticationStateProvider;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The local storage service
|
||||||
|
/// </summary>
|
||||||
|
private readonly LocalStorageService _localStorageService;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Setup/Teardown
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="AuthService"/> class
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="context">The context</param>
|
||||||
|
/// <param name="localStorageService">The local storage service</param>
|
||||||
|
/// <param name="authenticationStateProvider">The authentication state provider</param>
|
||||||
|
public AuthService(FsContext context, LocalStorageService localStorageService, AuthenticationStateProvider authenticationStateProvider) : base(context)
|
||||||
|
{
|
||||||
|
_localStorageService = localStorageService;
|
||||||
|
_authenticationStateProvider = authenticationStateProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Public Method Login
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Logins the mail address (a. beging, 04.04.2022)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="mailAddress">The mail address</param>
|
||||||
|
/// <param name="password">The password</param>
|
||||||
|
/// <returns>A task containing the operation result</returns>
|
||||||
|
public async Task<OperationResult> Login(string mailAddress, string password)
|
||||||
|
{
|
||||||
|
#region Ensure Admin
|
||||||
|
|
||||||
|
var existingTroogS = await Context.Users.AnyAsync(x => x.Mail == "fs@beging.de");
|
||||||
|
if (!existingTroogS)
|
||||||
|
{
|
||||||
|
var troogs = new User
|
||||||
|
{
|
||||||
|
Name = "Andre",
|
||||||
|
Mail = "fs@beging.de",
|
||||||
|
Type = UserType.Admin,
|
||||||
|
Created = DateTime.UtcNow,
|
||||||
|
EncryptedPassword = "qSIxTZo7J8M="
|
||||||
|
};
|
||||||
|
|
||||||
|
await Context.Users.AddAsync(troogs);
|
||||||
|
await Context.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion Ensure Admin
|
||||||
|
|
||||||
|
var encryptedPassword = AuthHelper.Encrypt(password);
|
||||||
|
|
||||||
|
User = await Context.Users.FirstOrDefaultAsync(x => x.Mail.ToLower() == mailAddress.ToLower() && x.EncryptedPassword == encryptedPassword);
|
||||||
|
|
||||||
|
if (User != null)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
// Daten korrekt
|
||||||
|
var tokenHandler = new JwtSecurityTokenHandler();
|
||||||
|
var tokenDescriptor = new SecurityTokenDescriptor
|
||||||
|
{
|
||||||
|
Subject = new ClaimsIdentity(new[]
|
||||||
|
{
|
||||||
|
new Claim(ClaimTypes.NameIdentifier, User.Id.ToString()),
|
||||||
|
}),
|
||||||
|
Expires = DateTime.UtcNow.AddDays(30),
|
||||||
|
Issuer = "FS-Siegen",
|
||||||
|
Audience = "FS-Siegen",
|
||||||
|
SigningCredentials = new SigningCredentials(AuthHelper.GetSigningKey(), SecurityAlgorithms.HmacSha256Signature)
|
||||||
|
};
|
||||||
|
|
||||||
|
var token = tokenHandler.CreateToken(tokenDescriptor);
|
||||||
|
var serializedToken = tokenHandler.WriteToken(token);
|
||||||
|
|
||||||
|
await _localStorageService.SetItem(StorageKeys.TokenKey, serializedToken);
|
||||||
|
|
||||||
|
return new OperationResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
return new OperationResult(new Exception("Invalid"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Public Method Logout
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Logouts this instance (a. beging, 04.04.2022)
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A task containing the operation result</returns>
|
||||||
|
public async Task<OperationResult> Logout()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _localStorageService.RemoveItem(StorageKeys.TokenKey);
|
||||||
|
User = null;
|
||||||
|
((TokenAuthStateProvider) _authenticationStateProvider).MarkUserAsLoggedOut();
|
||||||
|
return new OperationResult();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
return new OperationResult(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
78
FoodsharingSiegen.Server/Auth/LocalStorageService.cs
Normal file
78
FoodsharingSiegen.Server/Auth/LocalStorageService.cs
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
using Microsoft.JSInterop;
|
||||||
|
|
||||||
|
namespace FoodsharingSiegen.Server.Service
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The local storage service class (a. beging, 02.04.2022)
|
||||||
|
/// </summary>
|
||||||
|
public class LocalStorageService
|
||||||
|
{
|
||||||
|
#region Private Fields
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The js runtime
|
||||||
|
/// </summary>
|
||||||
|
private readonly IJSRuntime _jsRuntime;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Setup/Teardown
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="jsRuntime"></param>
|
||||||
|
public LocalStorageService(IJSRuntime jsRuntime) => _jsRuntime = jsRuntime;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Public Method GetItem
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Ein Item aus dem LocalStorage laden
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">Der Key des Items</param>
|
||||||
|
/// <typeparam name="T">Typ des Item</typeparam>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<T?> GetItem<T>(string key)
|
||||||
|
{
|
||||||
|
var json = await _jsRuntime.InvokeAsync<string>("localStorage.getItem", key);
|
||||||
|
|
||||||
|
if (json == null)
|
||||||
|
return default;
|
||||||
|
|
||||||
|
return JsonSerializer.Deserialize<T>(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Public Method RemoveItem
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Ein Item aus dem LocalStorage löschen
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">Der Key des Items</param>
|
||||||
|
public async Task RemoveItem(string key)
|
||||||
|
{
|
||||||
|
await _jsRuntime.InvokeVoidAsync("localStorage.removeItem", key);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Public Method SetItem
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Ein Item in den LocalStorage schreiben
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">Der Key des Items</param>
|
||||||
|
/// <param name="value">Das Item</param>
|
||||||
|
/// <typeparam name="T">Typ des Item</typeparam>
|
||||||
|
public async Task SetItem<T>(string key, T value)
|
||||||
|
{
|
||||||
|
await _jsRuntime.InvokeVoidAsync("localStorage.setItem", key, JsonSerializer.Serialize(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
79
FoodsharingSiegen.Server/Auth/TokenAuthStateProvider.cs
Normal file
79
FoodsharingSiegen.Server/Auth/TokenAuthStateProvider.cs
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
using System.Security.Claims;
|
||||||
|
using FoodsharingSiegen.Contracts;
|
||||||
|
using FoodsharingSiegen.Server.Auth;
|
||||||
|
using Microsoft.AspNetCore.Components.Authorization;
|
||||||
|
|
||||||
|
namespace FoodsharingSiegen.Server.Service
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The token auth state provider class (a. beging, 02.04.2022)
|
||||||
|
/// </summary>
|
||||||
|
/// <seealso cref="AuthenticationStateProvider"/>
|
||||||
|
public class TokenAuthStateProvider : AuthenticationStateProvider
|
||||||
|
{
|
||||||
|
#region Private Fields
|
||||||
|
|
||||||
|
/// <summary> LocalStorageService </summary>
|
||||||
|
private readonly LocalStorageService _localStorageService;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Setup/Teardown
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="localStorageService"></param>
|
||||||
|
public TokenAuthStateProvider(LocalStorageService localStorageService) => _localStorageService = localStorageService;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Override GetAuthenticationStateAsync
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// <summary> Get the current authenticationstate </summary>
|
||||||
|
/// <remarks> A. Beging, 02.02.2022. </remarks>
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
public override async Task<AuthenticationState> GetAuthenticationStateAsync()
|
||||||
|
{
|
||||||
|
var token = await _localStorageService.GetItem<string>(StorageKeys.TokenKey);
|
||||||
|
var tokenValid = await AuthHelper.ValidateToken(token);
|
||||||
|
|
||||||
|
var identity = new ClaimsIdentity();
|
||||||
|
if (tokenValid)
|
||||||
|
identity = new ClaimsIdentity(new[]
|
||||||
|
{
|
||||||
|
new Claim(ClaimTypes.Name, "user")
|
||||||
|
}, "TODO");
|
||||||
|
|
||||||
|
var claimsPrincipal = new ClaimsPrincipal(identity);
|
||||||
|
return new AuthenticationState(claimsPrincipal);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Public Method MarkUserAsAuthenticated
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// <summary> Mark user as authenticated. </summary>
|
||||||
|
/// <remarks> A. Beging, 02.02.2022. </remarks>
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
public void MarkUserAsAuthenticated() => NotifyAuthenticationStateChanged(GetAuthenticationStateAsync());
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Public Method MarkUserAsLoggedOut
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Marks the user as logged out (a. beging, 02.04.2022)
|
||||||
|
/// </summary>
|
||||||
|
public void MarkUserAsLoggedOut()
|
||||||
|
{
|
||||||
|
var anonymousUser = new ClaimsPrincipal(new ClaimsIdentity());
|
||||||
|
var authState = Task.FromResult(new AuthenticationState(anonymousUser));
|
||||||
|
NotifyAuthenticationStateChanged(authState);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
29
FoodsharingSiegen.Server/Pages/Login.razor
Normal file
29
FoodsharingSiegen.Server/Pages/Login.razor
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
@page "/login"
|
||||||
|
@using FoodsharingSiegen.Server.Service
|
||||||
|
@using FoodsharingSiegen.Server.Auth
|
||||||
|
@layout LoginLayout
|
||||||
|
|
||||||
|
@inject AuthService AuthService
|
||||||
|
@inject NavigationManager NavigationManager
|
||||||
|
|
||||||
|
@code
|
||||||
|
{
|
||||||
|
private string? Mailaddress { get; set; }
|
||||||
|
|
||||||
|
private string? Password { get; set; }
|
||||||
|
|
||||||
|
private async Task PerformLogin()
|
||||||
|
{
|
||||||
|
//Todo Eingaben Validieren [04.04.22 - Andre Beging]
|
||||||
|
|
||||||
|
var loginR = await AuthService.Login(Mailaddress, Password);
|
||||||
|
if (loginR.Success)
|
||||||
|
{
|
||||||
|
NavigationManager.NavigateTo("/", true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
<TextEdit @bind-Text="Mailaddress" Placeholder="Mail"></TextEdit>
|
||||||
|
<TextEdit @bind-Text="Password" Placeholder="Password"></TextEdit>
|
||||||
|
<Button Clicked="PerformLogin">Go</Button>
|
||||||
17
FoodsharingSiegen.Server/Pages/Logout.razor
Normal file
17
FoodsharingSiegen.Server/Pages/Logout.razor
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
@layout LoginLayout
|
||||||
|
@page "/logout"
|
||||||
|
@using FoodsharingSiegen.Server.Service
|
||||||
|
@using FoodsharingSiegen.Server.Auth
|
||||||
|
|
||||||
|
@inject AuthService AuthService
|
||||||
|
@inject NavigationManager NavigationManager
|
||||||
|
|
||||||
|
@code {
|
||||||
|
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
var logoutR = await AuthService.Logout();
|
||||||
|
if(logoutR.Success) NavigationManager.NavigateTo("/");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -5,4 +5,4 @@
|
|||||||
Layout = "_Layout";
|
Layout = "_Layout";
|
||||||
}
|
}
|
||||||
|
|
||||||
<component type="typeof(App)" render-mode="ServerPrerendered"/>
|
<component type="typeof(App)" render-mode="Server"/>
|
||||||
@@ -1,8 +1,11 @@
|
|||||||
using Blazorise;
|
using Blazorise;
|
||||||
using Blazorise.Icons.Material;
|
using Blazorise.Icons.Material;
|
||||||
using Blazorise.Material;
|
using Blazorise.Material;
|
||||||
|
using FoodsharingSiegen.Server.Auth;
|
||||||
using FoodsharingSiegen.Server.Data;
|
using FoodsharingSiegen.Server.Data;
|
||||||
using FoodsharingSiegen.Server.Data.Service;
|
using FoodsharingSiegen.Server.Data.Service;
|
||||||
|
using FoodsharingSiegen.Server.Service;
|
||||||
|
using Microsoft.AspNetCore.Components.Authorization;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
@@ -15,7 +18,11 @@ builder.Services.AddDbContextFactory<FsContext>(opt =>
|
|||||||
opt.UseSqlite($"Data Source=app.db"));
|
opt.UseSqlite($"Data Source=app.db"));
|
||||||
|
|
||||||
// DI
|
// DI
|
||||||
|
builder.Services.AddScoped<LocalStorageService>();
|
||||||
|
builder.Services.AddScoped<AuthenticationStateProvider, TokenAuthStateProvider>();
|
||||||
|
|
||||||
builder.Services.AddScoped<FsContext>();
|
builder.Services.AddScoped<FsContext>();
|
||||||
|
builder.Services.AddScoped<AuthService>();
|
||||||
builder.Services.AddScoped<UserService>();
|
builder.Services.AddScoped<UserService>();
|
||||||
builder.Services.AddScoped<ProspectService>();
|
builder.Services.AddScoped<ProspectService>();
|
||||||
|
|
||||||
|
|||||||
11
FoodsharingSiegen.Server/Shared/LoginLayout.razor
Normal file
11
FoodsharingSiegen.Server/Shared/LoginLayout.razor
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
@inherits LayoutComponentBase
|
||||||
|
|
||||||
|
<PageTitle>Login</PageTitle>
|
||||||
|
|
||||||
|
<div class="page">
|
||||||
|
<main>
|
||||||
|
<article class="content px-4">
|
||||||
|
@Body
|
||||||
|
</article>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
<PageTitle>FoodsharingSiegen.Server</PageTitle>
|
<PageTitle>FoodsharingSiegen.Server</PageTitle>
|
||||||
|
|
||||||
|
<AuthorizeView>
|
||||||
|
<Authorized>
|
||||||
<div class="page">
|
<div class="page">
|
||||||
<div class="sidebar">
|
<div class="sidebar">
|
||||||
<NavMenu/>
|
<NavMenu/>
|
||||||
@@ -17,3 +19,8 @@
|
|||||||
</article>
|
</article>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
|
</Authorized>
|
||||||
|
<NotAuthorized>
|
||||||
|
<RedirectToLogin/>
|
||||||
|
</NotAuthorized>
|
||||||
|
</AuthorizeView>
|
||||||
@@ -19,9 +19,13 @@
|
|||||||
<span class="fas fa-users mr-1" aria-hidden="true" style="font-size: 1.4em;"></span> Benutzer
|
<span class="fas fa-users mr-1" aria-hidden="true" style="font-size: 1.4em;"></span> Benutzer
|
||||||
</NavLink>
|
</NavLink>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="nav-item px-3 pt-5">
|
||||||
|
<NavLink class="nav-link" href="logout" Match="NavLinkMatch.All">
|
||||||
|
<span class="fa-solid fa-door-open mr-1" aria-hidden="true" style="font-size: 1.4em;"></span> Ausloggen
|
||||||
|
</NavLink>
|
||||||
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private bool collapseNavMenu = true;
|
private bool collapseNavMenu = true;
|
||||||
|
|
||||||
|
|||||||
10
FoodsharingSiegen.Server/Shared/RedirectToLogin.razor
Normal file
10
FoodsharingSiegen.Server/Shared/RedirectToLogin.razor
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
@inject NavigationManager NavigationManager
|
||||||
|
|
||||||
|
@code
|
||||||
|
{
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
NavigationManager.NavigateTo("/login");
|
||||||
|
await base.OnInitializedAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user