Middleware
Overview
ABP React implements a middleware system that handles critical aspects of the application's request pipeline, particularly focusing on tenant resolution and session management. The middleware runs on every request and ensures proper tenant context and session state.
Core Functionality
The middleware system provides the following key features:
-
Tenant Resolution
- Automatically detects and resolves tenant context from the host header
- Maintains tenant information in the session
- Redirects to tenant setup if tenant context is missing
-
Session Management
- Integrates with iron-session for secure session handling
- Manages authentication state
- Handles tenant-specific session data
Implementation
Tenant Resolution Middleware
export async function middleware(request: NextRequest): Promise<NextResponse | undefined> {
const session = await getIronSession<SessionData>(await cookies(), sessionOptions)
// Check if tenantId is present in the session
if (!session.tenantId && request.nextUrl.pathname !== '/auth/set-tenant') {
// Redirect to set-tenant page if tenantId is not present
let redirectUrl = new URL('/auth/set-tenant', request.nextUrl.origin)
// Validate the redirect URL
if (redirectUrl.origin === request.nextUrl.origin) {
return NextResponse.redirect(redirectUrl)
}
}
}
Session Data Structure
interface SessionData {
isLoggedIn: boolean
access_token?: string
code_verifier?: string
state?: string
userInfo?: {
sub: string
name: string
email: string
email_verified: boolean
}
tenantId?: string
}
Tenant Resolution Process
-
Initial Request
- Middleware checks for tenant ID in session
- If missing, redirects to
/auth/set-tenant
-
Tenant Setup
- Fetches tenant GUID based on host header
- Stores tenant ID in session
- Redirects back to original request
-
Subsequent Requests
- Includes tenant ID in API requests
- Maintains tenant context throughout the session
API Integration
The middleware ensures proper tenant context in API requests:
APIClient.interceptors.request.use(async (options) => {
const session = await getSession()
options.headers.set('Authorization', `Bearer ${session.access_token}`)
options.headers.set('__tenant', session.tenantId ?? '')
return options
})
Best Practices
-
Security
- Always validate redirect URLs
- Use secure session storage
- Implement proper error handling
-
Performance
- Minimize middleware operations
- Cache tenant information when possible
- Handle edge cases gracefully
-
Maintenance
- Keep middleware logic simple and focused
- Document tenant resolution process
- Monitor middleware performance
Configuration
The middleware can be configured through environment variables:
NEXT_PUBLIC_API_URL
: API endpoint for tenant resolutionSESSION_PASSWORD
: Secret key for session encryptionNEXT_PUBLIC_APP_URL
: Application base URL
Error Handling
The middleware implements robust error handling:
-
Tenant Resolution Failures
- Falls back to default tenant
- Logs resolution errors
- Maintains application stability
-
Session Errors
- Handles session corruption
- Provides graceful degradation
- Maintains user experience
Extending Middleware
To extend the middleware functionality:
- Create new middleware functions
- Register them in the middleware chain
- Implement proper error handling
- Test thoroughly with different scenarios