Appearance
URL Validation Middleware ​
File Information ​
- Path:
app/middleware/check-url.ts - Purpose: URL validation, brand verification, and route protection
- Type: Per-Route Middleware (but often used globally via page meta)
Overview ​
The check-url.ts middleware provides comprehensive URL validation and brand verification. It handles brand name validation, domain verification, brand switching logic, anonymous user handling, and public portal detection. This is one of the most complex middleware files, handling multiple edge cases and scenarios.
Features ​
- Brand Validation: Validates brand name existence and format
- Domain Verification: Verifies domain-based routing
- Reserved Slug Detection: Prevents access to reserved slugs (e.g.,
/api) - Brand Switching: Handles brand switching for authenticated users
- Anonymous User Handling: Manages anonymous user sessions
- Public Portal Detection: Detects and handles public portals
- Session Management: Cookie hydration and session validation
- Error Handling: Comprehensive error handling with appropriate status codes
Key Functionality ​
1. Asset Request Filtering ​
Ignores asset requests to avoid unnecessary processing:
typescript
if (to.path.startsWith('/_nuxt/') || to.path.includes('.')) {
return // Skip middleware for assets
}2. Active Session Detection ​
Detects active session from multiple sources:
typescript
// Server-side: Check cookies
if (import.meta.server) {
const tokenCookie = useCookie<string | null>('auth_token')
const hasAuthTokenInHeader = requestCookieHeader.includes('auth_token=')
hasActiveSession = Boolean(tokenCookie.value) || hasAuthTokenInHeader
}
// Client-side: Check store and API
if (import.meta.client) {
const sessionCheck = await $fetch('/api/auth/session')
if (sessionCheck?.authenticated) {
hasActiveSession = true
}
}3. Authenticated User Redirect on Auth Pages ​
Prevents authenticated users from accessing auth pages:
typescript
if (hasActiveSession && isAuthPage) {
const resolvedBrand = resolveBrandFromUser(authStore.user)
if (resolvedBrand) {
return navigateTo(`/${resolvedBrand}`, { replace: true, external: true })
}
}4. Reserved Brand Slug Handling ​
Prevents access to reserved slugs like /api:
typescript
if (isReservedBrandSlug(brandNameFromRoute)) {
if (hasActiveSession) {
// Redirect authenticated users to their brand
const resolvedBrand = resolveBrandFromUser(authStore.user)
return navigateTo(`/${resolvedBrand}`, { replace: true, external: true })
}
// Show error for unauthenticated users
throw createError({
statusCode: 500,
statusMessage: `Brand with "${brandNameFromRoute}" doesn't exists.`
})
}5. Brand Switching Logic ​
Handles brand switching for authenticated users:
typescript
if (authStore.isAuthenticated) {
const hasAccessToNewWorkspace = authStore.user?.accessibleInstances?.some(
(instance: any) => instance.url === brandNameFromRoute
)
if (!hasAccessToNewWorkspace && !isAnonymousUser) {
// Try public portal login
const response = await $fetch('/api/check-public-portal', {
method: 'POST',
body: { url: brandNameFromRoute }
})
if (response?.data) {
await authStore.login(email, password, workspace_id)
}
}
}6. Brand Validation ​
Validates brand existence via API:
typescript
// Domain-based validation
if (isSubdomain) {
const response = await $fetch('/api/verify-domain', {
method: 'POST',
body: { url: domainUrl }
})
if (response?.code === 200) {
// Brand is valid
appDataStore.brandDetails(response.data)
}
}
// URL slug-based validation
else if (brandNameFromRoute) {
const response = await $fetch('/api/verify-domain', {
method: 'POST',
body: { url: brandNameFromRoute }
})
}Helper Functions ​
isReservedBrandSlug(slug) ​
Checks if a slug is reserved (e.g., 'api'):
typescript
function isReservedBrandSlug(slug: string): boolean {
return slug.trim().toLowerCase() === 'api'
}extractBrandFromPath(path) ​
Extracts brand name from URL path:
typescript
function extractBrandFromPath(path?: string): string | null {
if (!path) return null
const m = path.match(/^\/([^/]+)/)
return m?.[1] || null
}resolveBrandFromUser(user) ​
Resolves brand name from user data:
typescript
function resolveBrandFromUser(user: any): string | null {
if (!user) return null
return user?.url || user?.brand_name || user?.accessibleInstances?.[0]?.url || null
}parseJsonCookieFromHeader(cookieHeader, cookieName) ​
Parses JSON cookie from raw cookie header:
typescript
function parseJsonCookieFromHeader(cookieHeader: string, cookieName: string): any | null {
// Parses "auth_user=%7B...%7D" format
// Returns parsed JSON object
}Usage ​
Automatic Usage ​
This middleware is often applied globally via page metadata or runs as part of the authentication flow.
Explicit Usage ​
vue
<script setup lang="ts">
definePageMeta({
middleware: 'check-url'
})
</script>Error Handling ​
The middleware throws appropriate errors:
typescript
// Invalid brand
throw createError({
statusCode: 500,
statusMessage: `Brand with "${brandNameFromRoute}" doesn't exists.`
})
// Reserved slug
throw createError({
statusCode: 500,
statusMessage: `Brand with "${brandNameFromRoute}" doesn't exists.`
})Anonymous User Handling ​
The middleware handles anonymous users specially:
typescript
// Anonymous user session tracking
if (authStore.user?.email === '[email protected]') {
const storedBrand = sessionStorage.getItem('anonymousCurrentBrand')
if (storedBrand) {
brandNameFromUser = storedBrand
}
}Public Portal Support ​
The middleware supports public portal detection and auto-login:
typescript
// Check if brand is a public portal
const response = await $fetch('/api/check-public-portal', {
method: 'POST',
body: { url: brandNameFromRoute }
})
if (response?.data) {
// Auto-login public portal
await authStore.login(email, password, workspace_id)
}Dependencies ​
useAuthStore()- Authentication storeuseAppDataStore()- App data storenavigateTo()- Nuxt navigation helperuseCookie()- Cookie accessuseRequestHeaders()- Request headers access$fetch()- API client
Related Middleware ​
- Global Auth Middleware - Global authentication
- Public Portal Middleware - Public portal auto-login
Related Documentation ​
- Authentication System - Authentication feature
- Middleware Overview - All middleware
- Auth Store - Authentication store