Skillshub algolia-security-basics
install
source · Clone the upstream repo
git clone https://github.com/ComeOnOliver/skillshub
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/ComeOnOliver/skillshub "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/jeremylongshore/claude-code-plugins-plus-skills/algolia-security-basics" ~/.claude/skills/comeonoliver-skillshub-algolia-security-basics && rm -rf "$T"
manifest:
skills/jeremylongshore/claude-code-plugins-plus-skills/algolia-security-basics/SKILL.mdsource content
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 | 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
# .env (NEVER commit — add to .gitignore) ALGOLIA_APP_ID=YourApplicationID ALGOLIA_ADMIN_KEY=admin_api_key_here # Backend only ALGOLIA_SEARCH_KEY=search_only_key_here # OK for frontend # .gitignore — MUST include: .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!); // Create a write-only key for a specific microservice const { key: indexingKey } = await client.addApiKey({ apiKey: { acl: ['addObject', 'deleteObject', 'editSettings'], description: 'Product sync service — write only', indexes: ['products', 'products_staging'], // Restrict to specific indices maxQueriesPerIPPerHour: 5000, referers: [], // Empty = no referer restriction (backend use) }, }); // Create a search key restricted to specific referers (frontend) 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: 50, }, });
Step 3: Generate Secured API Keys (Per-User Filtering)
// Secured API keys are generated on YOUR server, not via Algolia API. // They embed restrictions that the client can't bypass. 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: { // User can only see their tenant's data filters: `tenant_id:${tenantId}`, // Key expires in 1 hour validUntil: Math.floor(Date.now() / 1000) + 3600, // Restrict to specific indices restrictIndices: ['products'], // Optional: restrict sources (IPs) restrictSources: '', }, }); } // Usage in your API endpoint: // const userKey = generateUserSearchKey(req.user.id, req.user.tenantId); // return { appId: process.env.ALGOLIA_APP_ID, searchKey: userKey };
Step 4: Key Rotation Procedure
async function rotateApiKey(oldKeyDescription: string) { const client = algoliasearch(process.env.ALGOLIA_APP_ID!, process.env.ALGOLIA_ADMIN_KEY!); // 1. List keys to find the old one const { keys } = await client.listApiKeys(); const oldKey = keys.find(k => k.description === oldKeyDescription); if (!oldKey) throw new Error(`Key not found: ${oldKeyDescription}`); // 2. Create new key with same ACL 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 || [], }, }); console.log(`New key created: ...${newKey.slice(-8)}`); console.log('Update your env vars, then delete the old key:'); console.log(` client.deleteApiKey({ key: '${oldKey.value}' })`); return newKey; }
Security Checklist
- Admin key in env vars, never in frontend code or git
-
files in.env.gitignore - Frontend uses Search-Only or Secured API key
- Custom keys have minimal ACL (least privilege)
-
set on frontend keys to prevent abusereferers -
set on all public keysmaxQueriesPerIPPerHour - Secured API keys have
(expiration)validUntil - Key rotation scheduled quarterly
- Git history scanned for accidentally committed keys
Error Handling
| Security Issue | Detection | Mitigation |
|---|---|---|
| Admin key exposed in frontend | Code review, git scanning | Rotate immediately, restrict referers |
| Key in git history | | Rotate key, use git-secrets or gitleaks |
| Excessive ACL on key | Audit key permissions | Create scoped replacement key |
| Expired secured key | in the past | Generate fresh secured key |
Resources
Next Steps
For production deployment, see
algolia-prod-checklist.