Credentials That Rot
Two ways to prove who you are, and why one of them quietly expires on you.
A build broke because of a credential that was valid until 2035.
Not expired. Not malformed. Valid, and useless — and the difference taught me a distinction I now reach for constantly.
Two kinds of credential
A session token is what you get when you log in. The crucial part isn't the token; it's that the server wrote a row in its database when it issued one. When you present the token later, the server looks that row up. The token is a claim check. No row, no entry.
An API key is checked by the server directly. Nothing had to be stored earlier. It stands on its own.
They look the same in a config file. Both are opaque strings you paste into a secret. That resemblance is the trap.
What broke
A test suite needed to log in as an admin. It used a session token, committed to the repo, that had been issued against a developer's local database. Locally, the test setup restores a database dump — and the dump contains the matching row. So it works.
Against the shared environment, nobody had ever logged in as that user. No row. The server correctly said: I don't know this session.
The token wasn't old. It was a key to a different building.
Why I care about the distinction now
Because the tempting fix is to generate a fresh session token for the shared environment and put it in CI. That works tomorrow. It also:
- dies the moment anyone logs that account out, since logout deletes the row
- is tied to one person, and rots when they rotate credentials or leave
- stores a live human session in a build system
An API key has no row to delete. There's nothing to go stale.
The general shape
The question I ask now about any credential is: does this depend on state somewhere else?
If yes, that state is part of your system whether you modelled it or not, and something will eventually delete it at an inconvenient time. If no, you have a thing that either works or doesn't, consistently.
Most "it worked last week" mysteries I've chased have had a deleted row at the bottom of them.