๐ง๐๐ผ ๐๐๐ด๐ ๐ง๐ต๐ฎ๐ ๐ง๐ฎ๐๐ด๐ต๐ ๐ ๐ฒ ๐ ๐ผ๐ฟ๐ฒ ๐ง๐ต๐ฎ๐ป ๐๐ป๐ ๐ง๐๐๐ผ๐ฟ๐ถ๐ฎ๐น
I learned two lessons during my internship. Both lessons came from bugs that passed my local tests but failed in production.
Bug 1: The PKCE Auth Failure
I built a CLI tool for GitHub authorization. The flow worked like this:
- The CLI creates a verifier and a state.
- It saves these to a database.
- It opens a browser for user login.
- GitHub redirects back to a local callback.
- The CLI uses the state to find the verifier and get tokens.
The issue: The redirect failed because of how the state parameter behaved during the handoff. I assumed the state would always return exactly as I sent it. It did not.
Bug 2: The Argon2 Database Trap
I worked on a team project for session management. We used Argon2 to hash refresh tokens for security.
The logic looked correct:
- On login, we hashed the token and saved it to the database.
- On refresh, we tried to find the session by searching for the hashed token in the database.
The failure: Argon2 is non-deterministic. This means the same input produces a different hash every time. You cannot use a hashed token to search a database. A lookup query will always fail.
The fix: I changed the logic to use a unique ID instead.
- On login, I embed a unique tokenId in the JWT.
- I hash the refreshToken and save it with the tokenId.
- On refresh, I find the session using the tokenId.
- I then use Argon2.verify to check if the token is valid.
The lesson:
Both bugs happened because of one thing. I made assumptions about how my tools worked.
I assumed the state parameter was a constant. I assumed the hash would be predictable.
Do not just read documentation. Build a habit of asking one question: What assumptions am I making about this library?
Asking this question saves more time than any tutorial.
Source: https://dev.to/clinztouch/two-bugs-that-taught-me-more-than-any-tutorial-2jh7