Your Starter Kit application includes multiple security layers to protect user data and prevent unauthorized access.
Authentication security
JWT tokens
The Cloud API issues JSON Web Tokens for authentication:
Access tokens:
- Expire after 30 minutes
- Stored in httpOnly cookies (
devkit4ai-token)
- Not accessible to JavaScript
- Automatically included in API requests
Refresh tokens:
- Expire after 7 days
- Stored in httpOnly cookies (
devkit4ai-refresh-token)
- Used to obtain new access tokens
- Revoked on logout
Cookie configuration
function storeTokensInCookies(tokens: TokenResponse) {
cookies().set('devkit4ai-token', tokens.access_token, {
httpOnly: true, // Not accessible to JavaScript
secure: isProduction, // HTTPS only in production
sameSite: 'lax', // CSRF protection
maxAge: 60 * 30, // 30 minutes
path: '/' // Available site-wide
})
}
Never store authentication tokens in localStorage or sessionStorage. Use httpOnly cookies to prevent XSS attacks.
API key security
Storage and handling
Environment variables:
- Store keys in
.env.local for development
- Use hosting provider secrets for production
- Never commit keys to version control
Server-side only:
// ✅ Good - Server Component
export default async function Page() {
const developerKey = process.env.DEVKIT4AI_DEVELOPER_KEY
// Key stays on server
}
// ❌ Bad - Client Component
'use client'
export function MyComponent() {
const key = process.env.DEVKIT4AI_DEVELOPER_KEY // Undefined!
}
Key rotation
Generate new keys
In Cloud Admin, create new developer and project API keys.
Update environment variables
Set new keys in your hosting provider and local .env.local.
Deploy and verify
Deploy with new keys and confirm application works.
Revoke old keys
In Cloud Admin, revoke the old keys after confirming new ones work.
Rotate API keys every 90 days or immediately if compromised.
Password security
The Cloud API enforces strong password requirements:
Minimum requirements:
- At least 8 characters
- One uppercase letter
- One lowercase letter
- One digit
Client-side validation:
components/register-form.tsx
function validatePassword(password: string): string | null {
if (password.length < 8) {
return 'Password must be at least 8 characters'
}
if (!/[A-Z]/.test(password)) {
return 'Password must contain an uppercase letter'
}
if (!/[a-z]/.test(password)) {
return 'Password must contain a lowercase letter'
}
if (!/[0-9]/.test(password)) {
return 'Password must contain a digit'
}
return null
}
Server-side hashing:
Passwords are hashed with bcrypt before storage (handled by Cloud API).
HTTPS enforcement
Production configuration
All production deployments must use HTTPS:
Vercel, Netlify: Automatic HTTPS with free SSL certificates
Custom domains:
- Configure SSL certificate
- Redirect HTTP to HTTPS
- Enable HSTS headers
Next.js middleware:
import { NextResponse } from 'next/server'
export function middleware(request: Request) {
// Redirect HTTP to HTTPS in production
if (process.env.NODE_ENV === 'production' &&
request.url.startsWith('http://')) {
return NextResponse.redirect(
request.url.replace('http://', 'https://'),
301
)
}
}
CORS configuration
The Cloud API restricts cross-origin requests:
Allowed origins:
- Your registered domain(s)
localhost:* for development
Configure in Cloud Admin:
- Navigate to Project Settings
- Add allowed origins
- Wildcards supported for subdomains
Always validate user input:
Email addresses:
function isValidEmail(email: string): boolean {
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)
}
Sanitize display values:
import DOMPurify from 'isomorphic-dompurify'
function SafeContent({ html }: { html: string }) {
const clean = DOMPurify.sanitize(html)
return <div dangerouslySetInnerHTML={{ __html: clean }} />
}
Return URL validation:
export function sanitizeReturnUrl(url: string | null): string | null {
if (!url) return null
// Only allow relative paths
if (!url.startsWith('/')) return null
// Prevent protocol-relative URLs
if (url.startsWith('//')) return null
// Prevent control characters
if (/[\x00-\x1f]/.test(url)) return null
return url
}
Rate limiting
The Cloud API implements rate limits:
Per project:
- Authentication: 10 requests/minute
- Data endpoints: 100 requests/minute
- AI generation: 10 requests/minute
Handle rate limits:
async function fetchWithRetry(url: string, options: RequestInit) {
const response = await fetch(url, options)
if (response.status === 429) {
// Rate limited - implement backoff
const retryAfter = response.headers.get('Retry-After') || '60'
throw new Error(`Rate limited. Retry after ${retryAfter} seconds.`)
}
return response
}
Configure security headers in next.config.ts:
const nextConfig = {
async headers() {
return [
{
source: '/:path*',
headers: [
{
key: 'X-Frame-Options',
value: 'DENY'
},
{
key: 'X-Content-Type-Options',
value: 'nosniff'
},
{
key: 'Referrer-Policy',
value: 'strict-origin-when-cross-origin'
},
{
key: 'Permissions-Policy',
value: 'camera=(), microphone=(), geolocation=()'
}
]
}
]
}
}
Dependency security
Keep dependencies updated:
# Check for vulnerabilities
npm audit
# Fix automatically where possible
npm audit fix
# Update dependencies
npm update
Enable Dependabot:
- Go to GitHub repository settings
- Enable Dependabot alerts
- Configure automatic PR creation
Monitoring and logging
Never log sensitive data:
// ❌ Bad
console.log('User password:', password)
console.log('API key:', apiKey)
// ✅ Good
console.log('User authenticated successfully')
console.log('API call completed')
Log security events:
- Failed login attempts
- API key usage
- Permission denials
- Rate limit hits
Security checklist
Next steps