From 8bb73dcdb1ff99e1ef4e39f565d87f9d5353fffc Mon Sep 17 00:00:00 2001 From: Alexa <53471801+Alexa-RR@users.noreply.github.com> Date: Tue, 30 Jun 2026 14:29:55 +0300 Subject: [PATCH] Use native game auth client only --- .../Auth/IdentityServerIntegration.cs | 142 +----------------- .../Controllers/Admin/AdminController.cs | 7 - .../Startup/MiddlewarePipelineExtensions.cs | 3 +- .../admin-ui/src/pages/IdentityServer.tsx | 24 --- 4 files changed, 6 insertions(+), 170 deletions(-) diff --git a/DorkNet.Server/Auth/IdentityServerIntegration.cs b/DorkNet.Server/Auth/IdentityServerIntegration.cs index 69c8ab7..608ed04 100644 --- a/DorkNet.Server/Auth/IdentityServerIntegration.cs +++ b/DorkNet.Server/Auth/IdentityServerIntegration.cs @@ -3,7 +3,6 @@ using System.Security.Claims; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using System.Text; -using System.Text.Json; using Duende.IdentityServer; using Duende.IdentityServer.Models; using Duende.IdentityServer.Services; @@ -130,9 +129,8 @@ public static class RecRoomIdentityServerRegistration internal static class RecRoomIdentityServerConfig { - public const string ClientId = "recroom.client"; - public const string NativeClientId = "recroom"; - public const string NativeClientSecret = "VxZ53kgbbEaRoZAeMe00MagtgD12GLL2"; + public const string ClientId = "recroom"; + public const string ClientSecret = "VxZ53kgbbEaRoZAeMe00MagtgD12GLL2"; public const string GameClientScope = "gameClient"; public const string CachedLoginGrantType = "cached_login"; @@ -159,25 +157,9 @@ internal static class RecRoomIdentityServerConfig new() { ClientId = ClientId, - ClientName = "Rec Room compatibility client", - RequireClientSecret = false, - AllowedGrantTypes = { GrantType.ResourceOwnerPassword, GrantType.RefreshToken, CachedLoginGrantType }, - AllowedScopes = RecRoomScopes(), - AllowOfflineAccess = true, - AccessTokenLifetime = 60 * 60 * 12, - AbsoluteRefreshTokenLifetime = 60 * 60 * 24 * 30, - SlidingRefreshTokenLifetime = 60 * 60 * 24 * 30, - RefreshTokenUsage = TokenUsage.ReUse, - RefreshTokenExpiration = TokenExpiration.Absolute, - UpdateAccessTokenClaimsOnRefresh = true, - AlwaysIncludeUserClaimsInIdToken = true, - }, - new() - { - ClientId = NativeClientId, - ClientName = "Rec Room native client", + ClientName = "Rec Room game client", RequireClientSecret = true, - ClientSecrets = { new Secret(NativeClientSecret.Sha256()) }, + ClientSecrets = { new Secret(ClientSecret.Sha256()) }, AllowedGrantTypes = { GrantType.ResourceOwnerPassword, GrantType.RefreshToken, CachedLoginGrantType }, AllowedScopes = RecRoomScopes(), AllowOfflineAccess = true, @@ -201,7 +183,7 @@ internal static class RecRoomIdentityServerConfig ]; } -public sealed class IdentityServerLegacyTokenRequestMiddleware(RequestDelegate next) +public sealed class IdentityServerGameTokenRequestMiddleware(RequestDelegate next) { public async Task InvokeAsync(HttpContext context) { @@ -218,12 +200,6 @@ public sealed class IdentityServerLegacyTokenRequestMiddleware(RequestDelegate n StringComparer.OrdinalIgnoreCase); var changed = false; - if (!values.ContainsKey("client_id")) - { - values["client_id"] = RecRoomIdentityServerConfig.ClientId; - changed = true; - } - if (IsDevicePasswordGrant(values)) { if (!values.ContainsKey("username") || string.IsNullOrWhiteSpace(values["username"].ToString())) @@ -291,114 +267,6 @@ public sealed class IdentityServerLegacyTokenRequestMiddleware(RequestDelegate n } } -public sealed class IdentityServerTokenResponseMiddleware(RequestDelegate next, DomainConfig domain) -{ - public async Task InvokeAsync(HttpContext context) - { - if (!IsTokenRequest(context)) - { - await next(context); - return; - } - - var originalBody = context.Response.Body; - await using var buffer = new MemoryStream(); - context.Response.Body = buffer; - - await next(context); - - context.Response.Body = originalBody; - buffer.Position = 0; - - if (context.Response.StatusCode != StatusCodes.Status200OK || - !IsJson(context.Response.ContentType)) - { - await buffer.CopyToAsync(originalBody); - return; - } - - using var document = await JsonDocument.ParseAsync(buffer); - var response = new Dictionary(StringComparer.Ordinal); - foreach (var property in document.RootElement.EnumerateObject()) - response[property.Name] = ConvertJsonValue(property.Value); - - if (response.TryGetValue("access_token", out var accessValue) && - accessValue is string accessToken && - !string.IsNullOrWhiteSpace(accessToken)) - { - AddLegacyTokenAliases(response, accessToken); - SetAccessCookie(context, accessToken); - } - - var bytes = JsonSerializer.SerializeToUtf8Bytes(response); - context.Response.ContentLength = bytes.Length; - context.Response.ContentType = "application/json; charset=utf-8"; - await originalBody.WriteAsync(bytes); - } - - private static bool IsTokenRequest(HttpContext context) => - HttpMethods.IsPost(context.Request.Method) - && context.Request.Path.Equals("/connect/token", StringComparison.OrdinalIgnoreCase); - - private static bool IsJson(string? contentType) => - contentType?.StartsWith("application/json", StringComparison.OrdinalIgnoreCase) == true; - - private static object? ConvertJsonValue(JsonElement value) => - value.ValueKind switch - { - JsonValueKind.String => value.GetString(), - JsonValueKind.Number when value.TryGetInt64(out var l) => l, - JsonValueKind.Number => value.GetDouble(), - JsonValueKind.True => true, - JsonValueKind.False => false, - JsonValueKind.Null => null, - _ => JsonSerializer.Deserialize(value.GetRawText()), - }; - - private static void AddLegacyTokenAliases(Dictionary response, string accessToken) - { - response["Access_token"] = accessToken; - response["accessToken"] = accessToken; - response["AccessToken"] = accessToken; - response["token"] = accessToken; - response["Token"] = accessToken; - response["tokenType"] = "Bearer"; - response["TokenType"] = "Bearer"; - - if (response.TryGetValue("expires_in", out var expiresIn)) - { - response["expiresIn"] = expiresIn; - response["ExpiresIn"] = expiresIn; - } - - if (response.TryGetValue("refresh_token", out var refreshToken)) - { - response["Refresh_token"] = refreshToken; - response["refreshToken"] = refreshToken; - response["RefreshToken"] = refreshToken; - } - - var signingKey = Convert.ToBase64String(RandomNumberGenerator.GetBytes(32)); - response["key"] = signingKey; - response["Key"] = signingKey; - } - - private void SetAccessCookie(HttpContext context, string accessToken) - { - var cookie = new CookieOptions - { - HttpOnly = true, - Secure = string.Equals(domain.Scheme, "https", StringComparison.OrdinalIgnoreCase), - SameSite = SameSiteMode.None, - Expires = DateTimeOffset.UtcNow.AddHours(12), - IsEssential = true, - }; - if (domain.Apex.Contains('.')) - cookie.Domain = "." + domain.Apex; - context.Response.Cookies.Append(AuthService.AccessCookieName, accessToken, cookie); - } -} - public sealed class RecRoomPasswordValidator( PlayerService playerService, LevelService level, diff --git a/DorkNet.Server/Controllers/Admin/AdminController.cs b/DorkNet.Server/Controllers/Admin/AdminController.cs index 3df3fa9..58a15f8 100644 --- a/DorkNet.Server/Controllers/Admin/AdminController.cs +++ b/DorkNet.Server/Controllers/Admin/AdminController.cs @@ -1213,13 +1213,6 @@ public class AdminController( Store = "in-memory", Warning = "Refresh tokens are process-local until an operational store is configured.", }, - LegacyCompatibility = new - { - InjectsClientId = true, - InjectsDefaultScopes = true, - AddsLegacyTokenAliases = true, - AcceptsLegacyJwtSigningKey = true, - }, }); } /// GET api/admin/v1/settings — current server-wide diff --git a/DorkNet.Server/Startup/MiddlewarePipelineExtensions.cs b/DorkNet.Server/Startup/MiddlewarePipelineExtensions.cs index 306bc6d..7980c9f 100644 --- a/DorkNet.Server/Startup/MiddlewarePipelineExtensions.cs +++ b/DorkNet.Server/Startup/MiddlewarePipelineExtensions.cs @@ -62,8 +62,7 @@ public static class MiddlewarePipelineExtensions app.UseMiddleware(); - app.UseMiddleware(); - app.UseMiddleware(); + app.UseMiddleware(); app.UseIdentityServer(); app.UseAuthentication(); diff --git a/DorkNet.Server/admin-ui/src/pages/IdentityServer.tsx b/DorkNet.Server/admin-ui/src/pages/IdentityServer.tsx index e06f240..1a88af1 100644 --- a/DorkNet.Server/admin-ui/src/pages/IdentityServer.tsx +++ b/DorkNet.Server/admin-ui/src/pages/IdentityServer.tsx @@ -36,12 +36,6 @@ interface IdentityServerSettings { store: string; warning: string; }; - legacyCompatibility: { - injectsClientId: boolean; - injectsDefaultScopes: boolean; - addsLegacyTokenAliases: boolean; - acceptsLegacyJwtSigningKey: boolean; - }; } export function IdentityServer() { @@ -126,15 +120,6 @@ export function IdentityServer() { -
-

Legacy compatibility

-
- - - - -
-
@@ -198,15 +183,6 @@ function Metric({ label, value }: { label: string; value: string }) { ); } -function Compatibility({ label, ok }: { label: string; ok: boolean }) { - return ( -
- {label} - -
- ); -} - function Detail({ label, value, mono }: { label: string; value: string; mono?: boolean }) { return (