Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion apps/blog-next/app/api/login/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { loginForm } from '@/lib/schemas/auth'

export async function POST(request: Request) {
const submission = await validate(request, loginForm, {
csrf: true,
throttle: 'login',
})

Expand Down
1 change: 0 additions & 1 deletion apps/blog-next/app/api/register/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { registerForm } from '@/lib/schemas/auth'

export async function POST(request: Request) {
const submission = await validate(request, registerForm, {
csrf: true,
throttle: 'register',
})

Expand Down
1 change: 0 additions & 1 deletion apps/blog-next/app/login/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import { loginForm } from '@/lib/schemas/auth'

export async function loginAction(formData: FormData) {
const submission = await validate(formData, loginForm, {
csrf: true,
throttle: 'login',
})

Expand Down
1 change: 0 additions & 1 deletion apps/blog-next/app/login/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ const panelStyle = {

export default function LoginPage() {
const form = useForm(loginForm, {
csrf: true,
validateOn: 'blur',
initialValues: { email: '', password: '', remember: false },
async submitter({ formData }) {
Expand Down
1 change: 0 additions & 1 deletion apps/blog-next/app/register/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import { registerForm } from '@/lib/schemas/auth'

export async function registerAction(formData: FormData) {
const submission = await validate(formData, registerForm, {
csrf: true,
throttle: 'register',
})

Expand Down
1 change: 0 additions & 1 deletion apps/blog-next/app/register/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ const panelStyle = {

export default function RegisterPage() {
const form = useForm(registerForm, {
csrf: true,
validateOn: 'blur',
initialValues: { name: '', email: '', password: '', passwordConfirmation: '' },
async submitter({ formData }) {
Expand Down
2 changes: 1 addition & 1 deletion apps/blog-next/config/security.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export default defineSecurityConfig({
field: '_token',
header: 'X-CSRF-TOKEN',
cookie: 'XSRF-TOKEN',
except: [],
except: ['/api/v1/*'],
},
rateLimit: {
driver: 'file',
Expand Down
25 changes: 23 additions & 2 deletions apps/blog-next/proxy.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { authOnly, guestOnly, protectRoutes } from '@holo-js/auth/next/server'
import { csrfProtection } from '@holo-js/security/next/server'

export const proxy = protectRoutes(
const csrf = csrfProtection()
const auth = protectRoutes(
guestOnly({
routes: ['/login', '/register', '/forgot-password', '/reset-password'],
redirectTo: '/admin',
Expand All @@ -21,6 +23,25 @@ export const proxy = protectRoutes(
}),
)

export async function proxy(request: Parameters<typeof csrf>[0]) {
const csrfResponse = await csrf(request)
if (csrfResponse?.status === 419) {
return csrfResponse
}

const authResponse = await auth(request)
return authResponse ?? csrfResponse
}

export const config = {
matcher: ['/login', '/register', '/forgot-password', '/reset-password', '/admin/:path*', '/super-admin', '/super-admin/login'],
matcher: [
'/login',
'/register',
'/forgot-password',
'/reset-password',
'/admin/:path*',
'/super-admin',
'/super-admin/login',
'/api/:path*',
],
}
1 change: 0 additions & 1 deletion apps/blog-next/tests/login-page.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,6 @@ describe('login action', () => {
})

expect(mocks.validate).toHaveBeenCalledWith(formData, {}, {
csrf: true,
throttle: 'login',
})
expect(mocks.login).toHaveBeenCalledWith({
Expand Down
3 changes: 0 additions & 3 deletions apps/blog-next/tests/register-page.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -127,11 +127,9 @@ describe('register page', () => {
})

expect(mocks.useForm).toHaveBeenCalledWith(mocks.registerForm, expect.objectContaining({
csrf: true,
validateOn: 'blur',
}))
expect(mocks.validate).toHaveBeenCalledWith(expect.any(FormData), mocks.registerForm, {
csrf: true,
throttle: 'register',
})
expect(mocks.register).not.toHaveBeenCalled()
Expand Down Expand Up @@ -165,7 +163,6 @@ describe('registerAction', () => {

await expect(registerAction(new FormData())).resolves.toBe(failure)
expect(mocks.validate).toHaveBeenCalledWith(expect.any(FormData), mocks.registerForm, {
csrf: true,
throttle: 'register',
})
expect(mocks.register).not.toHaveBeenCalled()
Expand Down
1 change: 0 additions & 1 deletion apps/blog-nuxt/app/pages/login/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { loginForm } from '#shared/schemas/auth'

const { refreshUser } = await useAuth()
const form = useForm(loginForm, {
csrf: true,
validateOn: 'blur',
initialValues: { email: '', password: '', remember: false },
async submitter({ formData }) {
Expand Down
1 change: 0 additions & 1 deletion apps/blog-nuxt/app/pages/register/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { registerForm } from '#shared/schemas/auth'

const { refreshUser } = await useAuth()
const form = useForm(registerForm, {
csrf: true,
validateOn: 'blur',
initialValues: { name: '', email: '', password: '', passwordConfirmation: '' },
async submitter({ formData }) {
Expand Down
2 changes: 1 addition & 1 deletion apps/blog-nuxt/config/security.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export default defineSecurityConfig({
field: '_token',
header: 'X-CSRF-TOKEN',
cookie: 'XSRF-TOKEN',
except: [],
except: ['/api/v1/*'],
},
rateLimit: {
driver: 'file',
Expand Down
1 change: 0 additions & 1 deletion apps/blog-nuxt/server/api/login.post.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { loginForm } from '#shared/schemas/auth'

export default defineEventHandler(async (event) => {
const submission = await validate(event, loginForm, {
csrf: true,
throttle: 'login',
})

Expand Down
1 change: 0 additions & 1 deletion apps/blog-nuxt/server/api/register.post.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { registerForm } from '#shared/schemas/auth'

export default defineEventHandler(async (event) => {
const submission = await validate(event, registerForm, {
csrf: true,
throttle: 'register',
})

Expand Down
3 changes: 3 additions & 0 deletions apps/blog-nuxt/server/middleware/csrf.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { csrfProtection } from '@holo-js/security/nuxt/server'

export default csrfProtection()
2 changes: 1 addition & 1 deletion apps/blog-sveltekit/config/security.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export default defineSecurityConfig({
field: '_token',
header: 'X-CSRF-TOKEN',
cookie: 'XSRF-TOKEN',
except: [],
except: ['/api/v1/*'],
},
rateLimit: {
driver: 'file',
Expand Down
2 changes: 2 additions & 0 deletions apps/blog-sveltekit/src/hooks.server.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { sequence } from '@sveltejs/kit/hooks'
import { authOnly, guestOnly } from '@holo-js/auth/sveltekit/server'
import { csrfProtection } from '@holo-js/security/sveltekit/server'

export const handle = sequence(
csrfProtection(),
guestOnly({
routes: ['/login', '/register', '/forgot-password', '/reset-password'],
redirectTo: '/admin',
Expand Down
4 changes: 1 addition & 3 deletions apps/blog-sveltekit/src/routes/+layout.server.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import { auth } from '@holo-js/auth/sveltekit/server'
import { csrf } from '@holo-js/security'
import type { LayoutServerLoad } from './$types'

export const load = (async ({ request }) => {
export const load = (async () => {
const currentAuth = await auth()

return {
auth: currentAuth,
csrf: await csrf.field(request),
}
}) satisfies LayoutServerLoad
10 changes: 8 additions & 2 deletions apps/blog-sveltekit/src/routes/login/+page.server.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
import { fail, redirect } from '@sveltejs/kit'
import { login } from '@holo-js/auth'
import { validate } from '@holo-js/forms'
import { csrf } from '@holo-js/security'

import { loginForm } from '$lib/schemas/auth'
import type { Actions } from './$types'
import type { Actions, PageServerLoad } from './$types'

export const load = (async ({ request }) => ({
csrf: {
input: await csrf.input(request),
},
})) satisfies PageServerLoad

export const actions = {
default: async ({ request }) => {
const submission = await validate(request, loginForm, {
csrf: true,
throttle: 'login',
})

Expand Down
2 changes: 1 addition & 1 deletion apps/blog-sveltekit/src/routes/login/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
</div>

<form class="stack" method="post">
<input type="hidden" name={data.csrf.name} value={data.csrf.value} />
<input {...data.csrf.input} />

{#if formError}
<p class="error">{formError}</p>
Expand Down
10 changes: 8 additions & 2 deletions apps/blog-sveltekit/src/routes/register/+page.server.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
import { fail, redirect } from '@sveltejs/kit'
import { loginUsing, register } from '@holo-js/auth'
import { validate } from '@holo-js/forms'
import { csrf } from '@holo-js/security'

import { registerForm } from '$lib/schemas/auth'
import type { Actions } from './$types'
import type { Actions, PageServerLoad } from './$types'

export const load = (async ({ request }) => ({
csrf: {
input: await csrf.input(request),
},
})) satisfies PageServerLoad

export const actions = {
default: async ({ request }) => {
const submission = await validate(request, registerForm, {
csrf: true,
throttle: 'register',
})

Expand Down
2 changes: 1 addition & 1 deletion apps/blog-sveltekit/src/routes/register/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
</div>

<form class="stack" method="post">
<input type="hidden" name={data.csrf.name} value={data.csrf.value} />
<input {...data.csrf.input} />

{#if formError}
<p class="error">{formError}</p>
Expand Down
10 changes: 8 additions & 2 deletions apps/blog-sveltekit/src/routes/super-admin/login/+page.server.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
import { fail, redirect } from '@sveltejs/kit'
import auth from '@holo-js/auth'
import { validate } from '@holo-js/forms'
import { csrf } from '@holo-js/security'

import { loginForm } from '$lib/schemas/auth'
import type { Actions } from './$types'
import type { Actions, PageServerLoad } from './$types'

export const load = (async ({ request }) => ({
csrf: {
input: await csrf.input(request),
},
})) satisfies PageServerLoad

export const actions = {
default: async ({ request }) => {
const submission = await validate(request, loginForm, {
csrf: true,
throttle: 'login',
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
</div>

<form class="stack" method="post">
<input type="hidden" name={data.csrf.name} value={data.csrf.value} />
<input {...data.csrf.input} />

{#if formError}
<p class="error">{formError}</p>
Expand Down
3 changes: 0 additions & 3 deletions apps/blog-sveltekit/tests/auth-page-actions.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@ describe('SvelteKit login page action', () => {
expect(response.status).toBe(422)
expect(response).toEqual(failure)
expect(mocks.validate).toHaveBeenCalledWith(expect.any(Request), mocks.loginForm, {
csrf: true,
throttle: 'login',
})
expect(mocks.login).not.toHaveBeenCalled()
Expand Down Expand Up @@ -165,7 +164,6 @@ describe('SvelteKit register page action', () => {
expect(response.status).toBe(422)
expect(response).toEqual(failure)
expect(mocks.validate).toHaveBeenCalledWith(expect.any(Request), mocks.registerForm, {
csrf: true,
throttle: 'register',
})
expect(mocks.register).not.toHaveBeenCalled()
Expand Down Expand Up @@ -278,7 +276,6 @@ describe('SvelteKit super admin login page action', () => {
expect(response.status).toBe(422)
expect(response).toEqual(failure)
expect(mocks.validate).toHaveBeenCalledWith(expect.any(Request), mocks.loginForm, {
csrf: true,
throttle: 'login',
})
expect(mocks.guardLogin).not.toHaveBeenCalled()
Expand Down
4 changes: 0 additions & 4 deletions apps/docs/docs/auth/current-auth-client.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ import { loginForm } from '@/lib/schemas/login'

export async function loginAction(formData: FormData) {
const submission = await validate(formData, loginForm, {
csrf: true,
throttle: 'login',
})

Expand All @@ -86,7 +85,6 @@ import { loginAction } from './actions'

export default function LoginPage() {
const form = useForm(loginForm, {
csrf: true,
async submitter({ formData }) {
return await loginAction(formData)
},
Expand Down Expand Up @@ -131,7 +129,6 @@ import { loginForm } from '$lib/schemas/login'

export async function POST({ request }: { request: Request }) {
const submission = await validate(request, loginForm, {
csrf: true,
throttle: 'login',
})

Expand Down Expand Up @@ -161,7 +158,6 @@ export async function POST({ request }: { request: Request }) {

const auth = useAuth()
const form = useForm(loginForm, {
csrf: true,
async submitter({ formData }) {
const submission = await (await fetch('/api/login', { method: 'POST', body: formData })).json()
if (submission.ok === true && typeof submission.data?.redirectTo === 'string') {
Expand Down
Loading