Skip to content

Auth Guard

The AuthGuard factory from @stratal/framework/guards creates guards that check authentication and, optionally, permission. It works with AuthContext for authentication and with AccessService for permission checks — both supplied automatically when their respective modules are configured.

Apply AuthGuard() without options to require authentication on a controller or route:

import { Controller, IController, Route, RouterContext } from 'stratal/router'
import { UseGuards } from 'stratal/router'
import { AuthGuard } from '@stratal/framework/guards'
@Controller('/api/profile')
@UseGuards(AuthGuard())
export class ProfileController implements IController {
@Route({ response: profileSchema })
index(ctx: RouterContext) {
// only authenticated users reach this handler
return ctx.json({ profile: '...' })
}
}

When no permissions are provided, AuthGuard checks AuthContext.isAuthenticated(). If the user is not authenticated, it throws a UserNotAuthenticatedError (HTTP 401).

Pass a permissions option to enforce access-control checks alongside authentication. Each entry is a 'resource:action' string:

@Controller('/api/admin/users')
@UseGuards(AuthGuard({ permissions: 'users:ban' }))
export class AdminUsersController implements IController {
@Route({ response: usersSchema })
index(ctx: RouterContext) {
// only authenticated users with 'users:ban' permission reach this handler
return ctx.json({ users: [] })
}
}

permissions accepts a single string or an array. When you pass an array, every listed permission must be granted:

@UseGuards(AuthGuard({ permissions: ['posts:delete', 'admin:access'] }))

A bare resource without an action (e.g. 'admin') is treated as a wildcard — the user passes if they have any action defined for that resource.

AuthGuard first verifies authentication (401 if not authenticated), then checks permissions through AccessService (403 if unauthorized). The permission check reads roles from AuthContext, so it doesn’t trigger an extra database query.

Apply AuthGuard at the route level instead of the controller level when only some routes need authorization:

@Controller('/api/students')
export class StudentsController implements IController {
@Route({ response: studentsSchema })
@UseGuards(AuthGuard({ permissions: 'students:read' }))
index(ctx: RouterContext) {
// requires students:read permission
}
@Route({ body: createStudentSchema, response: studentSchema })
@UseGuards(AuthGuard({ permissions: 'students:write' }))
create(ctx: RouterContext) {
// requires students:write permission
}
}
ErrorHTTP StatusWhen
UserNotAuthenticatedError401User is not authenticated
InsufficientPermissionsError403User is authenticated but lacks the required permissions

Both errors are handled by Stratal’s global error handler and produce JSON error responses with localised messages.

  • AuthModule must be configured for any use of AuthGuard.
  • For permission checks, pass an accessControl option to AuthModule.forRootAsync() so that AccessService is registered. See Access Control.
  • Auth for configuring authentication.
  • Access Control for declaring resources and roles.
  • Guards for the core guard system and writing custom guards.