From 1a6574484d0db102686b09a9b9049e7d575f0367 Mon Sep 17 00:00:00 2001 From: John Morgan <70619927+john-s-morgan@users.noreply.github.com> Date: Thu, 18 Dec 2025 15:02:34 +0000 Subject: [PATCH 1/3] fix: sha256 computed hash needs to be used for base64 encoded result --- src/LiveSplit.Racetime/Controller/RacetimeAuthenticator.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/LiveSplit.Racetime/Controller/RacetimeAuthenticator.cs b/src/LiveSplit.Racetime/Controller/RacetimeAuthenticator.cs index 7950578..a5bc360 100644 --- a/src/LiveSplit.Racetime/Controller/RacetimeAuthenticator.cs +++ b/src/LiveSplit.Racetime/Controller/RacetimeAuthenticator.cs @@ -103,8 +103,9 @@ private static string SHA256(string inputStirng) { byte[] bytes = Encoding.ASCII.GetBytes(inputStirng); var sha256 = new SHA256Managed(); - sha256.ComputeHash(bytes); - string base64 = Convert.ToBase64String(bytes); + var hash = sha256.ComputeHash(bytes); + + string base64 = Convert.ToBase64String(hash); base64 = base64.Replace("+", "-"); base64 = base64.Replace("/", "_"); base64 = base64.Replace("=", ""); From c5ff21d84d4a0af37e8c55321311a8ac3d8eec51 Mon Sep 17 00:00:00 2001 From: John Morgan <70619927+john-s-morgan@users.noreply.github.com> Date: Thu, 18 Dec 2025 15:04:57 +0000 Subject: [PATCH 2/3] fix: code_verifier not sent during refresh_token grant --- src/LiveSplit.Racetime/Controller/RacetimeAuthenticator.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/LiveSplit.Racetime/Controller/RacetimeAuthenticator.cs b/src/LiveSplit.Racetime/Controller/RacetimeAuthenticator.cs index a5bc360..1fa3e68 100644 --- a/src/LiveSplit.Racetime/Controller/RacetimeAuthenticator.cs +++ b/src/LiveSplit.Racetime/Controller/RacetimeAuthenticator.cs @@ -152,13 +152,12 @@ private bool TryGetUserInfo() private async Task TryRefreshAccess() { - string request, verifier; + string request; Tuple result; - verifier = GenerateRandomBase64Data(32); if (RefreshToken != null) { - request = $"code={Code}&redirect_uri={RedirectUri}&client_id={s.ClientID}&code_verifier={verifier}&client_secret={s.ClientSecret}&refresh_token={RefreshToken}&grant_type=refresh_token"; + request = $"code={Code}&redirect_uri={RedirectUri}&client_id={s.ClientID}&client_secret={s.ClientSecret}&refresh_token={RefreshToken}&grant_type=refresh_token"; result = await RestRequest(s.TokenEndpoint, request); if (result.Item1 == 200) From d233da30950f7be91be09662da03c23978b80d0a Mon Sep 17 00:00:00 2001 From: John Morgan <70619927+john-s-morgan@users.noreply.github.com> Date: Thu, 18 Dec 2025 15:05:27 +0000 Subject: [PATCH 3/3] fix: verifier should persist across a single Authorize attempt. --- .../Controller/RacetimeAuthenticator.cs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/LiveSplit.Racetime/Controller/RacetimeAuthenticator.cs b/src/LiveSplit.Racetime/Controller/RacetimeAuthenticator.cs index 1fa3e68..91f31c2 100644 --- a/src/LiveSplit.Racetime/Controller/RacetimeAuthenticator.cs +++ b/src/LiveSplit.Racetime/Controller/RacetimeAuthenticator.cs @@ -17,6 +17,8 @@ public enum AuthResult { Pending, Success, Failure, Cancelled, Stale } public class RacetimeAuthenticator { + private string _verifier = string.Empty; + protected readonly IAuthentificationSettings s; protected string Code { get; set; } @@ -173,11 +175,10 @@ private async Task TryRefreshAccess() private async Task TryGetAccess() { - string request, verifier; + string request; Tuple result; - verifier = GenerateRandomBase64Data(32); - request = $"code={Code}&redirect_uri={RedirectUri}&client_id={s.ClientID}&code_verifier={verifier}&client_secret={s.ClientSecret}&scope={s.Scopes}&grant_type=authorization_code"; + request = $"code={Code}&redirect_uri={RedirectUri}&client_id={s.ClientID}&code_verifier={_verifier}&client_secret={s.ClientSecret}&scope={s.Scopes}&grant_type=authorization_code"; result = await RestRequest(s.TokenEndpoint, request); if (result.Item1 == 400) @@ -223,13 +224,15 @@ public void StopLocalEndpoint() private async Task TryGetAuthenticated() { - string reqState, state, verifier = null, challenge, request, response; + string reqState, state, challenge, request, response; + + _verifier = GenerateRandomBase64Data(32); Error = null; reqState = null; state = GenerateRandomBase64Data(32); - verifier = GenerateRandomBase64Data(32); - challenge = SHA256(verifier); + + challenge = SHA256(_verifier); try {