Here are several approaches to restrict API access to our frontend:
import cors from '@fastify/cors';
fastify.register(cors, {
origin: ['https://our-frontend-domain.com'],
credentials: true,
methods: ['GET', 'POST', 'PUT', 'DELETE']
});
Pros:
- Simple implementation
- Browser-level protection
- Standard web security practice
- Maintains secure cookie handling
Cons:
- Only browser-enforced
- Can be bypassed by non-browser clients
- Requires proper frontend domain configuration
fastify.addHook('preHandler', async (request, reply) => {
const apiKey = request.headers['x-api-key'];
const origin = request.headers.origin;
if (!isValidApiKey(apiKey) || !isAllowedOrigin(origin)) {
reply.code(403).send({ error: 'Unauthorized' });
}
});
Pros:
- Stronger security than CORS alone
- Works with non-browser clients
- Can implement rate limiting
- Fine-grained access control
Cons:
- Additional implementation complexity
- Key management overhead
- Requires secure key storage
// CORS + API Key + JWT
fastify.register(cors, {
origin: process.env.FRONTEND_URL,
credentials: true
});
fastify.addHook('preHandler', validateApiKey);
fastify.addHook('preHandler', validateOrigin);
Pros:
- Multiple security layers
- Comprehensive protection
- Flexible configuration
- Best security practices
Cons:
- More complex setup
- Additional request overhead
- Requires careful configuration
The combined approach provides the best security while maintaining usability for legitimate frontend requests.