mirror of
https://github.com/Drop-OSS/drop.git
synced 2025-11-14 08:41:15 +10:00
new accounts use argon2
This commit is contained in:
@ -18,6 +18,7 @@
|
||||
"@nuxtjs/tailwindcss": "^6.12.2",
|
||||
"@prisma/client": "^6.1.0",
|
||||
"@tailwindcss/vite": "^4.0.6",
|
||||
"argon2": "^0.41.1",
|
||||
"axios": "^1.7.7",
|
||||
"bcryptjs": "^2.4.3",
|
||||
"cookie-es": "^1.2.2",
|
||||
|
||||
@ -7,7 +7,8 @@ model LinkedAuthMec {
|
||||
mec AuthMec
|
||||
enabled Boolean @default(true)
|
||||
|
||||
credentials Json
|
||||
credentials Json // TODO: remove this, automate via migration
|
||||
password String?
|
||||
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
|
||||
|
||||
@ -1,7 +1,10 @@
|
||||
import { AuthMec } from "@prisma/client";
|
||||
import { JsonArray } from "@prisma/client/runtime/library";
|
||||
import prisma from "~/server/internal/db/database";
|
||||
import { checkHash } from "~/server/internal/security/simple";
|
||||
import {
|
||||
checkHashArgon2,
|
||||
checkHashBcrypt,
|
||||
} from "~/server/internal/security/simple";
|
||||
import sessionHandler from "~/server/internal/session";
|
||||
|
||||
export default defineEventHandler(async (h3) => {
|
||||
@ -19,10 +22,20 @@ export default defineEventHandler(async (h3) => {
|
||||
const authMek = await prisma.linkedAuthMec.findFirst({
|
||||
where: {
|
||||
mec: AuthMec.Simple,
|
||||
enabled: true,
|
||||
OR: [
|
||||
{
|
||||
// TODO: check if this is even needed with below condition
|
||||
credentials: {
|
||||
array_starts_with: username,
|
||||
},
|
||||
enabled: true,
|
||||
},
|
||||
{
|
||||
user: {
|
||||
username,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
include: {
|
||||
user: {
|
||||
@ -38,18 +51,43 @@ export default defineEventHandler(async (h3) => {
|
||||
statusCode: 401,
|
||||
statusMessage: "Invalid username or password.",
|
||||
});
|
||||
|
||||
const credentials = authMek.credentials as JsonArray;
|
||||
const hash = credentials.at(1);
|
||||
|
||||
if (!hash || !authMek.user.enabled)
|
||||
else if (!authMek.user.enabled)
|
||||
throw createError({
|
||||
statusCode: 403,
|
||||
statusMessage:
|
||||
"Invalid or disabled account. Please contact the server administrator.",
|
||||
});
|
||||
|
||||
if (!(await checkHash(password, hash.toString())))
|
||||
// if using old auth schema
|
||||
if (Array.isArray(authMek.credentials)) {
|
||||
const hash = authMek.credentials.at(1);
|
||||
|
||||
if (!hash)
|
||||
throw createError({
|
||||
statusCode: 403,
|
||||
statusMessage:
|
||||
"Invalid password state. Please contact the server administrator.",
|
||||
});
|
||||
|
||||
if (!(await checkHashBcrypt(password, hash.toString())))
|
||||
throw createError({
|
||||
statusCode: 401,
|
||||
statusMessage: "Invalid username or password.",
|
||||
});
|
||||
|
||||
// TODO: send user to forgot password screen or something to force them to change their password to new system
|
||||
await sessionHandler.setUserId(h3, authMek.userId, rememberMe);
|
||||
return { result: true, userId: authMek.userId };
|
||||
} else {
|
||||
// using new (modern) login flow
|
||||
|
||||
if (authMek.password === null)
|
||||
throw createError({
|
||||
statusCode: 500,
|
||||
statusMessage:
|
||||
"Invalid password state. Please contact the server administrator.",
|
||||
});
|
||||
else if (!(await checkHashArgon2(password, authMek.password)))
|
||||
throw createError({
|
||||
statusCode: 401,
|
||||
statusMessage: "Invalid username or password.",
|
||||
@ -58,4 +96,5 @@ export default defineEventHandler(async (h3) => {
|
||||
await sessionHandler.setUserId(h3, authMek.userId, rememberMe);
|
||||
|
||||
return { result: true, userId: authMek.userId };
|
||||
}
|
||||
});
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { AuthMec, Invitation } from "@prisma/client";
|
||||
import prisma from "~/server/internal/db/database";
|
||||
import { createHash } from "~/server/internal/security/simple";
|
||||
import { createHashArgon2 } from "~/server/internal/security/simple";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import * as jdenticon from "jdenticon";
|
||||
import objectHandler from "~/server/internal/objects";
|
||||
@ -97,6 +97,7 @@ export default defineEventHandler(async (h3) => {
|
||||
);
|
||||
const user = await prisma.user.create({
|
||||
data: {
|
||||
id: userId,
|
||||
username,
|
||||
displayName,
|
||||
email,
|
||||
@ -105,12 +106,13 @@ export default defineEventHandler(async (h3) => {
|
||||
},
|
||||
});
|
||||
|
||||
const hash = await createHash(password);
|
||||
const hash = await createHashArgon2(password);
|
||||
await prisma.linkedAuthMec.create({
|
||||
data: {
|
||||
mec: AuthMec.Simple,
|
||||
credentials: [username, hash],
|
||||
credentials: {},
|
||||
userId: user.id,
|
||||
password: hash,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@ -1,11 +1,19 @@
|
||||
import bcrypt from 'bcryptjs';
|
||||
import bcrypt from "bcryptjs";
|
||||
import * as argon2 from "argon2";
|
||||
|
||||
const rounds = 10;
|
||||
// const bcryptRounds = 10;
|
||||
// export async function createHashBcrypt(password: string) {
|
||||
// return await bcrypt.hash(password, bcryptRounds);
|
||||
// }
|
||||
|
||||
export async function createHash(password: string) {
|
||||
return bcrypt.hashSync(password, rounds);
|
||||
export async function checkHashBcrypt(password: string, hash: string) {
|
||||
return await bcrypt.compare(password, hash);
|
||||
}
|
||||
|
||||
export async function checkHash(password: string, hash: string) {
|
||||
return bcrypt.compareSync(password, hash);
|
||||
export async function createHashArgon2(password: string) {
|
||||
return await argon2.hash(password);
|
||||
}
|
||||
|
||||
export async function checkHashArgon2(password: string, hash: string) {
|
||||
return await argon2.verify(hash, password);
|
||||
}
|
||||
24
yarn.lock
24
yarn.lock
@ -1266,6 +1266,11 @@
|
||||
"@parcel/watcher-win32-ia32" "2.5.0"
|
||||
"@parcel/watcher-win32-x64" "2.5.0"
|
||||
|
||||
"@phc/format@^1.0.0":
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@phc/format/-/format-1.0.0.tgz#b5627003b3216dc4362125b13f48a4daa76680e4"
|
||||
integrity sha512-m7X9U6BG2+J+R1lSOdCiITLLrxm+cWlNI3HUFA92oLO77ObGNzaKdh8pMLqdZcshtkKuV84olNNXDfMc4FezBQ==
|
||||
|
||||
"@pkgjs/parseargs@^0.11.0":
|
||||
version "0.11.0"
|
||||
resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33"
|
||||
@ -2087,6 +2092,15 @@ arg@^5.0.2:
|
||||
resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.2.tgz#c81433cc427c92c4dcf4865142dbca6f15acd59c"
|
||||
integrity sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==
|
||||
|
||||
argon2@^0.41.1:
|
||||
version "0.41.1"
|
||||
resolved "https://registry.yarnpkg.com/argon2/-/argon2-0.41.1.tgz#30ce6b013e273bc7e92c558d40e66d35e5e8c63b"
|
||||
integrity sha512-dqCW8kJXke8Ik+McUcMDltrbuAWETPyU6iq+4AhxqKphWi7pChB/Zgd/Tp/o8xRLbg8ksMj46F/vph9wnxpTzQ==
|
||||
dependencies:
|
||||
"@phc/format" "^1.0.0"
|
||||
node-addon-api "^8.1.0"
|
||||
node-gyp-build "^4.8.1"
|
||||
|
||||
argparse@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
|
||||
@ -4958,6 +4972,11 @@ node-addon-api@^7.0.0:
|
||||
resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-7.1.1.tgz#1aba6693b0f255258a049d621329329322aad558"
|
||||
integrity sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==
|
||||
|
||||
node-addon-api@^8.1.0:
|
||||
version "8.3.1"
|
||||
resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-8.3.1.tgz#53bc8a4f8dbde3de787b9828059da94ba9fd4eed"
|
||||
integrity sha512-lytcDEdxKjGJPTLEfW4mYMigRezMlyJY8W4wxJK8zE533Jlb8L8dRuObJFWg2P+AuOIxoCgKF+2Oq4d4Zd0OUA==
|
||||
|
||||
node-fetch-native@^1.6.3, node-fetch-native@^1.6.4:
|
||||
version "1.6.4"
|
||||
resolved "https://registry.yarnpkg.com/node-fetch-native/-/node-fetch-native-1.6.4.tgz#679fc8fd8111266d47d7e72c379f1bed9acff06e"
|
||||
@ -4985,6 +5004,11 @@ node-gyp-build@^4.2.2:
|
||||
resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.8.2.tgz#4f802b71c1ab2ca16af830e6c1ea7dd1ad9496fa"
|
||||
integrity sha512-IRUxE4BVsHWXkV/SFOut4qTlagw2aM8T5/vnTsmrHJvVoKueJHRc/JaFND7QDDc61kLYUJ6qlZM3sqTSyx2dTw==
|
||||
|
||||
node-gyp-build@^4.8.1:
|
||||
version "4.8.4"
|
||||
resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.8.4.tgz#8a70ee85464ae52327772a90d66c6077a900cfc8"
|
||||
integrity sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==
|
||||
|
||||
node-mock-http@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/node-mock-http/-/node-mock-http-1.0.0.tgz#4b32cd509c7f46d844e68ea93fb8be405a18a42a"
|
||||
|
||||
Reference in New Issue
Block a user