mirror of
https://github.com/louislam/uptime-kuma.git
synced 2026-06-19 07:36:11 +00:00
Implement DisableAuth and implement doubleCheckPassword()
This commit is contained in:
+53
-15
@@ -1,4 +1,4 @@
|
||||
import { betterAuth } from "better-auth";
|
||||
import { betterAuth, Session } from "better-auth";
|
||||
// @ts-ignore
|
||||
import * as Database from "./database.js";
|
||||
import { genSecret, log } from "../src/util";
|
||||
@@ -123,32 +123,51 @@ export function getAuthSecret() {
|
||||
export function getSession(cookie: string) {
|
||||
log.info("auth", "Logged in with httpOnly cookie session");
|
||||
const context = {
|
||||
headers: new Headers(),
|
||||
headers: createHeaders(cookie),
|
||||
};
|
||||
context.headers.set("cookie", cookie || "");
|
||||
return authInstance.api.getSession(context);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Create Headers object with cookie for API calls
|
||||
* @param cookie Cookie string
|
||||
* @returns Headers object
|
||||
*/
|
||||
export function createHeaders(cookie: string) {
|
||||
const headers = new Headers();
|
||||
headers.set("cookie", cookie || "");
|
||||
return headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unfortunatety, there is no way to get a user object from better-auth api, so we have to craft a session object here.
|
||||
* @returns Crafted Session Object
|
||||
*/
|
||||
export async function getDisableAuthSession(): ReturnType<typeof getSession> {
|
||||
log.info("auth", "Logged in with Disable Auth");
|
||||
|
||||
const { users, total } = await authInstance.api.listUsers({
|
||||
query: {
|
||||
limit: 1,
|
||||
},
|
||||
});
|
||||
const obj = await R.getRow("SELECT * FROM better_auth_user LIMIT 1");
|
||||
|
||||
if (total == 0) {
|
||||
throw new Error("Unexpected error. No users found");
|
||||
if (!obj) {
|
||||
throw new Error("Unexpected Error: No user found in the database.");
|
||||
}
|
||||
|
||||
// Seems bugged, user from listUsers does not have all properties
|
||||
// Force parse the user object to BetterAuthUser.
|
||||
// https://github.com/better-auth/better-auth/issues/7452
|
||||
const user = users[0] as BetterAuthUser;
|
||||
const user = {
|
||||
id: obj.id as string,
|
||||
createdAt: obj.createdAt as Date,
|
||||
updatedAt: obj.updatedAt as Date,
|
||||
email: obj.email as string,
|
||||
emailVerified: obj.emailVerified === 1,
|
||||
name: obj.name as string,
|
||||
image: obj.image as string | null,
|
||||
username: obj.username as string | null,
|
||||
displayUsername: obj.displayUsername as string | null,
|
||||
banned: obj.banned === 1,
|
||||
role: obj.role as string | null,
|
||||
banReason: obj.banReason as string | null,
|
||||
banExpires: obj.banExpires as Date | null,
|
||||
twoFactorEnabled: obj.twoFactorEnabled === 1,
|
||||
};
|
||||
|
||||
return {
|
||||
user,
|
||||
@@ -177,6 +196,25 @@ export function checkLogin(socket: Socket) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* For logged-in users, double-check the password
|
||||
* @param cookie Cookie string
|
||||
* @param currentPassword Password to verify
|
||||
* @throws Error if the password is incorrect or the user is not found
|
||||
*/
|
||||
export async function doubleCheckPassword(cookie: string, currentPassword: string): Promise<void> {
|
||||
const { status } = await authInstance.api.verifyPassword({
|
||||
body: {
|
||||
password: currentPassword,
|
||||
},
|
||||
headers: createHeaders(cookie),
|
||||
});
|
||||
|
||||
if (!status) {
|
||||
throw new Error("Incorrect current password");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO
|
||||
*/
|
||||
|
||||
+2
-3
@@ -4,7 +4,7 @@
|
||||
* DO NOT require("./server") in other modules, it likely creates circular dependency!
|
||||
*/
|
||||
import { getRandomInt, isDev, log, sleep } from "../src/util";
|
||||
import { auth, getDisableAuthSession, getSession } from "./better-auth";
|
||||
import { auth, doubleCheckPassword, getDisableAuthSession, getSession } from "./better-auth";
|
||||
import { createBetterAuthRouter, needSetup } from "./routers/better-auth-router";
|
||||
import { betterAuthSocketHandler } from "./socket-handlers/better-auth-socket-handler";
|
||||
import { loadEnvFile } from "node:process";
|
||||
@@ -108,7 +108,6 @@ const {
|
||||
setSettings,
|
||||
setting,
|
||||
checkLogin,
|
||||
doubleCheckPassword,
|
||||
allowDevAllOrigin,
|
||||
printServerUrls,
|
||||
allowDevOrigin,
|
||||
@@ -1118,7 +1117,7 @@ app.use(function (req, res, next) {
|
||||
// Enabled Auth + Want to Enable Auth => No Check
|
||||
const currentDisabledAuth = await setting("disableAuth");
|
||||
if (!currentDisabledAuth && data.disableAuth) {
|
||||
await doubleCheckPassword(socket, currentPassword);
|
||||
await doubleCheckPassword(socket.request.headers.cookie, currentPassword);
|
||||
}
|
||||
|
||||
// Log out all clients if enabling auth
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
const { checkLogin, setSetting, setting, doubleCheckPassword } = require("../util-server");
|
||||
const { checkLogin, setSetting, setting } = require("../util-server");
|
||||
const { CloudflaredTunnel } = require("node-cloudflared-tunnel");
|
||||
const { UptimeKumaServer } = require("../uptime-kuma-server");
|
||||
const { log } = require("../../src/util");
|
||||
const { doubleCheckPassword } = require("../better-auth");
|
||||
const io = UptimeKumaServer.getInstance().io;
|
||||
|
||||
const prefix = "cloudflared_";
|
||||
@@ -74,7 +75,7 @@ module.exports.cloudflaredSocketHandler = (socket) => {
|
||||
checkLogin(socket);
|
||||
const disabledAuth = await setting("disableAuth");
|
||||
if (!disabledAuth) {
|
||||
await doubleCheckPassword(socket, currentPassword);
|
||||
await doubleCheckPassword(socket.request.headers.cookie, currentPassword);
|
||||
}
|
||||
cloudflared.stop();
|
||||
} catch (error) {
|
||||
|
||||
@@ -10,7 +10,6 @@ const {
|
||||
PING_COUNT_DEFAULT,
|
||||
PING_PER_REQUEST_TIMEOUT_DEFAULT,
|
||||
} = require("../src/util");
|
||||
const passwordHash = require("./password-hash");
|
||||
const iconv = require("iconv-lite");
|
||||
const chardet = require("chardet");
|
||||
const chroma = require("chroma-js");
|
||||
@@ -650,28 +649,6 @@ exports.checkLogin = (socket) => {
|
||||
betterAuthCheckLogin(socket);
|
||||
};
|
||||
|
||||
/**
|
||||
* For logged-in users, double-check the password
|
||||
* @param {Socket} socket Socket.io instance
|
||||
* @param {string} currentPassword Password to validate
|
||||
* @returns {Promise<Bean>} User
|
||||
* @throws The current password is not a string
|
||||
* @throws The provided password is not correct
|
||||
*/
|
||||
exports.doubleCheckPassword = async (socket, currentPassword) => {
|
||||
if (typeof currentPassword !== "string") {
|
||||
throw new Error("Wrong data type?");
|
||||
}
|
||||
|
||||
let user = await R.findOne("user", " id = ? AND active = 1 ", [socket.userID]);
|
||||
|
||||
if (!user || !passwordHash.verify(currentPassword, user.password)) {
|
||||
throw new Error("Incorrect current password");
|
||||
}
|
||||
|
||||
return user;
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert unknown string to UTF8
|
||||
* @param {Uint8Array} body Buffer
|
||||
|
||||
Reference in New Issue
Block a user