audit: harden better-auth config, fix types, cleanup
- Fix email verification link using Better Auth's url parameter (was hardcoded to google.com) - Make App.Locals session/user types nullable to match reality - Add explicit rate limiting config (60s window, 100 max) - Add trusted origins for localhost:5173 and production domain - Add Forgot Password? and Register links to login page - Remove unused dead code from auth-client.ts - Remove outdated known-bug note from AGENTS.md (register redirect is fixed)
This commit is contained in:
@@ -31,7 +31,6 @@ Requires `.env` with at least `DATABASE_URL`, `BETTER_AUTH_SECRET`, `BETTER_AUTH
|
|||||||
- **`expect: { requireAssertions: true }`** — every test must assert something.
|
- **`expect: { requireAssertions: true }`** — every test must assert something.
|
||||||
- **All route tests mock `$lib/db`** (Prisma client) and `$lib/auth-client`/`$lib/auth` via `vi.mock()`. Stub factories in `src/lib/test-utils.ts`.
|
- **All route tests mock `$lib/db`** (Prisma client) and `$lib/auth-client`/`$lib/auth` via `vi.mock()`. Stub factories in `src/lib/test-utils.ts`.
|
||||||
- **No `.env.test`** — mocking `$lib/db` makes real DB unnecessary.
|
- **No `.env.test`** — mocking `$lib/db` makes real DB unnecessary.
|
||||||
- **Known bug**: register page `throw redirect()` is caught by try/catch and returns 400 instead of redirecting (documented in test).
|
|
||||||
|
|
||||||
## Architecture notes
|
## Architecture notes
|
||||||
|
|
||||||
|
|||||||
Vendored
+2
-2
@@ -3,8 +3,8 @@ import type { Session, User } from "better-auth";
|
|||||||
declare global {
|
declare global {
|
||||||
namespace App {
|
namespace App {
|
||||||
interface Locals {
|
interface Locals {
|
||||||
session: Session,
|
session: Session | null;
|
||||||
user: User,
|
user: User | null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,3 @@
|
|||||||
import { createAuthClient } from "better-auth/svelte"
|
import { createAuthClient } from "better-auth/svelte"
|
||||||
|
|
||||||
export const authClient = createAuthClient({});
|
export const authClient = createAuthClient({});
|
||||||
|
|
||||||
const signIn = async () => {
|
|
||||||
const data = await authClient.signIn.social({
|
|
||||||
provider: "google",
|
|
||||||
});
|
|
||||||
};
|
|
||||||
+11
-2
@@ -11,13 +11,13 @@ export const auth = betterAuth({
|
|||||||
provider: 'postgresql'
|
provider: 'postgresql'
|
||||||
}),
|
}),
|
||||||
emailVerification: {
|
emailVerification: {
|
||||||
sendVerificationEmail: async ({ user }) => {
|
sendVerificationEmail: async ({ user, url }) => {
|
||||||
void sendMail({
|
void sendMail({
|
||||||
to: user.email,
|
to: user.email,
|
||||||
templateId: 'email-verification-email',
|
templateId: 'email-verification-email',
|
||||||
data: {
|
data: {
|
||||||
target_email_address: user.email,
|
target_email_address: user.email,
|
||||||
verification_link: 'https://google.com'
|
verification_link: url
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -43,5 +43,14 @@ export const auth = betterAuth({
|
|||||||
clientSecret: process.env.GOOGLE_CLIENT_SECRET as string
|
clientSecret: process.env.GOOGLE_CLIENT_SECRET as string
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
rateLimit: {
|
||||||
|
enabled: true,
|
||||||
|
window: 60,
|
||||||
|
max: 100
|
||||||
|
},
|
||||||
|
trustedOrigins: [
|
||||||
|
'http://localhost:5173',
|
||||||
|
'https://portal.rhemawavetech.com'
|
||||||
|
],
|
||||||
plugins: [sveltekitCookies(getRequestEvent)]
|
plugins: [sveltekitCookies(getRequestEvent)]
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -36,6 +36,14 @@
|
|||||||
<input type="password" placeholder="Password" bind:value={password} required class="my-2" />
|
<input type="password" placeholder="Password" bind:value={password} required class="my-2" />
|
||||||
<button class="mt-4 rounded bg-blue-200 px-4 py-2" type="submit">Sign In</button>
|
<button class="mt-4 rounded bg-blue-200 px-4 py-2" type="submit">Sign In</button>
|
||||||
</form>
|
</form>
|
||||||
|
<div class="mt-2 flex flex-col items-center gap-2">
|
||||||
|
<a href="/forgot-password" class="text-sm text-blue-600 hover:text-blue-800"
|
||||||
|
>Forgot Password?</a
|
||||||
|
>
|
||||||
|
<a href="/register" class="text-sm text-blue-600 hover:text-blue-800"
|
||||||
|
>Don't have an account? Register</a
|
||||||
|
>
|
||||||
|
</div>
|
||||||
<div class="mt-4 flex flex-col items-center justify-center">
|
<div class="mt-4 flex flex-col items-center justify-center">
|
||||||
<span>Or</span>
|
<span>Or</span>
|
||||||
<button
|
<button
|
||||||
|
|||||||
Reference in New Issue
Block a user