How I Would Fix exposed API keys and missing auth in a Make.com and Airtable client portal Using Launch Ready.
If I open a client portal and find Airtable keys in the browser, Make.com webhooks callable by anyone, or pages that let users see data without signing...
How I Would Fix exposed API keys and missing auth in a Make.com and Airtable client portal Using Launch Ready
If I open a client portal and find Airtable keys in the browser, Make.com webhooks callable by anyone, or pages that let users see data without signing in, I treat it as a production security incident. The most likely root cause is simple: the app was built fast, with secrets placed in frontend code or shared automations, and auth was either skipped or added only as a UI gate.
The first thing I would inspect is the actual request path from browser to backend to Airtable. I want to see where the key lives, who can hit the webhook, whether records are filtered server-side, and whether any client-side code is exposing credentials in the network tab or build output.
Triage in the First Hour
1. Check the live portal in an incognito window.
- Try opening protected pages without logging in.
- Refresh deep links directly, not just through navigation.
- Confirm whether data still loads when auth state is missing.
2. Open browser DevTools and inspect Network.
- Look for Airtable API calls from the client.
- Look for Make.com webhook URLs embedded in requests or JS bundles.
- Check response payloads for too much data, especially other clients' records.
3. Review deployed environment variables.
- Confirm no Airtable token, Make webhook secret, or admin password is shipped to the frontend.
- Check hosting logs for accidental secret exposure during build or deploy.
4. Audit Make.com scenarios.
- Identify triggers that accept public HTTP requests.
- Verify every scenario has input validation and an auth check before any write action.
- Confirm no scenario can update records without verifying tenant ownership.
5. Audit Airtable base permissions.
- Check whether the base is shared too broadly.
- Confirm API tokens use least privilege and only access required tables.
- Review any synced views or shared interfaces that may leak data.
6. Inspect app logs and error monitoring.
- Look for 401, 403, and unexpected 200 responses on protected routes.
- Search for repeated anonymous access attempts or unusual webhook traffic.
- Note any failed login spikes after recent changes.
7. Freeze risky changes.
- Pause new feature work until the auth path is fixed.
- If needed, rotate exposed keys immediately before deeper debugging.
## Quick sanity check for exposed secrets in a frontend build grep -R "airtable\|make.com\|webhook\|api_key\|Bearer" dist build .next .vercel/output 2>/dev/null
Root Causes
1. Secrets were placed in frontend code.
- How to confirm: search source maps, bundled JS, and runtime network calls for Airtable tokens or Make webhook URLs.
- Common pattern: `VITE_`, `NEXT_PUBLIC_`, or similar public env vars used for private credentials.
2. The portal uses UI-only protection instead of real authorization.
- How to confirm: log out and request protected endpoints directly; if they still return data, auth is missing at the server layer.
- Common pattern: hidden buttons or route guards exist, but APIs do not verify session ownership.
3. Make.com webhooks are public and unauthenticated.
- How to confirm: test whether a webhook accepts requests without a signed token, nonce, or shared secret header.
- Common pattern: anyone with the URL can trigger writes into Airtable.
4. Airtable access is too broad.
- How to confirm: review token scope and base permissions; if one token can read or write everything, blast radius is too large.
- Common pattern: one master token powers all tenants and all actions.
5. Tenant filtering happens only in the browser.
- How to confirm: change IDs in query params or request bodies and see whether another client's records appear.
- Common pattern: `clientId` is trusted from the client instead of derived from session claims.
6. No logging or alerting exists around sensitive actions.
- How to confirm: look for missing audit trails on record reads, updates, login failures, and webhook invocations.
- Common pattern: issues are discovered by customers before internal monitoring catches them.
The Fix Plan
My goal is not just to patch symptoms. I would cut off direct secret exposure first, then put real authorization at every boundary so the portal cannot leak data even if one layer fails.
1. Rotate every exposed secret immediately.
- Revoke old Airtable tokens and Make.com credentials before anything else.
- Replace any leaked webhook URLs with new ones and invalidate old endpoints where possible.
- If a key was committed publicly, assume it is compromised forever.
2. Move all private calls behind a server-side boundary.
- The browser should never talk directly to Airtable with a private token.
- The browser should call your backend or serverless function only after auth succeeds.
- That backend then talks to Airtable using environment variables stored on the server.
3. Add real authentication on protected routes and APIs.
- Require session validation on every portal page that returns customer data.
- Enforce authorization on every API request based on user identity plus tenant membership.
- Do not trust client-provided `clientId`, `role`, or `email` values alone.
4. Lock down Make.com scenarios behind verification checks.
- Require a signed header or shared secret on incoming webhooks.
- Reject requests with missing auth, bad timestamps, duplicate nonces, or invalid payload shape before any write action runs.
- Keep destructive actions separate from read-only flows so one bad trigger cannot wipe data.
5. Reduce Airtable permissions to minimum scope.
- Split bases if needed so each workflow has only what it needs access to read or write.
- Use separate tokens for staging and production so test traffic cannot touch live records by accident.
- Restrict views so automations only read approved subsets of data.
6. Add server-side tenant checks everywhere data is fetched or updated. One safe pattern is:
if (!session?.user?.id) return res.status(401).json({ error: "Unauthorized" });
if (record.client_id !== session.user.client_id) {
return res.status(403).json({ error: "Forbidden" });
}This does not solve everything by itself, but it stops the most common cross-tenant leak: trusting whatever ID came from the browser.
7. Separate public content from authenticated content clearly in UX.
- Show login state explicitly instead of silently failing requests behind blank screens.
- Return clean 401 and 403 screens with next-step guidance so users know whether they need to sign in or request access again,
not just a spinner that never ends।
- Remove any cached pages that might show previous user data after logout.
8. Add basic abuse controls before redeploying publicly accessible endpoints:
- Rate limit login attempts and webhook calls,
- enforce CORS only for your domain,
- log sensitive actions without storing secrets,
- block repeated failures at Cloudflare if traffic looks automated.
9. Deploy through Launch Ready if this stack needs hardening fast across domain and delivery layers:
- Domain,
- email,
- Cloudflare,
- SSL,
- deployment,
- secrets,
- monitoring,
all handled together so you do not fix auth but leave DNS misroutes or insecure environment handling behind.
Regression Tests Before Redeploy
I would not ship this until these checks pass:
1. Anonymous access test
- Open protected routes without signing in.
- Expected result: 401 redirect or blocked screen every time.
2. Cross-account access test
- Log in as Client A and try fetching Client B records by changing IDs or query params:
expected result: 403 or empty result set based on policy.
3. Webhook abuse test - Send malformed requests to Make.com triggers with missing headers: expected result: rejected before any Airtable write occurs.
4. Secret exposure test - Search built assets and environment output for private keys: expected result: no private tokens present in frontend bundles, source maps, or public config files။
5. Session expiry test - Expire the session manually, then refresh portal pages: expected result: user sees logged-out state rather than stale cached data।
6. Logging test - Trigger denied access once per route: expected result: security logs capture timestamp, user ID if known, route, and denial reason without exposing sensitive payloads।
7. Smoke test on core business flows - Login, view dashboard, submit form, sync record to Airtable, receive confirmation email: expected result: all work within normal latency targets under 2 seconds p95 for page actions।
Acceptance criteria I would use:
- Zero private API keys visible in browser code or public logs。
- All protected routes require authentication。
- All record reads/writes enforce tenant-level authorization server-side。
- All external automations reject unsigned requests。
- No cross-client data appears during manual QA。
- Login failure rate stays below 2 percent during smoke testing。
Prevention
If I am preventing this from coming back, I focus on guardrails that catch mistakes before they reach customers:
1. Security review on every release touching auth or data flow - I would require a short checklist covering authentication、 authorization、 secret handling、 CORS、 rate limits、 and logging。
2. Separate environments properly - Use distinct dev、 staging、 and production bases、 tokens、 domains、 and Make scenarios。 Never reuse production credentials inside tests。
3. Secret scanning in CI - Add automated scans for API keys, webhook URLs, and private tokens before merge。 A single leaked key should fail the build。
4. Monitoring with alerts that matter - Alert on repeated 401/403 spikes, unexpected webhook volume, and failed automation runs。 If customers notice broken access before you do,the alerting is too weak。
5. UX guardrails around auth states - Design loading, empty, error, expired-session, and unauthorized states explicitly。 Bad UX often hides security bugs because nobody notices broken flows until support tickets pile up。
6. Least privilege everywhere - One service account should not have full control over all customer records。 One automation should not be able to update every table。
7. Performance guardrails after security fixes - Keep portal p95 under 500 ms for authenticated reads where possible。 Avoid adding heavy client-side logic just to hide problems that should be solved at the API layer。
When to Use Launch Ready
What I would ask you to prepare before kickoff:
- Access to hosting、DNS、Cloudflare、Make.com、Airtable、and your deployment platform。
- A list of all current domains、subdomains、and redirects。
- Any known exposed keys,old webhooks,or suspicious logs。
- A simple description of who should see which records inside the portal。
- Your preferred go-live window so I can rotate secrets without breaking active users unexpectedly。
If your product has already leaked credentials once,I would not wait another week hoping it stabilizes itself。I would fix auth,rotate secrets,tighten delivery settings,and hand back a production-safe portal with a clear checklist so you know exactly what changed。
References
- https://roadmap.sh/api-security-best-practices
- https://roadmap.sh/cyber-security
- https://roadmap.sh/code-review-best-practices
- https://roadmap.sh/qa
- https://www.airtable.com/developers/web/api/introduction
---
Take the next step
If this is a problem in your product right now, here is what to do next:
- [Use the free Cyprian tools](/tools) - estimate cost, score app risk, check launch readiness, or pick the right service sprint.
- [Book a discovery call](/contact) - I will tell you honestly whether you need a sprint or if you can DIY the next step.
*Written by Cyprian Tinashe Aarons - senior full-stack and AI engineer helping founders rescue, launch, automate, and scale AI-built products.*
Cyprian Tinashe Aarons — Senior Full Stack & AI Engineer
Cyprian helps founders rescue, secure, deploy, and automate AI-built apps with production-grade engineering, launch systems, and AI integration.