From 0f4537e87bdb0b49bfd0aacadba2f7acff510e89 Mon Sep 17 00:00:00 2001 From: amy bones Date: Mon, 3 Apr 2023 02:23:51 -0700 Subject: [PATCH] fix: changing passwords, 2fa, and password resets. The argon2 usage was only implemented for sign-ins which broke a bunch of other endpoints and features. --- packages/backend/src/server/api/common/signup.ts | 5 ++--- .../src/server/api/endpoints/admin/reset-password.ts | 6 ++++-- .../backend/src/server/api/endpoints/i/2fa/key-done.ts | 4 ++-- .../backend/src/server/api/endpoints/i/2fa/register-key.ts | 4 ++-- .../backend/src/server/api/endpoints/i/2fa/register.ts | 4 ++-- .../backend/src/server/api/endpoints/i/2fa/remove-key.ts | 4 ++-- .../backend/src/server/api/endpoints/i/2fa/unregister.ts | 4 ++-- .../backend/src/server/api/endpoints/i/change-password.ts | 7 +++---- .../backend/src/server/api/endpoints/i/delete-account.ts | 4 ++-- .../backend/src/server/api/endpoints/i/regenerate-token.ts | 4 ++-- .../backend/src/server/api/endpoints/i/update-email.ts | 4 ++-- .../backend/src/server/api/endpoints/reset-password.ts | 5 ++--- packages/backend/src/server/api/private/signin.ts | 1 - packages/backend/src/server/api/private/signup.ts | 5 ++--- packages/backend/src/services/create-system-user.ts | 5 ++--- 15 files changed, 31 insertions(+), 35 deletions(-) diff --git a/packages/backend/src/server/api/common/signup.ts b/packages/backend/src/server/api/common/signup.ts index bb178506b..6beae2c78 100644 --- a/packages/backend/src/server/api/common/signup.ts +++ b/packages/backend/src/server/api/common/signup.ts @@ -1,4 +1,3 @@ -import bcrypt from "bcryptjs"; import { generateKeyPair } from "node:crypto"; import generateUserToken from "./generate-native-user-token.js"; import { User } from "@/models/entities/user.js"; @@ -12,6 +11,7 @@ import { usersChart } from "@/services/chart/index.js"; import { UsedUsername } from "@/models/entities/used-username.js"; import { db } from "@/db/postgre.js"; import config from "@/config/index.js"; +import { hashPassword } from "@/misc/password.js"; export async function signup(opts: { username: User["username"]; @@ -42,8 +42,7 @@ export async function signup(opts: { } // Generate hash of password - const salt = await bcrypt.genSalt(8); - hash = await bcrypt.hash(password, salt); + hash = await hashPassword(password); } // Generate secret diff --git a/packages/backend/src/server/api/endpoints/admin/reset-password.ts b/packages/backend/src/server/api/endpoints/admin/reset-password.ts index dd3f258f7..cbe6735ce 100644 --- a/packages/backend/src/server/api/endpoints/admin/reset-password.ts +++ b/packages/backend/src/server/api/endpoints/admin/reset-password.ts @@ -1,7 +1,8 @@ import define from "../../define.js"; -import bcrypt from "bcryptjs"; +// import bcrypt from "bcryptjs"; import rndstr from "rndstr"; import { Users, UserProfiles } from "@/models/index.js"; +import { hashPassword } from "@/misc/password.js"; export const meta = { tags: ["admin"], @@ -47,7 +48,8 @@ export default define(meta, paramDef, async (ps) => { const passwd = rndstr("a-zA-Z0-9", 8); // Generate hash of password - const hash = bcrypt.hashSync(passwd); + // const hash = bcrypt.hashSync(passwd); + const hash = await hashPassword(passwd); await UserProfiles.update( { diff --git a/packages/backend/src/server/api/endpoints/i/2fa/key-done.ts b/packages/backend/src/server/api/endpoints/i/2fa/key-done.ts index e80dc4d71..f0581de4b 100644 --- a/packages/backend/src/server/api/endpoints/i/2fa/key-done.ts +++ b/packages/backend/src/server/api/endpoints/i/2fa/key-done.ts @@ -1,4 +1,3 @@ -import bcrypt from "bcryptjs"; import { promisify } from "node:util"; import * as cbor from "cbor"; import define from "../../../define.js"; @@ -11,6 +10,7 @@ import { import config from "@/config/index.js"; import { procedures, hash } from "../../../2fa.js"; import { publishMainStream } from "@/services/stream.js"; +import { comparePassword } from "@/misc/password.js"; const cborDecodeFirst = promisify(cbor.decodeFirst) as any; const rpIdHashReal = hash(Buffer.from(config.hostname, "utf-8")); @@ -43,7 +43,7 @@ export default define(meta, paramDef, async (ps, user) => { const profile = await UserProfiles.findOneByOrFail({ userId: user.id }); // Compare password - const same = await bcrypt.compare(ps.password, profile.password!); + const same = await comparePassword(ps.password, profile.password!); if (!same) { throw new Error("incorrect password"); diff --git a/packages/backend/src/server/api/endpoints/i/2fa/register-key.ts b/packages/backend/src/server/api/endpoints/i/2fa/register-key.ts index 96239b56d..a10dc9b25 100644 --- a/packages/backend/src/server/api/endpoints/i/2fa/register-key.ts +++ b/packages/backend/src/server/api/endpoints/i/2fa/register-key.ts @@ -1,10 +1,10 @@ -import bcrypt from "bcryptjs"; import define from "../../../define.js"; import { UserProfiles, AttestationChallenges } from "@/models/index.js"; import { promisify } from "node:util"; import * as crypto from "node:crypto"; import { genId } from "@/misc/gen-id.js"; import { hash } from "../../../2fa.js"; +import { comparePassword } from "@/misc/password.js"; const randomBytes = promisify(crypto.randomBytes); @@ -26,7 +26,7 @@ export default define(meta, paramDef, async (ps, user) => { const profile = await UserProfiles.findOneByOrFail({ userId: user.id }); // Compare password - const same = await bcrypt.compare(ps.password, profile.password!); + const same = await comparePassword(ps.password, profile.password!); if (!same) { throw new Error("incorrect password"); diff --git a/packages/backend/src/server/api/endpoints/i/2fa/register.ts b/packages/backend/src/server/api/endpoints/i/2fa/register.ts index 9019787f2..533035bc9 100644 --- a/packages/backend/src/server/api/endpoints/i/2fa/register.ts +++ b/packages/backend/src/server/api/endpoints/i/2fa/register.ts @@ -1,9 +1,9 @@ -import bcrypt from "bcryptjs"; import * as speakeasy from "speakeasy"; import * as QRCode from "qrcode"; import config from "@/config/index.js"; import { UserProfiles } from "@/models/index.js"; import define from "../../../define.js"; +import { comparePassword } from "@/misc/password.js"; export const meta = { requireCredential: true, @@ -23,7 +23,7 @@ export default define(meta, paramDef, async (ps, user) => { const profile = await UserProfiles.findOneByOrFail({ userId: user.id }); // Compare password - const same = await bcrypt.compare(ps.password, profile.password!); + const same = await comparePassword(ps.password, profile.password!); if (!same) { throw new Error("incorrect password"); diff --git a/packages/backend/src/server/api/endpoints/i/2fa/remove-key.ts b/packages/backend/src/server/api/endpoints/i/2fa/remove-key.ts index d491f0a6e..862c971e7 100644 --- a/packages/backend/src/server/api/endpoints/i/2fa/remove-key.ts +++ b/packages/backend/src/server/api/endpoints/i/2fa/remove-key.ts @@ -1,4 +1,4 @@ -import bcrypt from "bcryptjs"; +import { comparePassword } from "@/misc/password.js"; import define from "../../../define.js"; import { UserProfiles, UserSecurityKeys, Users } from "@/models/index.js"; import { publishMainStream } from "@/services/stream.js"; @@ -22,7 +22,7 @@ export default define(meta, paramDef, async (ps, user) => { const profile = await UserProfiles.findOneByOrFail({ userId: user.id }); // Compare password - const same = await bcrypt.compare(ps.password, profile.password!); + const same = await comparePassword(ps.password, profile.password!); if (!same) { throw new Error("incorrect password"); diff --git a/packages/backend/src/server/api/endpoints/i/2fa/unregister.ts b/packages/backend/src/server/api/endpoints/i/2fa/unregister.ts index 9bb1538b0..57d57ff65 100644 --- a/packages/backend/src/server/api/endpoints/i/2fa/unregister.ts +++ b/packages/backend/src/server/api/endpoints/i/2fa/unregister.ts @@ -1,6 +1,6 @@ -import bcrypt from "bcryptjs"; import define from "../../../define.js"; import { UserProfiles } from "@/models/index.js"; +import { comparePassword } from "@/misc/password.js"; export const meta = { requireCredential: true, @@ -20,7 +20,7 @@ export default define(meta, paramDef, async (ps, user) => { const profile = await UserProfiles.findOneByOrFail({ userId: user.id }); // Compare password - const same = await bcrypt.compare(ps.password, profile.password!); + const same = await comparePassword(ps.password, profile.password!); if (!same) { throw new Error("incorrect password"); diff --git a/packages/backend/src/server/api/endpoints/i/change-password.ts b/packages/backend/src/server/api/endpoints/i/change-password.ts index fcfc38bd1..8bbb3ad93 100644 --- a/packages/backend/src/server/api/endpoints/i/change-password.ts +++ b/packages/backend/src/server/api/endpoints/i/change-password.ts @@ -1,6 +1,6 @@ -import bcrypt from "bcryptjs"; import define from "../../define.js"; import { UserProfiles } from "@/models/index.js"; +import { hashPassword, comparePassword } from "@/misc/password.js"; export const meta = { requireCredential: true, @@ -21,15 +21,14 @@ export default define(meta, paramDef, async (ps, user) => { const profile = await UserProfiles.findOneByOrFail({ userId: user.id }); // Compare password - const same = await bcrypt.compare(ps.currentPassword, profile.password!); + const same = await comparePassword(ps.currentPassword, profile.password!); if (!same) { throw new Error("incorrect password"); } // Generate hash of password - const salt = await bcrypt.genSalt(8); - const hash = await bcrypt.hash(ps.newPassword, salt); + const hash = await hashPassword(ps.newPassword); await UserProfiles.update(user.id, { password: hash, diff --git a/packages/backend/src/server/api/endpoints/i/delete-account.ts b/packages/backend/src/server/api/endpoints/i/delete-account.ts index 81aee9a41..781abe0b3 100644 --- a/packages/backend/src/server/api/endpoints/i/delete-account.ts +++ b/packages/backend/src/server/api/endpoints/i/delete-account.ts @@ -1,7 +1,7 @@ -import bcrypt from "bcryptjs"; import { UserProfiles, Users } from "@/models/index.js"; import { deleteAccount } from "@/services/delete-account.js"; import define from "../../define.js"; +import { comparePassword } from "@/misc/password.js"; export const meta = { requireCredential: true, @@ -25,7 +25,7 @@ export default define(meta, paramDef, async (ps, user) => { } // Compare password - const same = await bcrypt.compare(ps.password, profile.password!); + const same = await comparePassword(ps.password, profile.password!); if (!same) { throw new Error("incorrect password"); diff --git a/packages/backend/src/server/api/endpoints/i/regenerate-token.ts b/packages/backend/src/server/api/endpoints/i/regenerate-token.ts index dff37cf3d..b5b34c090 100644 --- a/packages/backend/src/server/api/endpoints/i/regenerate-token.ts +++ b/packages/backend/src/server/api/endpoints/i/regenerate-token.ts @@ -1,4 +1,3 @@ -import bcrypt from "bcryptjs"; import { publishInternalEvent, publishMainStream, @@ -7,6 +6,7 @@ import { import generateUserToken from "../../common/generate-native-user-token.js"; import define from "../../define.js"; import { Users, UserProfiles } from "@/models/index.js"; +import { comparePassword } from "@/misc/password.js"; export const meta = { requireCredential: true, @@ -29,7 +29,7 @@ export default define(meta, paramDef, async (ps, user) => { const profile = await UserProfiles.findOneByOrFail({ userId: user.id }); // Compare password - const same = await bcrypt.compare(ps.password, profile.password!); + const same = await comparePassword(ps.password, profile.password!); if (!same) { throw new Error("incorrect password"); diff --git a/packages/backend/src/server/api/endpoints/i/update-email.ts b/packages/backend/src/server/api/endpoints/i/update-email.ts index c3c24d4d3..94ad6b3c7 100644 --- a/packages/backend/src/server/api/endpoints/i/update-email.ts +++ b/packages/backend/src/server/api/endpoints/i/update-email.ts @@ -2,12 +2,12 @@ import { publishMainStream } from "@/services/stream.js"; import define from "../../define.js"; import rndstr from "rndstr"; import config from "@/config/index.js"; -import bcrypt from "bcryptjs"; import { Users, UserProfiles } from "@/models/index.js"; import { sendEmail } from "@/services/send-email.js"; import { ApiError } from "../../error.js"; import { validateEmailForAccount } from "@/services/validate-email-for-account.js"; import { HOUR } from "@/const.js"; +import { comparePassword } from "@/misc/password.js"; export const meta = { requireCredential: true, @@ -47,7 +47,7 @@ export default define(meta, paramDef, async (ps, user) => { const profile = await UserProfiles.findOneByOrFail({ userId: user.id }); // Compare password - const same = await bcrypt.compare(ps.password, profile.password!); + const same = await comparePassword(ps.password, profile.password!); if (!same) { throw new ApiError(meta.errors.incorrectPassword); diff --git a/packages/backend/src/server/api/endpoints/reset-password.ts b/packages/backend/src/server/api/endpoints/reset-password.ts index 51755727a..f695ae41f 100644 --- a/packages/backend/src/server/api/endpoints/reset-password.ts +++ b/packages/backend/src/server/api/endpoints/reset-password.ts @@ -1,8 +1,8 @@ -import bcrypt from "bcryptjs"; import { publishMainStream } from "@/services/stream.js"; import { Users, UserProfiles, PasswordResetRequests } from "@/models/index.js"; import define from "../define.js"; import { ApiError } from "../error.js"; +import { hashPassword } from "@/misc/password.js"; export const meta = { tags: ["reset password"], @@ -34,8 +34,7 @@ export default define(meta, paramDef, async (ps, user) => { } // Generate hash of password - const salt = await bcrypt.genSalt(8); - const hash = await bcrypt.hash(ps.password, salt); + const hash = await hashPassword(ps.password); await UserProfiles.update(req.userId, { password: hash, diff --git a/packages/backend/src/server/api/private/signin.ts b/packages/backend/src/server/api/private/signin.ts index 7c4b511a2..ef5b13781 100644 --- a/packages/backend/src/server/api/private/signin.ts +++ b/packages/backend/src/server/api/private/signin.ts @@ -1,5 +1,4 @@ import type Koa from "koa"; -import bcrypt from "bcryptjs"; import * as speakeasy from "speakeasy"; import signin from "../common/signin.js"; import config from "@/config/index.js"; diff --git a/packages/backend/src/server/api/private/signup.ts b/packages/backend/src/server/api/private/signup.ts index dc5eb2316..754d86c3b 100644 --- a/packages/backend/src/server/api/private/signup.ts +++ b/packages/backend/src/server/api/private/signup.ts @@ -1,6 +1,5 @@ import type Koa from "koa"; import rndstr from "rndstr"; -import bcrypt from "bcryptjs"; import { fetchMeta } from "@/misc/fetch-meta.js"; import { verifyHcaptcha, verifyRecaptcha } from "@/misc/captcha.js"; import { Users, RegistrationTickets, UserPendings } from "@/models/index.js"; @@ -9,6 +8,7 @@ import config from "@/config/index.js"; import { sendEmail } from "@/services/send-email.js"; import { genId } from "@/misc/gen-id.js"; import { validateEmailForAccount } from "@/services/validate-email-for-account.js"; +import { hashPassword } from "@/misc/password.js"; export default async (ctx: Koa.Context) => { const body = ctx.request.body; @@ -79,8 +79,7 @@ export default async (ctx: Koa.Context) => { const code = rndstr("a-z0-9", 16); // Generate hash of password - const salt = await bcrypt.genSalt(8); - const hash = await bcrypt.hash(password, salt); + const hash = await hashPassword(password); await UserPendings.insert({ id: genId(), diff --git a/packages/backend/src/services/create-system-user.ts b/packages/backend/src/services/create-system-user.ts index def3ee98f..24536090a 100644 --- a/packages/backend/src/services/create-system-user.ts +++ b/packages/backend/src/services/create-system-user.ts @@ -1,4 +1,3 @@ -import bcrypt from "bcryptjs"; import { v4 as uuid } from "uuid"; import generateNativeUserToken from "../server/api/common/generate-native-user-token.js"; import { genRsaKeyPair } from "@/misc/gen-key-pair.js"; @@ -9,13 +8,13 @@ import { genId } from "@/misc/gen-id.js"; import { UserKeypair } from "@/models/entities/user-keypair.js"; import { UsedUsername } from "@/models/entities/used-username.js"; import { db } from "@/db/postgre.js"; +import { hashPassword } from "@/misc/password.js"; export async function createSystemUser(username: string) { const password = uuid(); // Generate hash of password - const salt = await bcrypt.genSalt(8); - const hash = await bcrypt.hash(password, salt); + const hash = await hashPassword(password); // Generate secret const secret = generateNativeUserToken();