Add passkey and magic link authentication

This commit is contained in:
JB
2026-07-25 01:54:33 -04:00
parent 3c9f443499
commit c3244b0c79
31 changed files with 1017 additions and 58 deletions
+43
View File
@@ -0,0 +1,43 @@
import { env } from '$env/dynamic/private';
import nodemailer from 'nodemailer';
let transporter: ReturnType<typeof nodemailer.createTransport> | undefined;
function mailer() {
if (!env.SMTP_HOST || !env.SMTP_FROM) {
throw new Error('Email delivery is not configured.');
}
if (!transporter) {
transporter = nodemailer.createTransport({
host: env.SMTP_HOST,
port: Number(env.SMTP_PORT || 587),
secure: env.SMTP_SECURE === 'true',
auth: env.SMTP_USER ? { user: env.SMTP_USER, pass: env.SMTP_PASSWORD } : undefined,
requireTLS: env.SMTP_SECURE !== 'true',
disableFileAccess: true,
disableUrlAccess: true
});
}
return transporter;
}
export function applicationOrigin(): string {
return (env.APP_ORIGIN || 'http://localhost:5173').replace(/\/+$/, '');
}
export function emailDeliveryConfigured(): boolean {
return Boolean(env.SMTP_HOST && env.SMTP_FROM);
}
export async function sendAuthenticationLink(email: string, token: string, purpose: 'login' | 'verify_email'): Promise<void> {
const url = `${applicationOrigin()}/auth/magic-link?token=${encodeURIComponent(token)}`;
const subject = purpose === 'login' ? 'Sign in to SHD.build' : 'Verify your SHD.build email';
const action = purpose === 'login' ? 'SIGN IN TO SHD.BUILD' : 'VERIFY EMAIL ADDRESS';
await mailer().sendMail({
from: env.SMTP_FROM,
to: email,
subject,
text: `${subject}\n\nOpen this one-time link within 15 minutes:\n${url}\n\nIf you did not request this, you can ignore this message.`,
html: `<div style="background:#0a0c0d;color:#ecebe5;padding:28px;font-family:Arial,sans-serif"><p style="color:#f6a821;font-size:12px;letter-spacing:2px">SHD IDENTITY NETWORK</p><h1 style="font-size:24px">${subject}</h1><p style="color:#a5aaab">This one-time link expires in 15 minutes.</p><p><a href="${url}" style="display:inline-block;background:#f6a821;color:#111;padding:14px 20px;text-decoration:none;font-weight:800">${action}</a></p><p style="color:#737a7c;font-size:12px">If you did not request this, you can ignore this message.</p></div>`
});
}