mirror of
https://github.com/BradNut/example-sveltekit-email-password-webauthn
synced 2025-09-08 17:40:27 +00:00
update response
This commit is contained in:
parent
d440b7c183
commit
d9bfd6bc22
12 changed files with 48 additions and 66 deletions
|
|
@ -5,10 +5,11 @@ import { encodeBase32LowerCaseNoPadding } from "@oslojs/encoding";
|
||||||
|
|
||||||
import type { RequestEvent } from "@sveltejs/kit";
|
import type { RequestEvent } from "@sveltejs/kit";
|
||||||
|
|
||||||
export function getEmailVerificationRequest(id: string): EmailVerificationRequest | null {
|
export function getUserEmailVerificationRequest(userId: number, id: string): EmailVerificationRequest | null {
|
||||||
const row = db.queryOne("SELECT id, user_id, code, email, expires_at FROM email_verification_request WHERE id = ?", [
|
const row = db.queryOne(
|
||||||
id
|
"SELECT id, user_id, code, email, expires_at FROM email_verification_request WHERE id = ? AND user_id = ?",
|
||||||
]);
|
[id, userId]
|
||||||
|
);
|
||||||
if (row === null) {
|
if (row === null) {
|
||||||
return row;
|
return row;
|
||||||
}
|
}
|
||||||
|
|
@ -81,8 +82,8 @@ export function getUserEmailVerificationRequestFromRequest(event: RequestEvent):
|
||||||
if (id === null) {
|
if (id === null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const request = getEmailVerificationRequest(id);
|
const request = getUserEmailVerificationRequest(event.locals.user.id, id);
|
||||||
if (request !== null && request.userId !== event.locals.user.id) {
|
if (request !== null) {
|
||||||
deleteEmailVerificationRequestCookie(event);
|
deleteEmailVerificationRequestCookie(event);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,12 +23,11 @@ export async function POST(event: RequestEvent) {
|
||||||
status: 401
|
status: 401
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (!event.locals.user.emailVerified) {
|
if (
|
||||||
return new Response("Forbidden", {
|
!event.locals.user.emailVerified ||
|
||||||
status: 403
|
!event.locals.user.registeredPasskey ||
|
||||||
});
|
event.locals.session.twoFactorVerified
|
||||||
}
|
) {
|
||||||
if (!event.locals.user.registeredPasskey) {
|
|
||||||
return new Response("Forbidden", {
|
return new Response("Forbidden", {
|
||||||
status: 403
|
status: 403
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -29,12 +29,7 @@ async function action(event: RequestEvent) {
|
||||||
message: "Not authenticated"
|
message: "Not authenticated"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (!event.locals.user.emailVerified) {
|
if (!event.locals.user.emailVerified || !event.locals.user.registered2FA || event.locals.session.twoFactorVerified) {
|
||||||
return fail(403, {
|
|
||||||
message: "Forbidden"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (!event.locals.user.registered2FA) {
|
|
||||||
return fail(403, {
|
return fail(403, {
|
||||||
message: "Forbidden"
|
message: "Forbidden"
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -23,12 +23,11 @@ export async function POST(event: RequestEvent) {
|
||||||
status: 401
|
status: 401
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (!event.locals.user.emailVerified) {
|
if (
|
||||||
return new Response("Forbidden", {
|
!event.locals.user.emailVerified ||
|
||||||
status: 403
|
!event.locals.user.registeredSecurityKey ||
|
||||||
});
|
event.locals.session.twoFactorVerified
|
||||||
}
|
) {
|
||||||
if (!event.locals.user.registeredSecurityKey) {
|
|
||||||
return new Response("Forbidden", {
|
return new Response("Forbidden", {
|
||||||
status: 403
|
status: 403
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -33,12 +33,7 @@ async function action(event: RequestEvent) {
|
||||||
message: "Not authenticated"
|
message: "Not authenticated"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (!event.locals.user.emailVerified) {
|
if (!event.locals.user.emailVerified || !event.locals.user.registeredTOTP || event.locals.session.twoFactorVerified) {
|
||||||
return fail(403, {
|
|
||||||
message: "Forbidden"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (!event.locals.user.registered2FA) {
|
|
||||||
return fail(403, {
|
return fail(403, {
|
||||||
message: "Forbidden"
|
message: "Forbidden"
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
import { redirect } from "@sveltejs/kit";
|
|
||||||
import { getPasswordReset2FARedirect } from "$lib/server/2fa";
|
import { getPasswordReset2FARedirect } from "$lib/server/2fa";
|
||||||
import { validatePasswordResetSessionRequest } from "$lib/server/password-reset";
|
import { validatePasswordResetSessionRequest } from "$lib/server/password-reset";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,12 +24,7 @@ export async function POST(event: RequestEvent) {
|
||||||
status: 401
|
status: 401
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (!user.emailVerified) {
|
if (!user.emailVerified || !user.registeredPasskey || session.twoFactorVerified) {
|
||||||
return new Response("Forbidden", {
|
|
||||||
status: 403
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (!user.registeredPasskey) {
|
|
||||||
return new Response("Forbidden", {
|
return new Response("Forbidden", {
|
||||||
status: 403
|
status: 403
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -29,28 +29,23 @@ export const actions: Actions = {
|
||||||
};
|
};
|
||||||
|
|
||||||
async function action(event: RequestEvent) {
|
async function action(event: RequestEvent) {
|
||||||
const { session } = validatePasswordResetSessionRequest(event);
|
const { session, user } = validatePasswordResetSessionRequest(event);
|
||||||
if (session === null) {
|
if (session === null) {
|
||||||
return fail(401, {
|
return fail(401, {
|
||||||
message: "Not authenticated"
|
message: "Not authenticated"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (!session.emailVerified) {
|
if (!user.emailVerified || !user.registered2FA || session.twoFactorVerified) {
|
||||||
return fail(403, {
|
return fail(403, {
|
||||||
message: "Forbidden"
|
message: "Forbidden"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!recoveryCodeBucket.check(session.userId, 1)) {
|
if (!recoveryCodeBucket.check(session.userId, 1)) {
|
||||||
return fail(429, {
|
return fail(429, {
|
||||||
message: "Too many requests"
|
message: "Too many requests"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (session.twoFactorVerified) {
|
|
||||||
return fail(400, {
|
|
||||||
message: "Already verified"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const formData = await event.request.formData();
|
const formData = await event.request.formData();
|
||||||
const code = formData.get("code");
|
const code = formData.get("code");
|
||||||
if (typeof code !== "string") {
|
if (typeof code !== "string") {
|
||||||
|
|
|
||||||
|
|
@ -24,12 +24,7 @@ export async function POST(event: RequestEvent) {
|
||||||
status: 401
|
status: 401
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (!user.emailVerified) {
|
if (!user.emailVerified || !user.registeredSecurityKey || session.twoFactorVerified) {
|
||||||
return new Response("Forbidden", {
|
|
||||||
status: 403
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (!user.registeredSecurityKey) {
|
|
||||||
return new Response("Forbidden", {
|
return new Response("Forbidden", {
|
||||||
status: 403
|
status: 403
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -40,16 +40,16 @@ async function action(event: RequestEvent) {
|
||||||
message: "Not authenticated"
|
message: "Not authenticated"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (!user.emailVerified || !user.registeredTOTP || session.twoFactorVerified) {
|
||||||
|
return fail(403, {
|
||||||
|
message: "Forbidden"
|
||||||
|
});
|
||||||
|
}
|
||||||
if (!totpBucket.check(session.userId, 1)) {
|
if (!totpBucket.check(session.userId, 1)) {
|
||||||
return fail(429, {
|
return fail(429, {
|
||||||
message: "Too many requests"
|
message: "Too many requests"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (!user.registered2FA || session.twoFactorVerified || !session.emailVerified) {
|
|
||||||
return fail(403, {
|
|
||||||
message: "Forbidden"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const formData = await event.request.formData();
|
const formData = await event.request.formData();
|
||||||
const code = formData.get("code");
|
const code = formData.get("code");
|
||||||
|
|
|
||||||
|
|
@ -38,17 +38,17 @@ async function action(event: RequestEvent) {
|
||||||
message: "Not authenticated"
|
message: "Not authenticated"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (session.emailVerified) {
|
||||||
|
return fail(403, {
|
||||||
|
message: "Forbidden"
|
||||||
|
});
|
||||||
|
}
|
||||||
if (!bucket.check(session.userId, 1)) {
|
if (!bucket.check(session.userId, 1)) {
|
||||||
return fail(429, {
|
return fail(429, {
|
||||||
message: "Too many requests"
|
message: "Too many requests"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (session.emailVerified) {
|
|
||||||
return fail(400, {
|
|
||||||
message: "Already verified"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
const formData = await event.request.formData();
|
const formData = await event.request.formData();
|
||||||
const code = formData.get("code");
|
const code = formData.get("code");
|
||||||
if (typeof code !== "string") {
|
if (typeof code !== "string") {
|
||||||
|
|
|
||||||
|
|
@ -131,10 +131,6 @@ async function resendEmail(event: RequestEvent) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let verificationRequest = getUserEmailVerificationRequestFromRequest(event);
|
|
||||||
if (verificationRequest === null) {
|
|
||||||
return fail(401);
|
|
||||||
}
|
|
||||||
if (!sendVerificationEmailBucket.consume(event.locals.user.id, 1)) {
|
if (!sendVerificationEmailBucket.consume(event.locals.user.id, 1)) {
|
||||||
return fail(429, {
|
return fail(429, {
|
||||||
resend: {
|
resend: {
|
||||||
|
|
@ -142,7 +138,20 @@ async function resendEmail(event: RequestEvent) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
verificationRequest = createEmailVerificationRequest(verificationRequest.userId, verificationRequest.email);
|
|
||||||
|
let verificationRequest = getUserEmailVerificationRequestFromRequest(event);
|
||||||
|
if (verificationRequest === null) {
|
||||||
|
if (event.locals.user.emailVerified) {
|
||||||
|
return fail(403, {
|
||||||
|
resend: {
|
||||||
|
message: "Forbidden"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
verificationRequest = createEmailVerificationRequest(event.locals.user.id, event.locals.user.email);
|
||||||
|
} else {
|
||||||
|
verificationRequest = createEmailVerificationRequest(event.locals.user.id, verificationRequest.email);
|
||||||
|
}
|
||||||
sendVerificationEmail(verificationRequest.email, verificationRequest.code);
|
sendVerificationEmail(verificationRequest.email, verificationRequest.code);
|
||||||
setEmailVerificationRequestCookie(event, verificationRequest);
|
setEmailVerificationRequestCookie(event, verificationRequest);
|
||||||
return {
|
return {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue