Switch to JWT authentication (#32)
* switch to jwt authentication * update api to main/jwt * bump version Co-authored-by: rootdarkarchon <root.darkarchon@outlook.com>
This commit is contained in:
		
							
								
								
									
										2
									
								
								MareAPI
									
									
									
									
									
								
							
							
								
								
								
								
								
							
						
						
									
										2
									
								
								MareAPI
									
									
									
									
									
								
							 Submodule MareAPI updated: c01c4990d4...6645eaf63f
									
								
							| @@ -3,7 +3,7 @@ | |||||||
|   <PropertyGroup> |   <PropertyGroup> | ||||||
|     <Authors></Authors> |     <Authors></Authors> | ||||||
|     <Company></Company> |     <Company></Company> | ||||||
|     <Version>0.5.18</Version> |     <Version>0.5.19</Version> | ||||||
|     <Description></Description> |     <Description></Description> | ||||||
|     <Copyright></Copyright> |     <Copyright></Copyright> | ||||||
|     <PackageProjectUrl>https://github.com/Penumbra-Sync/client</PackageProjectUrl> |     <PackageProjectUrl>https://github.com/Penumbra-Sync/client</PackageProjectUrl> | ||||||
|   | |||||||
| @@ -512,7 +512,7 @@ public class SettingsUi : Window, IDisposable | |||||||
|             { |             { | ||||||
|                 _configuration.FullPause = marePaused; |                 _configuration.FullPause = marePaused; | ||||||
|                 _configuration.Save(); |                 _configuration.Save(); | ||||||
|                 Task.Run(_apiController.CreateConnections); |                 Task.Run(() => _apiController.CreateConnections(false)); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             UiShared.DrawHelpText("Completely pauses the sync and clears your current data (not uploaded files) on the service."); |             UiShared.DrawHelpText("Completely pauses the sync and clears your current data (not uploaded files) on the service."); | ||||||
|   | |||||||
| @@ -395,7 +395,7 @@ public class UiShared : IDisposable | |||||||
|             { |             { | ||||||
|                 _pluginConfiguration.FullPause = false; |                 _pluginConfiguration.FullPause = false; | ||||||
|                 _pluginConfiguration.Save(); |                 _pluginConfiguration.Save(); | ||||||
|                 Task.Run(_apiController.CreateConnections); |                 Task.Run(() => _apiController.CreateConnections(true)); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -432,7 +432,7 @@ public class UiShared : IDisposable | |||||||
|                     _pluginConfiguration.ClientSecret[_pluginConfiguration.ApiUri] = _secretKey; |                     _pluginConfiguration.ClientSecret[_pluginConfiguration.ApiUri] = _secretKey; | ||||||
|                     _pluginConfiguration.Save(); |                     _pluginConfiguration.Save(); | ||||||
|                     _secretKey = string.Empty; |                     _secretKey = string.Empty; | ||||||
|                     Task.Run(_apiController.CreateConnections); |                     Task.Run(() => _apiController.CreateConnections(true)); | ||||||
|                     _enterSecretKey = false; |                     _enterSecretKey = false; | ||||||
|                     callBackOnExit?.Invoke(); |                     callBackOnExit?.Invoke(); | ||||||
|                 } |                 } | ||||||
|   | |||||||
| @@ -46,24 +46,26 @@ public partial class ApiController | |||||||
|     private async Task<string> DownloadFileHttpClient(Uri url, IProgress<long> progress, CancellationToken ct) |     private async Task<string> DownloadFileHttpClient(Uri url, IProgress<long> progress, CancellationToken ct) | ||||||
|     { |     { | ||||||
|         using var client = new HttpClient(); |         using var client = new HttpClient(); | ||||||
|         client.DefaultRequestHeaders.Add("Authorization", SecretKey); |         client.DefaultRequestHeaders.Add(AuthorizationJwtHeader.Key, AuthorizationJwtHeader.Value); | ||||||
|         int attempts = 0; |         int attempts = 0; | ||||||
|         bool failed = true; |         bool failed = true; | ||||||
|         const int maxAttempts = 10; |         const int maxAttempts = 10; | ||||||
|  |  | ||||||
|         HttpResponseMessage response = null!; |         HttpResponseMessage response = null!; | ||||||
|         HttpStatusCode? lastError = HttpStatusCode.OK; |         HttpStatusCode? lastError = HttpStatusCode.OK; | ||||||
|  |         var bypassUrl = new Uri(url, "?nocache=" + DateTime.UtcNow.Ticks); | ||||||
|  |  | ||||||
|         while (failed && attempts < maxAttempts && !ct.IsCancellationRequested) |         while (failed && attempts < maxAttempts && !ct.IsCancellationRequested) | ||||||
|         { |         { | ||||||
|             try |             try | ||||||
|             { |             { | ||||||
|                 response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead, ct).ConfigureAwait(false); |                 response = await client.GetAsync(bypassUrl, HttpCompletionOption.ResponseHeadersRead, ct).ConfigureAwait(false); | ||||||
|                 response.EnsureSuccessStatusCode(); |                 response.EnsureSuccessStatusCode(); | ||||||
|                 failed = false; |                 failed = false; | ||||||
|             } |             } | ||||||
|             catch (HttpRequestException ex) |             catch (HttpRequestException ex) | ||||||
|             { |             { | ||||||
|                 Logger.Warn($"Attempt {attempts}: Error during download of {url}, HttpStatusCode: {ex.StatusCode}"); |                 Logger.Warn($"Attempt {attempts}: Error during download of {bypassUrl}, HttpStatusCode: {ex.StatusCode}"); | ||||||
|                 lastError = ex.StatusCode; |                 lastError = ex.StatusCode; | ||||||
|                 if (ex.StatusCode is HttpStatusCode.NotFound or HttpStatusCode.Unauthorized) |                 if (ex.StatusCode is HttpStatusCode.NotFound or HttpStatusCode.Unauthorized) | ||||||
|                 { |                 { | ||||||
| @@ -98,13 +100,13 @@ public partial class ApiController | |||||||
|                     progress.Report(bytesRead); |                     progress.Report(bytesRead); | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 Logger.Debug($"{url} downloaded to {fileName}"); |                 Logger.Debug($"{bypassUrl} downloaded to {fileName}"); | ||||||
|                 return fileName; |                 return fileName; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         catch (Exception ex) |         catch (Exception ex) | ||||||
|         { |         { | ||||||
|             Logger.Warn($"Error during file download of {url}", ex); |             Logger.Warn($"Error during file download of {bypassUrl}", ex); | ||||||
|             try |             try | ||||||
|             { |             { | ||||||
|                 File.Delete(fileName); |                 File.Delete(fileName); | ||||||
|   | |||||||
| @@ -3,6 +3,8 @@ using System.Collections.Concurrent; | |||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
| using System.Linq; | using System.Linq; | ||||||
| using System.Net.Http; | using System.Net.Http; | ||||||
|  | using System.Security.Cryptography; | ||||||
|  | using System.Text; | ||||||
| using System.Threading; | using System.Threading; | ||||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||||
| using MareSynchronos.API; | using MareSynchronos.API; | ||||||
| @@ -29,6 +31,8 @@ public partial class ApiController : IDisposable, IMareHubClient | |||||||
|     private readonly DalamudUtil _dalamudUtil; |     private readonly DalamudUtil _dalamudUtil; | ||||||
|     private readonly FileCacheManager _fileDbManager; |     private readonly FileCacheManager _fileDbManager; | ||||||
|     private CancellationTokenSource _connectionCancellationTokenSource; |     private CancellationTokenSource _connectionCancellationTokenSource; | ||||||
|  |     private string _jwtToken = string.Empty; | ||||||
|  |     private KeyValuePair<string, string> AuthorizationJwtHeader => new("Authorization", "Bearer " + _jwtToken); | ||||||
|  |  | ||||||
|     private HubConnection? _mareHub; |     private HubConnection? _mareHub; | ||||||
|  |  | ||||||
| @@ -70,7 +74,7 @@ public partial class ApiController : IDisposable, IMareHubClient | |||||||
|  |  | ||||||
|     private void DalamudUtilOnLogIn() |     private void DalamudUtilOnLogIn() | ||||||
|     { |     { | ||||||
|         Task.Run(CreateConnections); |         Task.Run(() => CreateConnections(true)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -134,7 +138,7 @@ public partial class ApiController : IDisposable, IMareHubClient | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public async Task CreateConnections() |     public async Task CreateConnections(bool forceGetToken = false) | ||||||
|     { |     { | ||||||
|         Logger.Debug("CreateConnections called"); |         Logger.Debug("CreateConnections called"); | ||||||
|  |  | ||||||
| @@ -169,6 +173,24 @@ public partial class ApiController : IDisposable, IMareHubClient | |||||||
|             { |             { | ||||||
|                 Logger.Debug("Building connection"); |                 Logger.Debug("Building connection"); | ||||||
|  |  | ||||||
|  |                 if (string.IsNullOrEmpty(_jwtToken) || forceGetToken) | ||||||
|  |                 { | ||||||
|  |                     Logger.Debug("Requesting new JWT token"); | ||||||
|  |                     using HttpClient httpClient = new(); | ||||||
|  |                     var postUri = new Uri(new Uri(ApiUri | ||||||
|  |                         .Replace("wss://", "https://", StringComparison.OrdinalIgnoreCase) | ||||||
|  |                         .Replace("ws://", "http://", StringComparison.OrdinalIgnoreCase)), MareAuth.AuthFullPath); | ||||||
|  |                     using var sha256 = SHA256.Create(); | ||||||
|  |                     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) | ||||||
|  |                     })).ConfigureAwait(false); | ||||||
|  |                     result.EnsureSuccessStatusCode(); | ||||||
|  |                     _jwtToken = await result.Content.ReadAsStringAsync().ConfigureAwait(false); | ||||||
|  |                     Logger.Debug("JWT Token Success"); | ||||||
|  |                 } | ||||||
|  |  | ||||||
|                 while (!_dalamudUtil.IsPlayerPresent && !token.IsCancellationRequested) |                 while (!_dalamudUtil.IsPlayerPresent && !token.IsCancellationRequested) | ||||||
|                 { |                 { | ||||||
|                     Logger.Debug("Player not loaded in yet, waiting"); |                     Logger.Debug("Player not loaded in yet, waiting"); | ||||||
| @@ -253,7 +275,7 @@ public partial class ApiController : IDisposable, IMareHubClient | |||||||
|  |  | ||||||
|     private Task MareHubOnReconnected(string? arg) |     private Task MareHubOnReconnected(string? arg) | ||||||
|     { |     { | ||||||
|         _ = Task.Run(CreateConnections); |         _ = Task.Run(() => CreateConnections(false)); | ||||||
|         return Task.CompletedTask; |         return Task.CompletedTask; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -332,7 +354,7 @@ public partial class ApiController : IDisposable, IMareHubClient | |||||||
|         return new HubConnectionBuilder() |         return new HubConnectionBuilder() | ||||||
|             .WithUrl(ApiUri + hubName, options => |             .WithUrl(ApiUri + hubName, options => | ||||||
|             { |             { | ||||||
|                 options.Headers.Add("Authorization", SecretKey); |                 options.Headers.Add(AuthorizationJwtHeader); | ||||||
|                 options.Transports = HttpTransportType.WebSockets | HttpTransportType.ServerSentEvents | HttpTransportType.LongPolling; |                 options.Transports = HttpTransportType.WebSockets | HttpTransportType.ServerSentEvents | HttpTransportType.LongPolling; | ||||||
|             }) |             }) | ||||||
|             .WithAutomaticReconnect(new ForeverRetryPolicy()) |             .WithAutomaticReconnect(new ForeverRetryPolicy()) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 rootdarkarchon
					rootdarkarchon