The password that outlives the person who set it
A partner integration goes live. Someone on your team, under deadline, skips real API authentication and just hands the partner the same login your customer support staff use to check orders. It works. Everyone moves on. Eight months later that partner relationship ends, and nobody can say for certain what data they touched, when they last logged in, or whether they're still pulling records through a Zapier flow nobody remembers approving.
This is how API authentication actually breaks at most small and mid-size companies. Not in one dramatic breach, but in a slow accumulation of shortcuts that made sense individually and add up to a system nobody trusts.
Why API authentication starts out fine and doesn't stay that way
Your first app is simple. A customer logs into a web portal, gets a session cookie, and that's the whole story. One user type, one login flow, one place to check who's who.
Then growth happens, and growth means more consumers of your data. A mobile app needs a token that survives longer than a browser session. Your ops team wants a back-office tool with different permissions than customers get. A partner wants to pull order status into their own system. Someone wants to connect QuickBooks. Eventually someone wants to wire up an AI assistant that can look up a customer's account and answer a question without a human in the loop.
Each of these gets bolted onto the original session-based login because that's what already exists. A "temporary" API key gets minted off someone's personal admin account. A contractor gets a shared login because setting up a real service account takes a sprint nobody has time for. Six months in, you've got five different ways into the same system, none of them documented, and half of them tied to a person instead of a purpose.
That's the core problem. Authentication that was designed for one type of user gets stretched to cover five, and nobody goes back to redesign it, because it "works."
The fixes people reach for, and why they don't hold
"Just give them an API key." Fine, until you realize the key has the same permissions as a logged-in admin because nobody built scopes. Now every integration partner can technically read, write, or delete anything in your system, and you're trusting their security practices as much as your own.
"We'll use one shared service account for all our integrations." This one feels efficient right up until you need to revoke access for a single partner. You can't, because rotating that credential breaks four other things at the same time. So you don't rotate it. It just sits there, valid forever, used by systems you've lost track of.
"We'll add OAuth later, once we have more partners." Reasonable in theory. In practice, "later" means you bolt OAuth onto an app that was never built with delegated access in mind, and it takes three times as long as it would have taken to build it right the first time, because now you have live integrations depending on the old auth model that you can't just rip out.
"Let's just log every login attempt." Logging logins tells you who signed in. It doesn't tell you what a credential actually did once inside — which records it touched, which endpoints it called, whether that 2am API call was the nightly sync job or something else entirely.
None of these are stupid decisions in isolation. They're the fast path, and the fast path is usually right for a first version. The mistake is never circling back once you have more than one type of consumer touching your API.
What you're actually trading off
There's no version of this that's free. The question is which cost you pay now versus later.
- Session cookies vs. tokens. Cookies are simple and fine for a browser-only app. They fall apart the moment a mobile app, a partner, or a background job needs to authenticate without a browser in the loop. If you have more than one consumer type, you need token-based auth for at least the non-browser cases.
- One shared credential vs. one per integration. A shared key is less setup work today. A key per partner (or per integration, or per environment) means more to manage, but it's the only way to revoke one thing without breaking five others, and the only way to know which system did what.
- Scoped permissions vs. all-or-nothing access. Building real scopes (read-only order status vs. full account access) takes longer than issuing an admin-equivalent key. It's also the difference between a compromised partner integration being a minor incident and a full breach.
- OAuth vs. plain API keys. OAuth 2.0 is the right call when a third party needs to act on behalf of your users with their consent — think "connect your Google Calendar." It's overkill for straightforward machine-to-machine integrations like a nightly Stripe reconciliation job, where a scoped API key does the job with far less overhead. Don't reach for OAuth because it sounds more secure; reach for it because the use case actually involves a user granting delegated access.
Picking the simpler option isn't wrong. Picking it and never revisiting it is.
A decision path that actually works
Before you issue the next credential, walk through this:
- Who or what is asking for access? A person on your team, an external partner, another system, or an AI agent are four different answers with four different auth patterns. Don't default all of them to "give them a login."
- Is there more than one consumer type already? Browser users, mobile app, staff tool, partner integrations. If the answer is yes and you're still on one auth mechanism, that's your sign to split it out before adding a fifth.
- Does this credential need to act on behalf of a specific user, or as a system in its own right? Delegated access (on behalf of a user) points to OAuth. System-to-system access points to a scoped API key or service account.
- What's the minimum this credential actually needs to do? Not "what's convenient to grant," but the actual minimum. If a partner only needs order status, they don't need customer contact details or write access.
- What happens when this relationship ends? If you can't answer "we revoke this one credential and nothing else breaks," you've built a shared dependency, not an integration.
- Is every credential's activity logged at the action level, not just at login? You want to know it read order #4471, not just that it logged in successfully at 2:14am.
If you can't answer these for your current integrations, that's the audit to run before you add the next one.
Getting from here to there without a rebuild
You don't need to tear down your app to fix this. Most of the work is sequencing.
Start by mapping what exists: every partner, every integration, every service account, and what credential each one is actually using today. Most teams are surprised by how many of these turn out to be a shared login nobody remembers creating.
Consolidate identity into one place. If your customer portal, your staff tool, and your partner API each have their own separate user tables, you're not managing access — you're managing three different guesses about who someone is. One source of truth for identity is what lets you actually answer "who has access to what" in a single query instead of a scavenger hunt across systems.
From there, introduce scoped API keys for machine-to-machine integrations before you reach for anything heavier. It solves the majority of real-world cases — partner data pulls, background jobs, third-party syncs — without the overhead of a full OAuth implementation. Save OAuth for the specific case of a third-party app acting on a user's behalf with their consent.
Set an expiration and rotation policy before you hand out the first key, not after the first incident. And build action-level logging in from the start; it's far cheaper to add when you're issuing five keys than when you're issuing fifty.
This is also where AI agents fit in, and where they don't yet. An AI assistant that can look up a customer's order or trigger a refund needs the same disciplined identity and scoped permissions as any other API consumer — arguably more, since it's making decisions without a human double-checking each call. If your current auth setup is a pile of shared credentials with no clear boundaries, adding an AI agent on top just gives you a faster way to misuse those same holes. Structured, scoped access has to exist first. The AI layer works on top of clean permissions, not instead of them.
Where to start
If you're staring at a spreadsheet of "who has API access to what" and can't fill in half the cells, that's the actual starting point — not a new auth library, not a rewrite. We've walked SMB teams through exactly this kind of untangling, connecting the systems and identity models that had drifted apart before layering automation or AI on top; you can see examples of that work in our case studies.
If you want a second set of eyes on your own setup, we run a free 30-minute Process Teardown where we map one of your painful workflows — auth included — and show you what it's quietly costing in time or risk. No pitch, just the map.
0 Comment