mirror of
https://github.com/JogmansonReal/Radicade.git
synced 2026-10-25 15:09:26 -07:00
Radicade Public Code
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using BestHTTP;
|
||||
using Il2CppInterop.Runtime;
|
||||
|
||||
internal static class HubSocketAuth
|
||||
{
|
||||
internal static string Token { get; private set; }
|
||||
|
||||
internal static string LastLoginRefusalCode { get; private set; }
|
||||
|
||||
private static readonly string[] AuthorizationHeaders = { "Authorization", "authorization", "AUTHORIZATION" };
|
||||
|
||||
private static readonly System.Collections.Generic.HashSet<string> Stated = new();
|
||||
|
||||
internal static bool IsServer(string url)
|
||||
{
|
||||
if (!Uri.TryCreate(url, UriKind.Absolute, out var request) ||
|
||||
!Uri.TryCreate(RadicadeEacBypassPlugin.ServerUrl.Value, UriKind.Absolute, out var server)) return false;
|
||||
return request.Host.Equals(server.Host, StringComparison.OrdinalIgnoreCase) && request.Port == server.Port &&
|
||||
(request.Scheme == server.Scheme || request.Scheme == (server.Scheme == "https" ? "wss" : "ws"));
|
||||
}
|
||||
internal static void Capture(HTTPRequest request)
|
||||
{
|
||||
if (request?.Uri == null || !IsServer(request.Uri.ToString())) return;
|
||||
foreach (var name in AuthorizationHeaders)
|
||||
{
|
||||
var values = request.GetHeaderValues(name);
|
||||
if (values == null || values.Count == 0) continue;
|
||||
var value = values[0];
|
||||
if (value != null && value.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
||||
Token = value.Substring(7).Trim();
|
||||
}
|
||||
}
|
||||
internal static void CaptureFromLoginResponse(HTTPRequest request, string url)
|
||||
{
|
||||
if (!IsServer(url) || !new Uri(url).AbsolutePath.EndsWith("/connect/token", StringComparison.OrdinalIgnoreCase)) return;
|
||||
Token = null;
|
||||
var original = request.Callback;
|
||||
request.Callback = DelegateSupport.ConvertDelegate<OnRequestFinishedDelegate>(
|
||||
new Action<HTTPRequest, HTTPResponse>((req, response) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
if (response != null && response.StatusCode == 200)
|
||||
{
|
||||
using var document = JsonDocument.Parse(response.DataAsText);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if (document.RootElement.TryGetProperty("access_token", out var token) &&
|
||||
token.ValueKind == JsonValueKind.String &&
|
||||
!string.IsNullOrWhiteSpace(token.GetString()))
|
||||
{
|
||||
Token = token.GetString();
|
||||
LastLoginRefusalCode = null;
|
||||
Diag.Trace("[Realtime] Login token captured (value omitted)");
|
||||
}
|
||||
else
|
||||
{
|
||||
Token = null;
|
||||
var error = document.RootElement.TryGetProperty("error", out var errorElement) ? errorElement.GetString() : null;
|
||||
var description = document.RootElement.TryGetProperty("error_description", out var descriptionElement) ? descriptionElement.GetString() : null;
|
||||
LastLoginRefusalCode = error;
|
||||
RadicadeEacBypassPlugin.LogSource.LogWarning(
|
||||
"[Realtime] connect/token answered HTTP 200 without an access_token - that is a login REFUSAL, not a login. " +
|
||||
"error='" + (error ?? "-") + "', error_description='" + (description ?? "-") + "'.");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex) { RadicadeEacBypassPlugin.LogSource.LogWarning("[Realtime] Token parse failed: " + ex.GetType().Name); }
|
||||
finally { original?.Invoke(req, response); }
|
||||
}));
|
||||
}
|
||||
internal static void AuthenticateHubRequest(HTTPRequest request, string url)
|
||||
{
|
||||
if (!IsServer(url) || !NameserverRedirect.IsHubUrl(url)) return;
|
||||
if (!string.IsNullOrWhiteSpace(Token))
|
||||
{
|
||||
request.Uri = new Il2CppSystem.Uri(NameserverRedirect.EnsureHubToken(url, Token));
|
||||
request.SetHeader("Authorization", "Bearer " + Token);
|
||||
}
|
||||
Diag.Trace("[Realtime] Hub request " + new Uri(url).AbsolutePath +
|
||||
"; token=" + (NameserverRedirect.HasHubToken(request.Uri.ToString()) ? "present" : "missing"));
|
||||
}
|
||||
|
||||
internal static void AuthenticateServerRequest(HTTPRequest request, string url)
|
||||
{
|
||||
if (request == null || !IsServer(url) || string.IsNullOrWhiteSpace(Token)) return;
|
||||
try
|
||||
{
|
||||
if (IsAnonymousPath(new Uri(url).AbsolutePath)) return;
|
||||
|
||||
foreach (var name in AuthorizationHeaders)
|
||||
{
|
||||
var values = request.GetHeaderValues(name);
|
||||
if (values != null && values.Count > 0) return;
|
||||
}
|
||||
|
||||
request.SetHeader("Authorization", "Bearer " + Token);
|
||||
var path = new Uri(url).AbsolutePath;
|
||||
if (Stated.Add(path))
|
||||
Diag.Trace("[Auth] stated the session token on " + path + " (the client sent none)");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Diag.Warn("[Auth] could not state the token on " + url + ": " + ex.GetType().Name);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsAnonymousPath(string path) =>
|
||||
path.StartsWith("/auth/connect/token", StringComparison.OrdinalIgnoreCase) ||
|
||||
path.StartsWith("/auth/cachedlogin", StringComparison.OrdinalIgnoreCase) ||
|
||||
path.StartsWith("/auth/eac/", StringComparison.OrdinalIgnoreCase) ||
|
||||
path.StartsWith("/images/", StringComparison.OrdinalIgnoreCase) ||
|
||||
path.StartsWith("/cdn/", StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
Reference in New Issue
Block a user