Server Types
Type-safe server-side authentication with Nuxt Aegis.
getAuthUser<T>()
Use generic type parameter for type-safe access to JWT claims:
typescript
import type { AppTokenClaims } from '~/types/token'
export default defineEventHandler((event) => {
const user = getAuthUser<AppTokenClaims>(event)
// Fully typed access
return {
userId: user.sub,
role: user.role, // Custom claim - typed!
permissions: user.permissions // string[] - typed!
}
})Protected Routes
typescript
// server/api/admin/users.get.ts
import type { AppTokenClaims } from '~/types/token'
export default defineEventHandler((event) => {
const user = getAuthUser<AppTokenClaims>(event)
// Type-safe role check
if (user.role !== 'admin') {
throw createError({
statusCode: 403,
message: 'Admin access required'
})
}
return { users: [] }
})Custom Claims in Handlers
typescript
// server/plugins/aegis.ts
import type { AppTokenClaims } from '~/types/token'
export default defineNitroPlugin(() => {
defineAegisHandler({
impersonation: {
async fetchTarget(targetId) {
const dbUser = await database.findById(targetId)
if (!dbUser) return null
// Return JWT claims (AppTokenClaims structure)
return {
sub: dbUser.id,
email: dbUser.email,
name: dbUser.name,
picture: dbUser.picture,
role: dbUser.role,
permissions: dbUser.permissions,
organizationId: dbUser.organizationId,
// Note: No hashedPassword or other sensitive fields
}
}
}
})
})requireAuth<T>()
Alternative that throws if not authenticated:
typescript
import type { AppTokenClaims } from '~/types/token'
export default defineEventHandler((event) => {
const authedEvent = requireAuth<AppTokenClaims>(event)
// TypeScript knows user is defined
return {
role: authedEvent.context.user.role
}
})Type-Safe Middleware
typescript
// server/middleware/admin.ts
import type { AppTokenClaims } from '~/types/token'
export default defineEventHandler((event) => {
const user = getAuthUser<AppTokenClaims>(event)
if (user.role !== 'admin') {
throw createError({
statusCode: 403,
message: 'Forbidden'
})
}
})Complete Example
typescript
// server/api/projects/[id].get.ts
import type { AppTokenClaims } from '~/types/token'
import type { DatabaseUser } from '~/types/database'
export default defineEventHandler(async (event) => {
// 1. Get JWT claims (type-safe)
const tokenUser = getAuthUser<AppTokenClaims>(event)
// 2. Fetch from database
const dbUser: DatabaseUser = await database.findById(tokenUser.sub)
// 3. Check permissions
if (!tokenUser.permissions.includes('projects:read')) {
throw createError({ statusCode: 403 })
}
// 4. Fetch project
const projectId = getRouterParam(event, 'id')
const project = await database.getProject(projectId)
// 5. Authorize access
if (project.organizationId !== tokenUser.organizationId) {
throw createError({ statusCode: 404 })
}
return project
})Best Practices
✓ Do
typescript
// Use AppTokenClaims for JWT claims
const user = getAuthUser<AppTokenClaims>(event)
// Fetch database record separately if needed
const dbUser = await database.findById(user.sub)✗ Don't
typescript
// DON'T use DatabaseUser as JWT type
const user = getAuthUser<DatabaseUser>(event) // ✗ Wrong!
// DatabaseUser has fields not in JWT
// This will cause type mismatchesNext Steps
- Token Types - Define custom payloads
- Database Types - Separate models
- API Reference - Complete docs