| name | algolia-security-basics |
| description | Apply Algolia security best practices: API key scoping, secured API keys,
frontend vs backend key separation, and key rotation.
Trigger: "algolia security", "algolia API key security", "secure algolia",
"algolia secrets", "algolia key rotation", "algolia secured key".
|
| allowed-tools | Read, Write, Edit, Grep |
| version | 1.6.0 |
| license | MIT |
| author | Jeremy Longshore <jeremy@intentsolutions.io> |
| tags | ["saas","search","algolia"] |
| compatibility | Designed for Claude Code |
Algolia Security Basics
Overview
Algolia's security model is built around scoped API keys. Every Algolia app has three default keys (Admin, Search-Only, Monitoring). For production, create custom keys with minimal permissions and use Secured API Keys for per-user/per-tenant restrictions.
Key Types and Where to Use Them
| Key Type | ACL | Expose to Frontend? | Use Case |
|---|
| Admin | All operations | NEVER | Backend indexing, settings, key management |
| Search-Only | search only | Yes (safe) | Frontend search widgets |
| Monitoring | Read monitoring data | No | Health checks, dashboards |
| Custom | You define ACL | Depends on ACL | Scoped backend services |
| Secured | Derived from parent key | Yes | Per-user filtered search |
Instructions
Step 1: Environment Variable Setup
ALGOLIA_APP_ID=YourApplicationID
ALGOLIA_ADMIN_KEY=admin_api_key_here
ALGOLIA_SEARCH_KEY=search_only_key_here
.env
.env.local
.env.*.local
Step 2: Create Scoped API Keys
import { algoliasearch } from 'algoliasearch';
const client = algoliasearch(process.env.ALGOLIA_APP_ID!, process.env.ALGOLIA_ADMIN_KEY!);
const { key: indexingKey } = await client.addApiKey({
apiKey: {
acl: ['addObject', 'deleteObject', 'editSettings'],
description: 'Product sync service — write only',
indexes: ['products', 'products_staging'],
maxQueriesPerIPPerHour: 5000,
referers: [],
},
});
const { key: frontendKey } = await client.addApiKey({
apiKey: {
acl: ['search'],
description: 'Frontend search — domain-restricted',
indexes: ['products'],
referers: ['https://mystore.com/*', 'https://*.mystore.com/*'],
maxQueriesPerIPPerHour: 1000,
maxHitsPerQuery: ,
},
});
Step 3: Generate Secured API Keys (Per-User Filtering)
function generateUserSearchKey(userId: string, tenantId: string): string {
const client = algoliasearch(process.env.ALGOLIA_APP_ID!, process.env.ALGOLIA_ADMIN_KEY!);
return client.generateSecuredApiKey({
parentApiKey: process.env.ALGOLIA_SEARCH_KEY!,
restrictions: {
filters: `tenant_id:${tenantId}`,
validUntil: Math.floor(Date.now() / 1000) + 3600,
restrictIndices: ['products'],
restrictSources: '',
},
});
}
Step 4: Key Rotation Procedure
async function rotateApiKey(oldKeyDescription: string) {
const client = algoliasearch(process.env.ALGOLIA_APP_ID!, process.env.ALGOLIA_ADMIN_KEY!);
const { keys } = await client.listApiKeys();
const oldKey = keys.find(k => k.description === oldKeyDescription);
if (!oldKey) throw new Error(`Key not found: ${oldKeyDescription}`);
const { key: newKey } = await client.addApiKey({
apiKey: {
acl: oldKey.acl,
description: `${oldKeyDescription} (rotated ${new Date().toISOString().split('T')[0]})`,
indexes: oldKey.indexes || [],
maxQueriesPerIPPerHour: oldKey.maxQueriesPerIPPerHour || 0,
referers: oldKey.referers || [],
},
});
.();
.();
.();
newKey;
}
Security Checklist
Error Handling
| Security Issue | Detection | Mitigation |
|---|
| Admin key exposed in frontend | Code review, git scanning | Rotate immediately, restrict referers |
| Key in git history | git log -S 'ALGOLIA' | Rotate key, use git-secrets or gitleaks |
| Excessive ACL on key | Audit key permissions | Create scoped replacement key |
| Expired secured key | validUntil in the past | Generate fresh secured key |
Resources
Next Steps
For production deployment, see algolia-prod-checklist.