fix: resolve auth security issues - 2FA require TOTP on disable, rate limiting, timing-safe login, token expiry check
This commit is contained in:
1 parent
4a06b30263
commit
64f50b2dde
6 files changed
+63
-9
No files matched your search
@@ -6,6 +6,7 @@ import { LaravelEncrypter } from "@/lib/auth/laravel-encrypter";
|
||||
import { generateTotpSecret, verifyTotp } from "@/lib/auth/totp";
|
||||
import { auth } from "@/lib/auth";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { clientIp, rateLimit } from "@/lib/rate-limit";
|
||||
import { env } from "@/env";
|
||||
|
||||
async function sessionUserId(): Promise<number> {
|
||||
@@ -31,6 +32,9 @@ export async function beginTwoFactor(): Promise<void> {
|
||||
export async function confirmTwoFactor(formData: FormData): Promise<void> {
|
||||
const id = await sessionUserId();
|
||||
if (!env.APP_KEY) redirect("/settings/2fa?error=noappkey");
|
||||
|
||||
if (!rateLimit(`2fa-confirm:${id}`, 5, 30_000).ok) redirect("/settings/2fa?error=ratelimit");
|
||||
|
||||
const code = String(formData.get("code") ?? "").trim();
|
||||
|
||||
const user = await prisma.user.findUnique({
|
||||
@@ -53,8 +57,30 @@ export async function confirmTwoFactor(formData: FormData): Promise<void> {
|
||||
redirect("/settings/2fa?enabled=1");
|
||||
}
|
||||
|
||||
export async function disableTwoFactor(): Promise<void> {
|
||||
export async function disableTwoFactor(formData: FormData): Promise<void> {
|
||||
const id = await sessionUserId();
|
||||
if (!env.APP_KEY) redirect("/settings/2fa?error=noappkey");
|
||||
|
||||
if (!rateLimit(`2fa-disable:${id}`, 5, 30_000).ok) redirect("/settings/2fa?error=ratelimit");
|
||||
|
||||
const code = String(formData.get("code") ?? "").trim();
|
||||
|
||||
const user = await prisma.user.findUnique({
|
||||
where: { id },
|
||||
select: { twoFactorSecret: true },
|
||||
});
|
||||
|
||||
let ok = false;
|
||||
if (user?.twoFactorSecret && code) {
|
||||
try {
|
||||
const secret = new LaravelEncrypter(env.APP_KEY).decrypt(user.twoFactorSecret);
|
||||
ok = verifyTotp(code, secret);
|
||||
} catch {
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
if (!ok) redirect("/settings/2fa?error=badcode");
|
||||
|
||||
await prisma.user.update({
|
||||
where: { id },
|
||||
data: {
|
||||
|
||||
Reference in new issue
Block a user