Server-Side Utilities
nuxt-directus-sdk provides server-side utilities for authenticating Directus requests in Nuxt server routes. These utilities automatically handle session tokens and admin authentication.
Overview
The module provides several server utilities:
useServerDirectus(event)- Authenticated requests using user sessionuseAdminDirectus()- Admin requests using admin tokenuseTokenDirectus(token)- Custom token authenticationgetDirectusSessionToken(event)- Manual token extraction
User Authentication
useServerDirectus(event)
Use the current user's session token for authenticated requests:
// server/api/profile.ts
export default defineEventHandler(async (event) => {
const directus = useServerDirectus(event)
// This request uses the user's session token
const user = await directus.request(readMe())
return { user }
})This automatically:
- Extracts the session token from cookies
- Attaches it to Directus requests
- Maintains the user's authentication context
Complete Example
// server/api/my-articles.ts
import { readItems } from '@directus/sdk'
export default defineEventHandler(async (event) => {
const directus = useServerDirectus(event)
try {
// Get current user
const user = await directus.request(readMe())
// Fetch user's articles
const articles = await directus.request(readItems('articles', {
filter: {
author: { _eq: user.id }
},
sort: ['-date_created'],
limit: 10,
}))
return {
user,
articles,
}
} catch (error) {
throw createError({
statusCode: 401,
message: 'Unauthorized - Please log in',
})
}
})Admin Authentication
useAdminDirectus()
Use the admin token for privileged operations:
// server/api/admin/users.ts
import { readUsers } from '@directus/sdk'
export default defineEventHandler(async () => {
const directus = useAdminDirectus()
// Admin-level access to all users
const users = await directus.request(readUsers({
fields: ['id', 'email', 'first_name', 'last_name', 'role'],
}))
return { users }
})Requirements:
DIRECTUS_ADMIN_TOKENmust be set in.env- Should only be used for server-side operations
- Never expose admin token to client
Admin Operations
// server/api/admin/create-user.ts
import { createUser } from '@directus/sdk'
export default defineEventHandler(async (event) => {
const directus = useAdminDirectus()
const body = await readBody(event)
// Create user with admin privileges
const user = await directus.request(createUser({
email: body.email,
password: body.password,
role: body.role,
}))
return { user }
})Custom Token Authentication
useTokenDirectus(token?)
Use a custom token for authentication:
// server/api/custom-auth.ts
export default defineEventHandler(async (event) => {
// Get token from header
const token = getHeader(event, 'Authorization')?.replace('Bearer ', '')
if (!token) {
throw createError({
statusCode: 401,
message: 'No token provided',
})
}
const directus = useTokenDirectus(token)
const user = await directus.request(readMe())
return { user }
})API Key Authentication
// server/api/webhook.ts
export default defineEventHandler(async (event) => {
const apiKey = getHeader(event, 'X-API-Key')
// Validate API key and get associated token
const token = await validateApiKey(apiKey)
const directus = useTokenDirectus(token)
// Make authenticated request
const items = await directus.request(readItems('webhooks'))
return { items }
})Manual Token Extraction
getDirectusSessionToken(event)
Extract the session token manually:
// server/api/check-auth.ts
export default defineEventHandler((event) => {
const token = getDirectusSessionToken(event)
return {
authenticated: !!token,
token: token ? '***' : null, // Don't expose actual token
}
})Use case: Custom authentication logic
// server/middleware/auth.ts
export default defineEventHandler((event) => {
const publicPaths = ['/api/public']
if (publicPaths.some(path => event.path.startsWith(path))) {
return
}
const token = getDirectusSessionToken(event)
if (!token) {
throw createError({
statusCode: 401,
message: 'Authentication required',
})
}
})Advanced Examples
Protected API Route
// server/api/protected/data.ts
import { readItems } from '@directus/sdk'
export default defineEventHandler(async (event) => {
// Verify user is authenticated
const token = getDirectusSessionToken(event)
if (!token) {
throw createError({
statusCode: 401,
message: 'Unauthorized',
})
}
const directus = useServerDirectus(event)
// Get user data
const user = await directus.request(readMe())
// Check user role
if (user.role.name !== 'Admin') {
throw createError({
statusCode: 403,
message: 'Forbidden - Admin access required',
})
}
// Fetch sensitive data
const data = await directus.request(readItems('sensitive_data'))
return { data }
})Hybrid Authentication
Combine user and admin authentication:
// server/api/analytics.ts
import { readItems } from '@directus/sdk'
export default defineEventHandler(async (event) => {
// Try user authentication first
const userToken = getDirectusSessionToken(event)
let directus
let scope = 'public'
if (userToken) {
directus = useServerDirectus(event)
const user = await directus.request(readMe())
// Admins get full data
if (user.role.name === 'Admin') {
directus = useAdminDirectus()
scope = 'admin'
} else {
scope = 'user'
}
} else {
// Public users get limited data
directus = useAdminDirectus() // Still need read access
scope = 'public'
}
// Fetch data based on scope
const filter = scope === 'public'
? { status: { _eq: 'published' } }
: {}
const analytics = await directus.request(readItems('analytics', {
filter,
limit: scope === 'admin' ? -1 : 10,
}))
return { scope, analytics }
})Batch Operations
// server/api/batch/import.ts
import { createItems } from '@directus/sdk'
export default defineEventHandler(async (event) => {
const body = await readBody(event)
const directus = useAdminDirectus()
// Batch create items
const results = await directus.request(createItems('items', body.items))
return {
success: true,
count: results.length,
items: results,
}
})File Upload Handler
// server/api/upload.ts
import { uploadFiles } from '@directus/sdk'
import { readFiles } from 'h3'
export default defineEventHandler(async (event) => {
const directus = useServerDirectus(event)
// Read multipart form data
const files = await readFiles(event)
if (!files || files.length === 0) {
throw createError({
statusCode: 400,
message: 'No files provided',
})
}
const formData = new FormData()
files.forEach(file => {
formData.append('file', file)
})
// Upload to Directus
const uploaded = await directus.request(uploadFiles(formData))
return { uploaded }
})Scheduled Task
// server/tasks/sync.ts
import { readItems, updateItem } from '@directus/sdk'
export default defineTask({
meta: {
name: 'sync:data',
description: 'Sync data with external API',
},
async run() {
const directus = useAdminDirectus()
// Fetch items to sync
const items = await directus.request(readItems('sync_queue', {
filter: { status: { _eq: 'pending' } },
limit: 100,
}))
for (const item of items) {
try {
// Sync with external API
await syncToExternalAPI(item)
// Update status
await directus.request(updateItem('sync_queue', item.id, {
status: 'completed',
synced_at: new Date(),
}))
} catch (error) {
console.error(`Failed to sync item ${item.id}:`, error)
}
}
return { synced: items.length }
},
})Database Query Helper
// server/utils/db.ts
import type { Query } from '@directus/sdk'
export async function fetchWithAuth<T>(
event: H3Event,
collection: string,
query?: Query<DirectusSchema, any>
) {
const directus = useServerDirectus(event)
return directus.request(readItems(collection, query))
}
// Usage in route
// server/api/posts.ts
export default defineEventHandler(async (event) => {
const posts = await fetchWithAuth(event, 'posts', {
sort: ['-date_created'],
limit: 20,
})
return { posts }
})Role-Based Access Control
// server/utils/auth.ts
export async function requireRole(event: H3Event, requiredRole: string) {
const directus = useServerDirectus(event)
const user = await directus.request(readMe({
fields: ['id', 'email', 'role.*'],
}))
if (user.role.name !== requiredRole) {
throw createError({
statusCode: 403,
message: `Access denied - ${requiredRole} role required`,
})
}
return user
}
// Usage
// server/api/admin/settings.ts
export default defineEventHandler(async (event) => {
await requireRole(event, 'Admin')
const directus = useAdminDirectus()
const settings = await directus.request(readSingleton('settings'))
return { settings }
})Configuration
Admin Token Setup
Set your admin token in .env:
DIRECTUS_ADMIN_TOKEN=your_admin_token_hereGet your admin token from Directus:
- Go to Directus Admin → User Menu → Account
- Copy your token under "Admin Access Token"
Security Best Practices
Never expose admin token to client
typescript// ❌ DON'T export default defineEventHandler(() => { return { adminToken: process.env.DIRECTUS_ADMIN_TOKEN } }) // ✅ DO export default defineEventHandler(() => { const directus = useAdminDirectus() // Use admin token internally only })Always validate user input
typescriptexport default defineEventHandler(async (event) => { const body = await readBody(event) // Validate input if (!body.email || !isValidEmail(body.email)) { throw createError({ statusCode: 400, message: 'Invalid email' }) } const directus = useServerDirectus(event) // Proceed with validated data })Use appropriate authentication level
typescript// User operations - use user session const directus = useServerDirectus(event) // Admin operations - use admin token const directus = useAdminDirectus()
API Reference
useServerDirectus(event)
Create a Directus client authenticated with the user's session token.
Parameters:
event: H3Event- The Nuxt server event
Returns: DirectusClient - Authenticated Directus client
Example:
const directus = useServerDirectus(event)
const user = await directus.request(readMe())useAdminDirectus()
Create a Directus client authenticated with the admin token.
Returns: DirectusClient - Admin-authenticated Directus client
Throws: Error if DIRECTUS_ADMIN_TOKEN is not set
Example:
const directus = useAdminDirectus()
const users = await directus.request(readUsers())useTokenDirectus(token?)
Create a Directus client with a custom token.
Parameters:
token?: string- Optional authentication token
Returns: DirectusClient - Token-authenticated Directus client
Example:
const directus = useTokenDirectus('custom-token')
const items = await directus.request(readItems('items'))getDirectusSessionToken(event)
Extract the session token from cookies.
Parameters:
event: H3Event- The Nuxt server event
Returns: string | undefined - The session token if present
Example:
const token = getDirectusSessionToken(event)
if (token) {
console.log('User is authenticated')
}useDirectusUrl(path?)
Get the full Directus URL for a given path.
Parameters:
path?: string- Optional path to append
Returns: string - Full Directus URL
Example:
const assetsUrl = useDirectusUrl('assets')
// Returns: https://your-directus.com/assetsTroubleshooting
Token Not Found
If getDirectusSessionToken() returns undefined:
- Check that user is logged in on the frontend
- Verify cookies are being sent with requests
- Check cookie name is
directus_session_token - Ensure
credentials: 'include'is set in module config
Admin Token Errors
If you get "DIRECTUS_ADMIN_TOKEN is not set":
- Add
DIRECTUS_ADMIN_TOKENto your.envfile - Restart your development server
- Verify the token is valid in Directus
Permission Errors
If you get permission errors:
- Verify the user/token has appropriate permissions in Directus
- Check collection access settings in Directus
- Use
useAdminDirectus()for privileged operations