### Complete AdonisJS Shield Configuration
Source: https://context7.com/adonisjs/shield/llms.txt
A production-ready Shield configuration example demonstrating all guards enabled and properly configured. This configuration can be adapted for different environments using environment variables.
```typescript
// config/shield.ts
import { defineConfig } from '@adonisjs/shield'
const shieldConfig = defineConfig({
csp: {
enabled: true,
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", '@nonce', 'https://cdn.jsdelivr.net'],
styleSrc: ["'self'", "'unsafe-inline'", 'https://fonts.googleapis.com'],
fontSrc: ["'self'", 'https://fonts.gstatic.com'],
imgSrc: ["'self'", 'data:', 'https:'],
connectSrc: ["'self'", process.env.API_URL!],
frameSrc: ["'none'"],
objectSrc: ["'none'"],
baseUri: ["'self'"],
formAction: ["'self'"],
upgradeInsecureRequests: [],
},
reportOnly: false,
},
csrf: {
enabled: true,
exceptRoutes: [
'/api/webhooks/*',
'/api/stripe/webhook',
'/api/health',
],
enableXsrfCookie: true,
methods: ['POST', 'PUT', 'PATCH', 'DELETE'],
cookieOptions: {
sameSite: 'lax',
secure: process.env.NODE_ENV === 'production',
},
},
xFrame: {
enabled: true,
action: 'DENY',
},
hsts: {
enabled: process.env.NODE_ENV === 'production',
maxAge: '1 year',
includeSubDomains: true,
preload: false,
},
contentTypeSniffing: {
enabled: true,
},
})
export default shieldConfig
```
--------------------------------
### Create HSTS Guard
Source: https://context7.com/adonisjs/shield/llms.txt
Use `hstsFactory` to create an HSTS guard. Configure the `maxAge`, `includeSubDomains`, and `preload` options to enforce HTTPS connections. Examples for production and development configurations are provided.
```typescript
import { hstsFactory } from '@adonisjs/shield/guards'
const hstsGuard = hstsFactory({
enabled: true,
// Duration to remember HTTPS preference
// Accepts string expressions: '1 year', '180 days', '6 months'
// Or number in seconds: 31536000
maxAge: '1 year',
// Apply HSTS to all subdomains
includeSubDomains: true,
// Enable HSTS preloading (browser built-in list)
// Only enable after confirming HTTPS works for all subdomains
preload: true,
})
// Resulting header:
// Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
// Production configuration example:
const productionHsts = hstsFactory({
enabled: process.env.NODE_ENV === 'production',
maxAge: '2 years',
includeSubDomains: true,
preload: true,
})
// Development configuration (shorter duration for testing):
const developmentHsts = hstsFactory({
enabled: true,
maxAge: '1 hour',
includeSubDomains: false,
preload: false,
})
```
--------------------------------
### Create Content Security Policy Guard
Source: https://context7.com/adonisjs/shield/llms.txt
Use `cspFactory` to create a CSP guard. Register custom keywords and define directives for various resource types like scripts, styles, and images. The `@nonce` keyword can be used to allow specific inline scripts.
```typescript
import { cspFactory } from '@adonisjs/shield/guards'
import { cspKeywords } from '@adonisjs/shield'
// Register custom CSP keywords
cspKeywords.register('@googleAnalytics', (req, res) => {
return 'https://www.google-analytics.com'
})
const cspGuard = cspFactory({
enabled: true,
directives: {
// Default policy for all resource types
defaultSrc: ["'self'"],
// Script sources - @nonce allows inline scripts with matching nonce
scriptSrc: ["'self'", '@nonce', 'https://cdn.jsdelivr.net'],
// Style sources
styleSrc: ["'self'", "'unsafe-inline'", 'https://fonts.googleapis.com'],
// Font sources
fontSrc: ["'self'", 'https://fonts.gstatic.com'],
// Image sources
imgSrc: ["'self'", 'data:', 'https:', 'blob:'],
// API/fetch/XHR connections
connectSrc: ["'self'", 'https://api.example.com', 'wss://socket.example.com'],
// Frame sources (iframes)
frameSrc: ["'self'", 'https://www.youtube.com'],
// Object/embed/applet sources
objectSrc: ["'none'"],
// Form submission targets
formAction: ["'self'"],
// Base URI restriction
baseUri: ["'self'"],
// Upgrade insecure requests
upgradeInsecureRequests: [],
},
// Report-only mode (doesn't block, just reports violations)
reportOnly: false,
})
// In Edge.js templates, use the nonce for inline scripts:
//
// In a controller, access the nonce:
// export default class PageController {
// async show({ response, view }: HttpContext) {
// const nonce = response.nonce
// return view.render('page', { inlineScriptNonce: nonce })
// }
// }
```
--------------------------------
### Create Frame Guard Factory
Source: https://context7.com/adonisjs/shield/llms.txt
Use frameGuardFactory to create guards that set the X-Frame-Options header. Configure actions like DENY, SAMEORIGIN, or ALLOW-FROM with a specific domain. Conditional configuration based on environment variables is also supported.
```typescript
import { frameGuardFactory } from '@adonisjs/shield/guards'
// Deny all iframe embedding
const denyFrameGuard = frameGuardFactory({
enabled: true,
action: 'DENY',
})
// Header: X-Frame-Options: DENY
// Allow same-origin iframe embedding only
const sameOriginGuard = frameGuardFactory({
enabled: true,
action: 'SAMEORIGIN',
})
// Header: X-Frame-Options: SAMEORIGIN
// Allow embedding from a specific domain
const allowFromGuard = frameGuardFactory({
enabled: true,
action: 'ALLOW-FROM',
domain: 'https://trusted-partner.com',
})
// Header: X-Frame-Options: ALLOW-FROM https://trusted-partner.com
// Conditional configuration based on environment
const frameGuard = frameGuardFactory({
enabled: true,
action: process.env.ALLOW_IFRAME_EMBED === 'true' ? 'SAMEORIGIN' : 'DENY',
})
```
--------------------------------
### Configure @adonisjs/shield with defineConfig
Source: https://context7.com/adonisjs/shield/llms.txt
Use `defineConfig` to create a Shield configuration object, merging partial options with defaults. All guards are disabled by default, requiring explicit enabling.
```typescript
import { defineConfig } from '@adonisjs/shield'
const shieldConfig = defineConfig({
// Enable CSRF protection for form submissions
csrf: {
enabled: true,
exceptRoutes: ['/api/webhooks', '/api/stripe/webhook'],
enableXsrfCookie: true,
methods: ['POST', 'PUT', 'PATCH', 'DELETE'],
cookieOptions: {
httpOnly: false,
sameSite: 'strict',
},
},
// Configure Content Security Policy
csp: {
enabled: true,
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", '@nonce', 'https://cdn.example.com'],
styleSrc: ["'self'", "'unsafe-inline'"],
imgSrc: ["'self'", 'data:', 'https:'],
connectSrc: ["'self'", 'https://api.example.com'],
},
reportOnly: false,
},
// Enforce HTTPS connections
hsts: {
enabled: true,
maxAge: '1 year',
includeSubDomains: true,
preload: true,
},
// Prevent clickjacking attacks
xFrame: {
enabled: true,
action: 'SAMEORIGIN',
},
// Prevent MIME type sniffing
contentTypeSniffing: {
enabled: true,
},
})
export default shieldConfig
```
--------------------------------
### Configure Shield API Client Plugin
Source: https://context7.com/adonisjs/shield/llms.txt
Integrate the shieldApiClient plugin with Japa for testing CSRF protection. Ensure both apiClient and shieldApiClient are included in the configure function.
```typescript
// tests/bootstrap.ts
import { shieldApiClient } from '@adonisjs/shield/plugins/api_client'
import { apiClient } from '@japa/api-client'
import { configure } from '@japa/runner'
configure({
plugins: [
apiClient(),
shieldApiClient(),
],
})
```
--------------------------------
### Register and Use ShieldMiddleware in AdonisJS
Source: https://context7.com/adonisjs/shield/llms.txt
The `ShieldMiddleware` orchestrates security guards. It's typically registered automatically, but manual registration in `start/kernel.ts` is shown. The middleware adds CSRF tokens and CSP nonces to the request and response context.
```typescript
import ShieldMiddleware from '@adonisjs/shield/shield_middleware'
import router from '@adonisjs/core/services/router'
// The middleware is automatically registered when configuring the package.
// Manual registration in start/kernel.ts:
router.use([
() => import('@adonisjs/shield/shield_middleware')
])
// The middleware adds these properties to the request/response:
// ctx.request.csrfToken - The CSRF token for the current session
// ctx.response.nonce - A cryptographic nonce for CSP inline scripts
// In a controller:
export default class FormController {
async show({ request, view }: HttpContext) {
// Access the CSRF token programmatically
const token = request.csrfToken
// Render view with CSRF protection
return view.render('form', { csrfToken: token })
}
async submit({ request, response }: HttpContext) {
// CSRF validation happens automatically for POST/PUT/PATCH/DELETE
const data = request.only(['email', 'password'])
// Process form submission...
return response.redirect('/dashboard')
}
}
```
--------------------------------
### Register Custom CSP Keywords
Source: https://context7.com/adonisjs/shield/llms.txt
Register custom keywords for dynamic CSP directive values. These are typically registered in a preload file before shield configuration. The built-in '@nonce' keyword is automatically registered.
```typescript
import { cspKeywords } from '@adonisjs/shield'
// Register custom keywords before shield configuration
// Typically in a preload file: start/shield.ts
// Built-in @nonce keyword (registered automatically)
// Resolves to 'nonce-'
// Register a custom keyword for trusted CDN
cspKeywords.register('@trustedCdn', (request, response) => {
return 'https://cdn.trusted.com'
})
// Dynamic keyword based on environment
cspKeywords.register('@apiEndpoint', (request, response) => {
return process.env.NODE_ENV === 'production'
? 'https://api.production.com'
: 'https://api.staging.com'
})
// Use custom keywords in CSP configuration
import { defineConfig } from '@adonisjs/shield'
export default defineConfig({
csp: {
enabled: true,
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", '@nonce', '@trustedCdn'],
connectSrc: ["'self'", '@apiEndpoint'],
},
},
})
```
--------------------------------
### Create CSRF Protection Guard
Source: https://context7.com/adonisjs/shield/llms.txt
Use `csrfFactory` to create a CSRF guard. Configure routes to exclude, enable XSRF cookies for JavaScript frameworks, and specify HTTP methods requiring validation. The guard integrates with Edge.js templates for token generation and rendering.
```typescript
import { csrfFactory } from '@adonisjs/shield/guards'
import type { HttpContext } from '@adonisjs/core/http'
// Configuration options
const csrfGuard = csrfFactory({
enabled: true,
// Routes to exclude from CSRF validation
exceptRoutes: ['/api/webhooks', '/api/external/*'],
// Or use a function for dynamic exclusion
// exceptRoutes: (ctx: HttpContext) => {
// return ctx.request.url().startsWith('/api/public')
// },
// Enable XSRF cookie for JavaScript frameworks (Angular, Axios)
enableXsrfCookie: true,
// HTTP methods that require CSRF validation
methods: ['POST', 'PUT', 'PATCH', 'DELETE'],
// Cookie options for XSRF-TOKEN cookie
cookieOptions: {
sameSite: 'strict',
secure: true,
},
}, encryption, edge)
// In Edge.js templates, these helpers are available:
// {{ csrfToken }} - The raw CSRF token value
// {{{ csrfField() }}} - Renders:
// {{{ csrfMeta() }}} - Renders:
// Example form template (resources/views/form.edge):
//
// For AJAX requests, include the token in headers:
// JavaScript example:
// fetch('/api/data', {
// method: 'POST',
// headers: {
// 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content,
// 'Content-Type': 'application/json',
// },
// body: JSON.stringify(data),
// })
```
--------------------------------
### Test API Endpoints with CSRF Protection
Source: https://context7.com/adonisjs/shield/llms.txt
Use the withCsrfToken() method on the API client to automatically include a valid CSRF token in requests. Test various HTTP methods (POST, PUT, DELETE) and verify responses, including failure cases for missing tokens.
```typescript
// tests/functional/users.spec.ts
import { test } from '@japa/runner'
test.group('User Management', () => {
test('create new user with CSRF protection', async ({ client }) => {
// The withCsrfToken() method automatically generates
// a valid CSRF token and includes it in the request
const response = await client
.post('/users')
.withCsrfToken()
.json({
email: 'user@example.com',
password: 'securePassword123',
name: 'John Doe',
})
response.assertStatus(201)
response.assertBodyContains({ email: 'user@example.com' })
})
test('update user profile', async ({ client }) => {
const response = await client
.put('/users/1')
.withCsrfToken()
.withSession({ userId: 1 }) // Combine with session if needed
.json({ name: 'Jane Doe' })
response.assertStatus(200)
})
test('delete user account', async ({ client }) => {
const response = await client
.delete('/users/1')
.withCsrfToken()
.withSession({ userId: 1 })
response.assertStatus(204)
})
test('request without CSRF token fails', async ({ client }) => {
const response = await client
.post('/users')
.json({ email: 'user@example.com' })
response.assertStatus(403)
})
})
```
--------------------------------
### Handle E_BAD_CSRF_TOKEN Exception
Source: https://context7.com/adonisjs/shield/llms.txt
Customize the exception handler to manage E_BAD_CSRF_TOKEN errors. For API requests, return a JSON response with an appropriate status code and message. For HTML requests, the default behavior of redirecting back with a flash error is preserved.
```typescript
import { errors } from '@adonisjs/shield'
// The exception is thrown automatically when CSRF validation fails
// You can catch and customize it in exception handler
// app/exceptions/handler.ts
import { ExceptionHandler, HttpContext } from '@adonisjs/core/http'
export default class Handler extends ExceptionHandler {
async handle(error: unknown, ctx: HttpContext) {
// Custom handling for CSRF errors
if (error instanceof errors.E_BAD_CSRF_TOKEN) {
// For API requests, return JSON
if (ctx.request.accepts(['html', 'json']) === 'json') {
return ctx.response.status(403).json({
error: 'CSRF_TOKEN_INVALID',
message: 'Your session has expired. Please refresh and try again.',
})
}
// For HTML requests, the default behavior redirects back with flash
// error.handle() is called automatically
}
return super.handle(error, ctx)
}
}
// The error includes i18n support. Add translation:
// resources/lang/en/errors.json:
// {
// "E_BAD_CSRF_TOKEN": "Your session has expired. Please refresh the page and try again."
// }
```
--------------------------------
### Create No Sniff Factory
Source: https://context7.com/adonisjs/shield/llms.txt
The noSniffFactory creates a guard that sets the X-Content-Type-Options header to 'nosniff'. This prevents browsers from MIME-sniffing responses, which can mitigate certain security risks.
```typescript
import { noSniffFactory } from '@adonisjs/shield/guards'
const noSniffGuard = noSniffFactory({
enabled: true,
})
// Header: X-Content-Type-Options: nosniff
// This prevents attacks where a browser might interpret a file
// differently than the server intended, such as treating a
// text file as executable JavaScript.
```
=== COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.