Dyrected
Guides

Adding Authentication

Add a users collection with login, JWT auth, and protected routes.

1. Add an auth collection

// dyrected.config.ts  (same for both frameworks)
export default defineConfig({
  collections: [
    {
      slug: 'users',
      auth: true,
      fields: [
        { name: 'name', type: 'text' },
      ],
    },
  ],
})

2. Set the JWT secret

# .env.local
DYRECTED_JWT_SECRET=a-long-random-secret-at-least-32-chars

The same secret must be set in every environment. Rotating it invalidates all existing sessions.


3. Log in

import { createClient } from '@dyrected/sdk'

const client = createClient({ baseUrl: '/dyrected' })

const { token, user } = await client.collection('users').login(
  'jane@example.com',
  'hunter2'
)
// app/login/actions.ts
'use server'
import { cookies } from 'next/headers'
import { createClient } from '@dyrected/sdk'

const client = createClient({ baseUrl: process.env.NEXT_PUBLIC_DYRECTED_URL! })

export async function login(email: string, password: string) {
  const { token, user } = await client.collection('users').login(email, password)
  
  cookies().set('dyrected-token', token, { httpOnly: true, path: '/' })
  return user
}
<!-- components/LoginForm.vue -->
<script setup lang="ts">
const { login, user, logout } = useDyrectedAuth('users')

async function submit(e: Event) {
  const form = e.target as HTMLFormElement
  await login(form.email.value, form.password.value)
}
</script>

<template>
  <div v-if="user">
    Hello, {{ user.name }} — <button @click="logout">Log out</button>
  </div>
  <form v-else @submit.prevent="submit">
    <input name="email" type="email" placeholder="Email" />
    <input name="password" type="password" placeholder="Password" />
    <button type="submit">Log in</button>
  </form>
</template>

4. Protect API routes

// dyrected.config.ts — access functions work the same in both frameworks
{
  slug: 'orders',
  access: {
    read:   ({ user }) => !!user,
    create: ({ user }) => !!user,
    update: ({ user, doc }) => user?.id === doc.userId,
    delete: ({ user }) => user?.role === 'admin',
  },
}

5. Protect frontend routes

// middleware.ts
import { NextRequest, NextResponse } from 'next/server'

export function middleware(req: NextRequest) {
  const token = req.cookies.get('dyrected-token')?.value
  if (!token) {
    return NextResponse.redirect(new URL('/login', req.url))
  }
  return NextResponse.next()
}

export const config = {
  matcher: ['/dashboard/:path*', '/account/:path*'],
}
// middleware/auth.ts
export default defineNuxtRouteMiddleware(() => {
  const { user } = useDyrectedAuth('users')
  if (!user.value) return navigateTo('/login')
})

Apply it to a page:

<!-- pages/dashboard.vue -->
<script setup>
definePageMeta({ middleware: 'auth' })
</script>

6. Get the current user

// In a Server Component
import { cookies } from 'next/headers'
import { createClient } from '@dyrected/sdk'

const client = createClient({ baseUrl: process.env.NEXT_PUBLIC_DYRECTED_URL! })

async function getUser() {
  const token = cookies().get('dyrected-token')?.value
  if (!token) return null

  client.setToken(token)
  try {
    return await client.collection('users').me()
  } catch {
    return null
  }
}
<script setup lang="ts">
const { user } = useDyrectedAuth('users')
// reactive — updates automatically on login/logout
</script>

<template>
  <span v-if="user">{{ user.name }}</span>
</template>

Next steps

On this page