返回提交历史
Modified
src/controllers/custom/getAccountInfoController.ts
+1
-1
Modified
src/controllers/custom/ircDroppedController.ts
+4
-19
Modified
src/middleware/errorHandler.ts
+1
-1
Modified
src/services/loginService.ts
+20
-2
XFEstudio/SpaceNinjaServer
feat: irc tokens (#3302)
Because the IRC connection is generally not secure (even over TLS), we don't wanna send the nonce over it, so... a token proves ownership of the accountId-nonce pair while being limited to 2 harmless endpoints. Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/3302 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
b7d752f3
代码差异
4 个文件
+26
-23
@@ -4,7 +4,7 @@ import { getAccountForRequest, isAdministrator } from "../../services/loginServi
4
4
import type { RequestHandler } from "express";
5
5
6
6
export const getAccountInfoController: RequestHandler = async (req, res) => {
7
const account = await getAccountForRequest(req);
7
const account = await getAccountForRequest(req, true);
8
8
const inventory = await getInventory(account._id.toString(), "QuestKeys");
9
9
const info: IAccountInfo = {
10
10
DisplayName: account.DisplayName,
@@ -1,24 +1,9 @@
1
import { Account } from "../../models/loginModel.ts";
2
1
import type { RequestHandler } from "express";
2
import { getAccountForRequest } from "../../services/loginService.ts";
3
3
4
4
export const ircDroppedController: RequestHandler = async (req, res) => {
5
if (!req.query.accountId) {
6
throw new Error("Request is missing accountId parameter");
7
}
8
const nonce: number = parseInt(req.query.nonce as string);
9
if (!nonce) {
10
throw new Error("Request is missing nonce parameter");
11
}
12
13
await Account.updateOne(
14
{
15
_id: req.query.accountId,
16
Nonce: nonce
17
},
18
{
19
Dropped: true
20
}
21
);
22
5
const account = await getAccountForRequest(req, true);
6
account.Dropped = true;
7
await account.save();
23
8
res.end();
24
9
};
@@ -2,7 +2,7 @@ import type { NextFunction, Request, Response } from "express";
2
2
import { logError } from "../utils/logger.ts";
3
3
4
4
export const errorHandler = (err: Error, req: Request, res: Response, _next: NextFunction): void => {
5
if (err.message == "Invalid accountId-nonce pair") {
5
if (err.message == "Invalid accountId-nonce pair" || err.message == "Invalid accountId-token pair") {
6
6
res.status(400).send("Log-in expired");
7
7
} else {
8
8
logError(err, `processing ${req.path} request`);
@@ -9,6 +9,7 @@ import type { Request } from "express";
9
9
import { config } from "./configService.ts";
10
10
import { createStats } from "./statsService.ts";
11
11
import crc32 from "crc-32";
12
import crypto from "node:crypto";
12
13
13
14
export const isCorrectPassword = (requestPassword: string, databasePassword: string): boolean => {
14
15
return requestPassword === databasePassword;
@@ -71,15 +72,32 @@ export const createPersonalRooms = async (accountId: Types.ObjectId, shipId: Typ
71
72
export type TAccountDocument = Document<unknown, {}, IDatabaseAccountJson> &
72
73
IDatabaseAccountJson & { _id: Types.ObjectId; __v: number };
73
74
74
export const getAccountForRequest = async (req: Request): Promise<TAccountDocument> => {
75
export const getAccountForRequest = async (req: Request, acceptToken?: true): Promise<TAccountDocument> => {
75
76
if (!req.query.accountId) {
76
77
throw new Error("Request is missing accountId parameter");
77
78
}
79
80
// Tokens are specific to OpenWF to avoid sending the nonce (which gives full account access) over insecure transports.
81
if (acceptToken && req.query.token) {
82
const account = await Account.findById(req.query.accountId as string);
83
if (!account || !account.Nonce) {
84
throw new Error("Invalid accountId-token pair");
85
}
86
const token = crypto
87
.createHmac("sha256", account.Nonce.toString())
88
.update(`accountId=${req.query.accountId as string}&ct=${(req.query.ct as string | undefined) ?? ""}`)
89
.digest("hex");
90
//console.log(`expected token: ${token}`);
91
if ((req.query.token as string).toLowerCase() != token) {
92
throw new Error("Invalid accountId-token pair");
93
}
94
return account;
95
}
96
78
97
const nonce: number = parseInt(req.query.nonce as string);
79
98
if (!nonce) {
80
99
throw new Error("Request is missing nonce parameter");
81
100
}
82
83
101
const account = await Account.findById(req.query.accountId as string);
84
102
if (!account || account.Nonce != nonce) {
85
103
throw new Error("Invalid accountId-nonce pair");