LANCommander/LANCommander.Launcher.Services/AuthenticationService.cs

216 lines
6.1 KiB
C#
Raw Permalink Normal View History

2025-01-15 02:28:11 -06:00
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using LANCommander.SDK.Abstractions;
2025-10-08 19:51:44 -05:00
using LANCommander.SDK.Extensions;
using LANCommander.SDK.Models;
using LANCommander.SDK.Providers;
using LANCommander.SDK.Services;
using Microsoft.Extensions.DependencyInjection;
2025-01-15 02:28:11 -06:00
using Microsoft.Extensions.Logging;
namespace LANCommander.Launcher.Services;
public class AuthenticationService(
ITokenProvider tokenProvider,
2025-10-02 19:41:47 -05:00
ISettingsProvider settingsProvider,
IServiceScopeFactory scopeFactory,
IConnectionClient connectionClient,
AuthenticationClient authenticationClient,
ILogger<AuthenticationService> logger) : BaseService(logger)
2025-01-15 02:28:11 -06:00
{
private bool TemporarilyOffline;
2025-01-15 02:28:11 -06:00
public bool IsConnected()
{
return connectionClient.IsConnected();
}
2025-01-15 02:28:11 -06:00
public async Task<bool> IsServerOnlineAsync()
{
try
{
2025-10-08 19:51:44 -05:00
logger.LogDebug("Checking if server is online");
return await connectionClient.PingAsync();
2025-01-15 02:28:11 -06:00
}
catch
{
logger.LogDebug("Server could not be reached");
2025-01-15 02:28:11 -06:00
}
return false;
2025-01-15 02:28:11 -06:00
}
public async Task Login()
{
2025-10-08 19:51:44 -05:00
using (var op = logger.BeginDebugOperation("Logging in using stored credentials"))
{
2025-11-19 00:36:03 -06:00
await Login(settingsProvider.CurrentValue.Authentication.ServerAddress, settingsProvider.CurrentValue.Authentication.Token);
2025-10-08 19:51:44 -05:00
op.Complete();
}
}
public async Task Login(Uri serverAddress, string username, string password)
{
2025-10-08 19:51:44 -05:00
using (var op = logger.BeginDebugOperation("Logging in using username/password"))
{
await connectionClient.UpdateServerAddressAsync(serverAddress.ToString());
var token = await authenticationClient.AuthenticateAsync(username, password, serverAddress);
2025-10-08 19:51:44 -05:00
await Login(serverAddress, token);
op.Complete();
}
}
public async Task Login(Uri serverAddress, SDK.Models.AuthToken token)
{
try
{
2025-10-08 19:51:44 -05:00
using (var op = logger.BeginDebugOperation("Logging in using token"))
{
await connectionClient.UpdateServerAddressAsync(serverAddress.ToString());
2025-11-19 00:36:03 -06:00
tokenProvider.SetToken(token);
if (await authenticationClient.ValidateTokenAsync())
2025-10-08 19:51:44 -05:00
{
//SetOfflineMode(false);
TemporarilyOffline = false;
settingsProvider.Update(s =>
{
s.Authentication.ServerAddress = serverAddress;
});
await using var scope = scopeFactory.CreateAsyncScope();
var profileService = scope.ServiceProvider.GetRequiredService<ProfileService>();
2025-10-08 19:51:44 -05:00
await profileService.DownloadProfileInfoAsync();
2025-10-08 19:51:44 -05:00
}
op.Complete();
}
}
2025-10-08 19:51:44 -05:00
catch (Exception ex)
{
2025-10-08 19:51:44 -05:00
logger.LogError(ex, "Error while logging in");
}
}
public async Task Register(string username, string password, string passwordConfirmation)
{
2025-10-08 19:51:44 -05:00
using (var op = logger.BeginDebugOperation("Registering using username/password"))
{
if (String.IsNullOrWhiteSpace(username))
throw new Exception("Username cannot be blank");
2025-10-08 19:51:44 -05:00
if (String.IsNullOrWhiteSpace(password))
throw new Exception("Password cannot be blank");
2025-10-08 19:51:44 -05:00
if (password != passwordConfirmation)
throw new Exception("Passwords do not match");
await authenticationClient.RegisterAsync(username, password, passwordConfirmation);
2025-10-08 19:51:44 -05:00
settingsProvider.Update(s =>
{
s.Authentication.ServerAddress = connectionClient.GetServerAddress();
2025-10-08 19:51:44 -05:00
});
await using var scope = scopeFactory.CreateAsyncScope();
var profileService = scope.ServiceProvider.GetRequiredService<ProfileService>();
await profileService.DownloadProfileInfoAsync();
2025-10-08 19:51:44 -05:00
op.Complete();
}
}
public void LoginOffline()
{
TemporarilyOffline = true;
}
public async Task SetOfflineModeAsync(bool state)
{
2025-10-08 19:51:44 -05:00
logger.LogDebug("Going into offline mode, state: {State}", state);
await connectionClient.EnableOfflineModeAsync();
if (state)
await connectionClient.DisconnectAsync();
}
public async Task Logout()
{
2025-10-08 19:51:44 -05:00
using (var op = logger.BeginDebugOperation("Logging out"))
{
await authenticationClient.LogoutAsync();
2025-10-08 19:51:44 -05:00
TemporarilyOffline = false;
op.Complete();
}
}
2025-01-15 02:28:11 -06:00
public Guid GetUserId()
{
var decodedToken = DecodeToken();
if (decodedToken == null)
return Guid.Empty;
var claim = decodedToken.Claims.First(c => c.Type == ClaimTypes.NameIdentifier);
if (Guid.TryParse(claim.Value, out Guid id))
2025-01-15 02:28:11 -06:00
return id;
return Guid.Empty;
}
public string GetCurrentUserName()
{
var decodedToken = DecodeToken();
if (decodedToken == null)
return String.Empty;
return decodedToken.Claims?.FirstOrDefault(claim => claim.Type == ClaimTypes.Name)?.Value ?? string.Empty;
}
public JwtSecurityToken? DecodeToken()
2025-01-15 02:28:11 -06:00
{
var token = tokenProvider.GetToken();
if (String.IsNullOrEmpty(token?.AccessToken))
2025-01-15 02:28:11 -06:00
return null;
try
{
var handler = new JwtSecurityTokenHandler();
2025-11-19 00:36:03 -06:00
return handler.ReadToken(token.AccessToken) as JwtSecurityToken;
2025-01-15 02:28:11 -06:00
}
catch
2025-01-15 02:28:11 -06:00
{
return null;
}
}
public bool HasStoredCredentials()
{
if (String.IsNullOrEmpty(tokenProvider.GetToken()?.AccessToken))
2025-01-15 02:28:11 -06:00
return false;
var decodedToken = DecodeToken();
return decodedToken != null;
}
public async Task<bool> OfflineModeAvailableAsync()
{
return !(await IsServerOnlineAsync()) && !IsConnected() && HasStoredCredentials();
2025-01-15 02:28:11 -06:00
}
}