From 3cd42103e5580e521471e4db152fe5b188c130dc Mon Sep 17 00:00:00 2001 From: azures04 Date: Sun, 28 Dec 2025 23:19:38 +0100 Subject: [PATCH] Add legacy authentication and session routes Introduces legacy endpoints for login, joinserver, and checkserver, along with their input validation schemas. Updates sessionsService with joinLegacyServer to support legacy session handling. This enables compatibility with legacy clients requiring these authentication flows. --- routes/legacy/checkserver.js | 24 +++++++++++++++++++ routes/legacy/joinserver.js | 26 ++++++++++++++++++++ routes/legacy/login.js | 36 ++++++++++++++++++++++++++++ schemas/legacy/joinserver.js | 11 +++++++++ schemas/legacy/legacy/checkserver.js | 10 ++++++++ schemas/legacy/login.js | 16 +++++++++++++ services/sessionsService.js | 16 +++++++++++++ 7 files changed, 139 insertions(+) create mode 100644 routes/legacy/checkserver.js create mode 100644 routes/legacy/joinserver.js create mode 100644 routes/legacy/login.js create mode 100644 schemas/legacy/joinserver.js create mode 100644 schemas/legacy/legacy/checkserver.js create mode 100644 schemas/legacy/login.js diff --git a/routes/legacy/checkserver.js b/routes/legacy/checkserver.js new file mode 100644 index 0000000..40ad74d --- /dev/null +++ b/routes/legacy/checkserver.js @@ -0,0 +1,24 @@ +const express = require("express") +const router = express.Router() +const sessionsService = require("../../services/sessionsService") + +router.get("/", async (req, res) => { + const { user, serverId } = req.query + try { + const result = await sessionsService.hasJoinedServer({ + username: user, + serverId, + ip: null + }) + + if (result.code === 200) { + return res.send("YES") + } else { + return res.send("NO") + } + } catch (err) { + return res.send("NO") + } +}) + +module.exports = router \ No newline at end of file diff --git a/routes/legacy/joinserver.js b/routes/legacy/joinserver.js new file mode 100644 index 0000000..62802fe --- /dev/null +++ b/routes/legacy/joinserver.js @@ -0,0 +1,26 @@ +const express = require("express") +const router = express.Router() +const sessionsService = require("../../services/sessionsService") +const logger = require("../../modules/logger") + +router.get("/", async (req, res) => { + const { user, sessionId, serverId } = req.query + const clientIp = req.ip || req.connection.remoteAddress + + try { + await sessionsService.joinLegacyServer({ + name: user, + sessionId, + serverId, + ip: clientIp + }) + + logger.log(`Legacy Join: ${user} -> ${serverId}`, ["AUTH", "green"]) + return res.send("OK") + + } catch (err) { + return res.send("Bad login") + } +}) + +module.exports = router \ No newline at end of file diff --git a/routes/legacy/login.js b/routes/legacy/login.js new file mode 100644 index 0000000..7f4ccbe --- /dev/null +++ b/routes/legacy/login.js @@ -0,0 +1,36 @@ +const express = require("express") +const router = express.Router() +const crypto = require("crypto") +const authService = require("../../services/authService") +const sessionsService = require("../../services/sessionsService") +const logger = require("../../modules/logger") + +router.all("/", async (req, res) => { + const { user, password } = { ...req.query, ...req.body } + + try { + const result = await authService.authenticate({ + identifier: user, + password, + clientToken: "", + requireUser: false + }) + + const profile = result.response.selectedProfile + const sessionId = crypto.randomBytes(16).toString("hex") + + await sessionsService.registerLegacySession({ + uuid: profile.id, + sessionId + }) + + logger.log(`Legacy Login: ${user}`, ["AUTH", "green"]) + + const timestamp = Date.now() + return res.send(`${timestamp}:deprecated:${profile.name}:${sessionId}:${profile.id}`) + } catch (err) { + return res.send("Bad login") + } +}) + +module.exports = router \ No newline at end of file diff --git a/schemas/legacy/joinserver.js b/schemas/legacy/joinserver.js new file mode 100644 index 0000000..02d5cff --- /dev/null +++ b/schemas/legacy/joinserver.js @@ -0,0 +1,11 @@ +const z = require("zod") + +module.exports = { + GET: { + query: z.object({ + user: z.string().min(1), + sessionId: z.string().min(1), + serverId: z.string().min(1) + }) + } +} \ No newline at end of file diff --git a/schemas/legacy/legacy/checkserver.js b/schemas/legacy/legacy/checkserver.js new file mode 100644 index 0000000..2487bc0 --- /dev/null +++ b/schemas/legacy/legacy/checkserver.js @@ -0,0 +1,10 @@ +const z = require("zod") + +module.exports = { + GET: { + query: z.object({ + user: z.string().min(1), + serverId: z.string().min(1) + }) + } +} \ No newline at end of file diff --git a/schemas/legacy/login.js b/schemas/legacy/login.js new file mode 100644 index 0000000..6037e22 --- /dev/null +++ b/schemas/legacy/login.js @@ -0,0 +1,16 @@ +const z = require("zod") + +const loginShape = { + user: z.string().min(1, { message: "Username required" }), + password: z.string().min(1, { message: "Password required" }), + version: z.union([z.string(), z.number()]).optional() +} + +module.exports = { + POST: { + body: z.object(loginShape), + }, + GET: { + query: z.object(loginShape) + } +} \ No newline at end of file diff --git a/services/sessionsService.js b/services/sessionsService.js index 9a60ebd..e72d043 100644 --- a/services/sessionsService.js +++ b/services/sessionsService.js @@ -152,10 +152,26 @@ async function hasJoinedServer({ username, serverId, ip }) { }) } +async function joinLegacyServer({ name, sessionId, serverId }) { + try { + await validateLegacySession({ name, sessionId }) + } catch (error) { + throw new DefaultError(403, "Bad login", "ForbiddenOperationException") + } + + const userResult = await authRepository.getUser(name) + const uuid = userResult.user.uuid + + await sessionRepository.saveServerSession(uuid, sessionId, serverId, "0.0.0.0") + + return { code: 200, message: "OK" } +} + module.exports = { getProfile, joinServer, hasJoinedServer, + joinLegacyServer, getBlockedServers, registerLegacySession, validateLegacySession,