Decorators

Security Decorators

Define TypeScript authentication, authorization, permissions, policies, rate limits, CSRF protection, input sanitization, IP restrictions, and identity requirements with AxilJS.

6 min readDocumentationEdit this page

Security Decorators

AxilJS security decorators declare access-control and security requirements as semantic metadata.

Instead of implementing authorization logic directly inside application methods, you describe the security requirement and let the appropriate security consumer enforce it.

Security decorators cover:

  • Authentication
  • Roles and permissions
  • Authorization policies
  • Rate limiting
  • CSRF protection
  • Input sanitization
  • IP allowlists
  • Verified identities

@tAuth

tAuth declares that an operation requires an authenticated caller.

typescript
import { tAuth } from '@axiljs/decorator'
 
@tAuth()
async getProfile() {}

Authentication requirements can be configured for specific authentication schemes or stronger authentication requirements:

typescript
@tAuth({
  required: true,
  schemes: ['bearer', 'apiKey'],
  mfa: true
})
async transferFunds() {}

Options

OptionTypeDescription
requiredbooleanWhether authentication is required
schemesstring[]Accepted authentication schemes
mfabooleanRequire multi-factor authentication

By default, required is true.

@tRole

tRole restricts an operation to callers with the specified role.

typescript
@tRole('admin')
async deleteUser() {}

Multiple roles can be declared:

typescript
@tRole('admin', 'editor')
async publishPost() {}

Use roles for coarse-grained access control.

For resource-level or relationship-based authorization, use @tPolicy.

@tPermission

tPermission defines fine-grained permissions required to execute an operation.

typescript
@tPermission('users.write')
async createUser() {}

Multiple permissions can be required:

typescript
@tPermission(
  'orders.read',
  'orders.update'
)
async updateOrder() {}

Permissions are useful when role-based access control is too broad for the application's authorization model.

@tPolicy

tPolicy references a named authorization policy.

Use policies when authorization depends on application context rather than a simple role or permission.

typescript
@tPolicy('OrderOwnership')
async updateOrder(orderId: string) {}

Another example:

typescript
@tPolicy('TenantAdmin')
async manageSettings() {}

The policy consumer evaluates the named policy against the current execution context.

Typical policy inputs may include:

  • Current user
  • Resource being accessed
  • Tenant
  • User roles
  • User permissions
  • Resource ownership
  • Organization membership

The policy determines whether the operation is allowed.

@tRateLimit

tRateLimit constrains how frequently an operation can execute.

typescript
@tRateLimit({
  limit: 10,
  window: '1m'
})
async search() {}

The rate limit can be scoped to a specific identity or request attribute:

typescript
@tRateLimit({
  limit: 5,
  window: '15m',
  key: 'ip'
})
async login() {}

Options

OptionTypeDescription
limitnumberMaximum number of executions
windowstringTime window such as 10s, 1m, or 1h
keystringRate-limit grouping key such as ip, user, or tenant

Rate limiting can be particularly useful for:

  • Authentication endpoints
  • Public APIs
  • Search endpoints
  • Expensive operations
  • Tenant-specific API limits

@tCsrf

tCsrf declares that an operation requires a valid Cross-Site Request Forgery (CSRF) token.

typescript
@tCsrf()
async updateSettings() {}

Use this for state-changing operations where CSRF protection is required.

The security consumer is responsible for validating the token according to the application's configured CSRF mechanism.

@tSanitize

tSanitize declares input sanitization requirements.

typescript
@tSanitize({
  stripHtml: true,
  trim: true
})
async createComment(
  @tBody() dto: CommentDto
) {}

Options

OptionTypeDescription
stripHtmlbooleanRemove HTML markup
trimbooleanTrim leading and trailing whitespace
normalizeWhitespacebooleanCollapse repeated whitespace

Sanitization should complement validation rather than replace it.

For schema validation, use the validation decorators.

@tIpAllowList

tIpAllowList restricts access to configured IP addresses or CIDR ranges.

typescript
@tIpAllowList(
  '192.168.1.0/24',
  '10.0.0.1'
)
async internalEndpoint() {}

This is useful for endpoints intended for:

  • Internal services
  • Private infrastructure
  • Administrative operations
  • Trusted network environments

IP-based restrictions should generally be treated as an additional security boundary, not the sole authorization mechanism.

@tVerifiedEmail

tVerifiedEmail requires the authenticated user's email address to be verified.

typescript
@tVerifiedEmail()
async createOrder() {}

This is useful when an operation requires a verified account identity.

Composing Security Requirements

Security decorators are designed to be composed.

For example:

typescript
@tHttp({
  method: 'DELETE',
  path: '/users/:id'
})
@tAuth({ required: true })
@tRole('admin')
@tRateLimit({
  limit: 5,
  window: '1h'
})
@tIpAllowList('10.0.0.0/8')
@tAudit({
  action: 'user.deleted',
  sensitivity: 'high'
})
async deleteUser(
  @tParam('id') id: string
) {
  await this.userService.delete(id)
}

Each declaration represents a separate security or operational requirement:

DecoratorResponsibility
tAuthAuthentication
tRoleRole-based authorization
tRateLimitRequest frequency control
tIpAllowListNetwork restriction
tAuditSecurity and compliance auditing

The decorators remain independent. The security runtime can evaluate the relevant metadata without requiring the decorators themselves to know how authentication, authorization, or rate limiting is implemented.

Security Metadata

Security decorators write their declarations to the AxilJS metadata registry.

A security consumer can then inspect the metadata and enforce the required constraints:

text
Application Method
       │
       ├── @tAuth
       ├── @tRole
       ├── @tPermission
       ├── @tPolicy
       └── @tRateLimit
              │
              ▼
       Metadata Registry
              │
              ▼
       Security Consumer
              │
              ├── Authentication
              ├── Authorization
              ├── Rate Limiting
              └── Security Policy

This separates the declaration of a security requirement from its implementation.

Complete Example

A protected API operation can combine HTTP, authentication, authorization, rate limiting, and auditing:

typescript
import {
  tHttp,
  tAuth,
  tPermission,
  tRateLimit,
  tAudit,
  tParam
} from '@axiljs/decorator'
 
@tHttp({
  method: 'DELETE',
  path: '/orders/:id'
})
@tAuth()
@tPermission('orders.delete')
@tRateLimit({
  limit: 10,
  window: '1m',
  key: 'user'
})
@tAudit({
  action: 'order.deleted'
})
async deleteOrder(
  @tParam('id') orderId: string
) {
  return this.orderService.delete(orderId)
}

The business method remains focused on the operation itself while its security requirements remain explicit and machine-readable.

Security Decorator Reference

DecoratorPurpose
tAuthRequire authentication
tRoleRequire one or more roles
tPermissionRequire specific permissions
tPolicyApply a named authorization policy
tRateLimitLimit execution frequency
tCsrfRequire CSRF protection
tSanitizeDeclare input sanitization
tIpAllowListRestrict access by IP or CIDR
tVerifiedEmailRequire a verified email identity

Security and Other Decorators

Security decorators can be combined with decorators from other AxilJS domains.

For example:

text
HTTP
  +
Authentication
  +
Authorization
  +
Rate Limiting
  +
Transaction
  +
Audit
  +
Observability

This allows the complete operational contract of an endpoint to remain visible in its declarations while implementation details remain inside independent runtime consumers.

Help improve the documentation

AxilJS is open source and documentation improvements are welcome.

AxilJS DocumentationMIT License · Built by SyntaxilitY