Files
NebulaLauncher/Nebula.Shared/Services/AuthService.cs

99 lines
3.1 KiB
C#
Raw Permalink Normal View History

2025-02-01 18:19:18 +03:00
using System.Net;
using System.Net.Http.Headers;
using System.Text.Json;
using System.Text.Json.Serialization;
2025-01-05 17:05:23 +03:00
using Nebula.Shared.Models.Auth;
using Nebula.Shared.Services.Logging;
2025-02-01 18:19:18 +03:00
using Nebula.Shared.Utils;
2024-12-22 21:38:19 +03:00
2025-01-05 17:05:23 +03:00
namespace Nebula.Shared.Services;
2024-12-22 21:38:19 +03:00
[ServiceRegister]
2025-01-14 22:10:16 +03:00
public class AuthService(
RestService restService,
DebugService debugService,
2025-01-05 17:05:23 +03:00
CancellationService cancellationService)
2024-12-22 21:38:19 +03:00
{
private readonly HttpClient _httpClient = new();
2025-02-01 18:19:18 +03:00
public CurrentAuthInfo? SelectedAuth { get; private set; }
private readonly ILogger _logger = debugService.GetLogger("AuthService");
2024-12-27 19:15:33 +03:00
2025-02-01 18:19:18 +03:00
public async Task Auth(AuthLoginPassword authLoginPassword, string? code = null)
2024-12-22 21:38:19 +03:00
{
var authServer = authLoginPassword.AuthServer;
var login = authLoginPassword.Login;
var password = authLoginPassword.Password;
2025-01-14 22:10:16 +03:00
_logger.Debug($"Auth to {authServer}api/auth/authenticate {login}");
2025-01-14 22:10:16 +03:00
2024-12-28 08:29:01 +03:00
var authUrl = new Uri($"{authServer}api/auth/authenticate");
2024-12-22 21:38:19 +03:00
2025-02-01 18:19:18 +03:00
try
{
var result =
await restService.PostAsync<AuthenticateResponse, AuthenticateRequest>(
new AuthenticateRequest(login, null, password, code), authUrl, cancellationService.Token);
2025-01-14 22:10:16 +03:00
2025-02-01 18:19:18 +03:00
SelectedAuth = new CurrentAuthInfo(result.UserId,
new LoginToken(result.Token, result.ExpireTime), authLoginPassword.Login, authLoginPassword.AuthServer);
}
catch (RestRequestException e)
2024-12-27 19:15:33 +03:00
{
2025-02-01 18:19:18 +03:00
Console.WriteLine(e.Content);
if (e.StatusCode != HttpStatusCode.Unauthorized) throw;
var err = await e.Content.AsJson<AuthDenyError>();
if (err is null) throw;
throw new AuthException(err);
2024-12-27 19:15:33 +03:00
}
2024-12-22 21:38:19 +03:00
}
2025-01-05 17:05:23 +03:00
public void ClearAuth()
{
SelectedAuth = null;
}
2025-02-01 18:19:18 +03:00
public async Task<bool> SetAuth(CurrentAuthInfo info)
2025-01-07 17:01:00 +03:00
{
2025-02-01 18:19:18 +03:00
SelectedAuth = info;
return await EnsureToken();
2025-01-07 17:01:00 +03:00
}
2024-12-22 21:38:19 +03:00
public async Task<bool> EnsureToken()
{
if (SelectedAuth is null) return false;
2025-02-01 18:19:18 +03:00
var authUrl = new Uri($"{SelectedAuth.AuthServer}api/auth/ping");
2024-12-22 21:38:19 +03:00
using var requestMessage = new HttpRequestMessage(HttpMethod.Get, authUrl);
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("SS14Auth", SelectedAuth.Token.Token);
2025-01-05 17:05:23 +03:00
using var resp = await _httpClient.SendAsync(requestMessage, cancellationService.Token);
2024-12-22 21:38:19 +03:00
if (!resp.IsSuccessStatusCode) SelectedAuth = null;
return resp.IsSuccessStatusCode;
}
}
2025-02-01 18:19:18 +03:00
public sealed record CurrentAuthInfo(Guid UserId, LoginToken Token, string Login, string AuthServer);
public record AuthLoginPassword(string Login, string Password, string AuthServer);
2025-01-14 22:10:16 +03:00
2025-02-01 18:19:18 +03:00
public sealed record AuthDenyError(string[] Errors, AuthenticateDenyCode Code);
public sealed class AuthException(AuthDenyError error) : Exception
{
public AuthDenyError Error { get; } = error;
}
[JsonConverter(typeof(JsonStringEnumConverter))]
public enum AuthenticateDenyCode
{
None = 0,
InvalidCredentials = 1,
AccountUnconfirmed = 2,
TfaRequired = 3,
TfaInvalid = 4,
AccountLocked = 5,
}