Refactoring Claims, add Server Side Messaging (#33)

* cache JWT by ApiUri, CharaIdent, SecretKey, refactor auth flow to new api

* add server side message handling

* update client to mainline api

Co-authored-by: rootdarkarchon <root.darkarchon@outlook.com>
This commit is contained in:
rootdarkarchon
2023-01-04 15:53:27 +01:00
committed by GitHub
parent 2404dc3f94
commit 9f5b4c189e
8 changed files with 92 additions and 36 deletions

View File

@@ -78,6 +78,12 @@ public partial class ApiController
_mareHub!.On(nameof(Client_AdminUpdateOrAddForbiddenFile), act);
}
public void OnReceiveServerMessage(Action<MessageSeverity, string> act)
{
if (_initialized) return;
_mareHub!.On(nameof(Client_ReceiveServerMessage), act);
}
public Task Client_UserUpdateClientPairs(ClientPairDto dto)
{
var entry = PairedClients.SingleOrDefault(e => string.Equals(e.OtherUID, dto.OtherUID, System.StringComparison.Ordinal));
@@ -213,4 +219,25 @@ public partial class ApiController
return Task.CompletedTask;
}
public Task Client_ReceiveServerMessage(MessageSeverity severity, string message)
{
switch (severity)
{
case MessageSeverity.Error:
Logger.Error(message);
_dalamudUtil.PrintErrorChat(message);
break;
case MessageSeverity.Warning:
Logger.Warn(message);
_dalamudUtil.PrintWarnChat(message);
break;
case MessageSeverity.Information:
Logger.Info(message);
_dalamudUtil.PrintInfoChat(message);
break;
}
return Task.CompletedTask;
}
}

View File

@@ -12,7 +12,6 @@ using MareSynchronos.FileCache;
using MareSynchronos.Utils;
using MareSynchronos.WebAPI.Utils;
using Microsoft.AspNetCore.Http.Connections;
using Microsoft.AspNetCore.SignalR;
using Microsoft.AspNetCore.SignalR.Client;
using Microsoft.Extensions.Logging;
@@ -20,6 +19,8 @@ namespace MareSynchronos.WebAPI;
public delegate void SimpleStringDelegate(string str);
public record JwtCache(string ApiUrl, string CharaIdent, string SecretKey);
public partial class ApiController : IDisposable, IMareHubClient
{
public const string MainServer = "Lunae Crescere Incipientis (Central Server EU)";
@@ -31,8 +32,8 @@ public partial class ApiController : IDisposable, IMareHubClient
private readonly DalamudUtil _dalamudUtil;
private readonly FileCacheManager _fileDbManager;
private CancellationTokenSource _connectionCancellationTokenSource;
private Dictionary<string, string> _jwtToken = new(StringComparer.Ordinal);
private KeyValuePair<string, string> AuthorizationJwtHeader => new("Authorization", "Bearer " + _jwtToken[SecretKey]);
private Dictionary<JwtCache, string> _jwtToken = new();
private KeyValuePair<string, string> AuthorizationJwtHeader => new("Authorization", "Bearer " + _jwtToken.GetValueOrDefault(new JwtCache(ApiUri, _dalamudUtil.PlayerNameHashed, SecretKey), string.Empty));
private HubConnection? _mareHub;
@@ -41,6 +42,7 @@ public partial class ApiController : IDisposable, IMareHubClient
private ConnectionDto? _connectionDto;
public ServerInfoDto ServerInfo => _connectionDto?.ServerInfo ?? new ServerInfoDto();
public string AuthFailureMessage { get; private set; } = string.Empty;
public SystemInfoDto SystemInfoDto { get; private set; } = new();
public bool IsModerator => (_connectionDto?.IsAdmin ?? false) || (_connectionDto?.IsModerator ?? false);
@@ -167,15 +169,17 @@ public partial class ApiController : IDisposable, IMareHubClient
continue;
}
AuthFailureMessage = string.Empty;
await StopConnection(token).ConfigureAwait(false);
try
{
Logger.Debug("Building connection");
if (!_jwtToken.TryGetValue(SecretKey, out var jwtToken) || forceGetToken)
if (!_jwtToken.TryGetValue(new JwtCache(ApiUri, _dalamudUtil.PlayerNameHashed, SecretKey), out var jwtToken) || forceGetToken)
{
Logger.Debug("Requesting new JWT token");
Logger.Debug("Requesting new JWT");
using HttpClient httpClient = new();
var postUri = new Uri(new Uri(ApiUri
.Replace("wss://", "https://", StringComparison.OrdinalIgnoreCase)
@@ -184,11 +188,13 @@ public partial class ApiController : IDisposable, IMareHubClient
var auth = BitConverter.ToString(sha256.ComputeHash(Encoding.UTF8.GetBytes(SecretKey))).Replace("-", "", StringComparison.OrdinalIgnoreCase);
var result = await httpClient.PostAsync(postUri, new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("auth", auth)
new KeyValuePair<string, string>("auth", auth),
new KeyValuePair<string, string>("charaIdent", _dalamudUtil.PlayerNameHashed)
})).ConfigureAwait(false);
AuthFailureMessage = await result.Content.ReadAsStringAsync().ConfigureAwait(false);
result.EnsureSuccessStatusCode();
_jwtToken[SecretKey] = await result.Content.ReadAsStringAsync().ConfigureAwait(false);
Logger.Debug("JWT Token Success");
_jwtToken[new JwtCache(ApiUri, _dalamudUtil.PlayerNameHashed, SecretKey)] = await result.Content.ReadAsStringAsync().ConfigureAwait(false);
Logger.Debug("JWT Success");
}
while (!_dalamudUtil.IsPlayerPresent && !token.IsCancellationRequested)
@@ -203,9 +209,10 @@ public partial class ApiController : IDisposable, IMareHubClient
await _mareHub.StartAsync(token).ConfigureAwait(false);
OnReceiveServerMessage((sev, msg) => Client_ReceiveServerMessage(sev, msg));
OnUpdateSystemInfo((dto) => Client_UpdateSystemInfo(dto));
_connectionDto = await Heartbeat(_dalamudUtil.PlayerNameHashed).ConfigureAwait(false);
_connectionDto = await GetConnectionDto().ConfigureAwait(false);
ServerState = ServerState.Connected;
@@ -225,24 +232,6 @@ public partial class ApiController : IDisposable, IMareHubClient
_mareHub.Reconnected += MareHubOnReconnected;
}
}
catch (HubException ex)
{
if (ex.Message.Contains("unauthorized", StringComparison.OrdinalIgnoreCase))
{
Logger.Warn(ex.Message);
ServerState = ServerState.Unauthorized;
await StopConnection(token).ConfigureAwait(false);
return;
}
Logger.Warn(ex.GetType().ToString());
Logger.Warn(ex.Message);
Logger.Warn(ex.StackTrace ?? string.Empty);
ServerState = ServerState.RateLimited;
await StopConnection(token).ConfigureAwait(false);
return;
}
catch (HttpRequestException ex)
{
Logger.Warn(ex.GetType().ToString());
@@ -423,6 +412,11 @@ public partial class ApiController : IDisposable, IMareHubClient
return await _mareHub!.InvokeAsync<ConnectionDto>(nameof(Heartbeat), characterIdentification).ConfigureAwait(false);
}
public async Task<ConnectionDto> GetConnectionDto()
{
return await _mareHub!.InvokeAsync<ConnectionDto>(nameof(GetConnectionDto)).ConfigureAwait(false);
}
public async Task<bool> CheckClientHealth()
{
return await _mareHub!.InvokeAsync<bool>(nameof(CheckClientHealth)).ConfigureAwait(false);