From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Modrinth Enhanced Date: Mon, 14 Sep 2026 10:27:34 +0200 Subject: [PATCH] Add offline accounts Adds a second way to add a Minecraft account that never talks to Microsoft or Mojang, for playing singleplayer worlds and servers running in offline mode. An offline account is an ordinary row in `minecraft_users`, marked by a sentinel in the refresh token column, so no database migration is needed. `Credentials::refresh` and the online profile lookup both return early for such an account, which keeps every existing code path - launching, account switching, serialisation to the frontend - working without further changes. The player UUID is derived the way Minecraft itself derives it, as an MD5 name UUID over `OfflinePlayer:`. That is what vanilla servers in offline mode and other launchers use, so worlds keep the same player data when they are opened elsewhere. Usernames are validated the way Mojang validates them: 3 to 16 characters of letters, numbers and underscores. Two places had to be opened up for any of this to be reachable. The account card was hidden until a Microsoft account had been added, which left offline sign-in unreachable for exactly the people who want it, and the "Minecraft required" modal - what you actually hit on pressing Play with no account - offered Microsoft and nothing else. --- Cargo.lock | 1 + Cargo.toml | 1 + apps/app-frontend/src/App.vue | 10 +- .../src/components/ui/AccountsCard.vue | 30 ++++ .../src/components/ui/OfflineAccountModal.vue | 136 ++++++++++++++++++ .../MinecraftRequiredModal.vue | 26 +++- apps/app-frontend/src/helpers/auth.js | 13 ++ apps/app/src/api/auth.rs | 7 + packages/app-lib/Cargo.toml | 1 + packages/app-lib/src/api/minecraft_auth.rs | 39 +++++ packages/app-lib/src/state/minecraft_auth.rs | 68 +++++++++ 11 files changed, 327 insertions(+), 5 deletions(-) create mode 100644 apps/app-frontend/src/components/ui/OfflineAccountModal.vue diff --git a/Cargo.lock b/Cargo.lock index d40a959..95bc842 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11384,6 +11384,7 @@ dependencies = [ "indicatif", "itertools 0.14.0", "json5", + "md-5", "modrinth-content-management", "notify", "notify-debouncer-mini", diff --git a/Cargo.toml b/Cargo.toml index a4a779c..a85f576 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -132,6 +132,7 @@ lz4_flex = { version = "0.11.5", default-features = false, features = [ "std", ] } maxminddb = "0.26.0" +md-5 = "0.10.6" modrinth-content-management = { path = "packages/modrinth-content-management" } modrinth-log = { path = "packages/modrinth-log" } modrinth-util = { path = "packages/modrinth-util" } diff --git a/apps/app-frontend/src/App.vue b/apps/app-frontend/src/App.vue index 6e7b27d..532f104 100644 --- a/apps/app-frontend/src/App.vue +++ b/apps/app-frontend/src/App.vue @@ -2472,10 +2472,12 @@ provideAppUpdateDownloadProgress(appUpdateDownload) /> + diff --git a/apps/app-frontend/src/components/ui/minecraft-required-modal/MinecraftRequiredModal.vue b/apps/app-frontend/src/components/ui/minecraft-required-modal/MinecraftRequiredModal.vue index 73293f5..bbdc517 100644 --- a/apps/app-frontend/src/components/ui/minecraft-required-modal/MinecraftRequiredModal.vue +++ b/apps/app-frontend/src/components/ui/minecraft-required-modal/MinecraftRequiredModal.vue @@ -43,6 +43,16 @@ {{ formatMessage(messages.signIn) }} +
+

+ {{ formatMessage(messages.offlineHint) }} +

+ +
+

{{ formatMessage(messages.dontHaveAccount) }}