Implementing OIDC From Scratch Is Hard
Cover photo by Adi Goldstein on Unsplash
Stop building your own auth providers
I was looking at a pull request yesterday where a dev decided to hand-roll the OpenID Connect flow. They were manually parsing JWTs, validating claims, and trying to dance the authorization code grant shuffle. It was a mess. Stop doing this. Unless you are building an identity provider (and even then, I would suggest looking at existing battle-tested libraries), you are just creating a massive security liability for yourself.
Why you get it wrong
OIDC isn’t just one protocol. It is a set of rules layered on top of OAuth 2.0. You have to handle discovery endpoints, handle key rotation (JWKS), validate nonces, and manage state to prevent cross-site request forgery. It is trivial to get wrong. If you miss one check, your entire application access model crumbles.
Here is what the basic verification of an ID token should look like in a sane world:
// Don't do this from scratch if you can avoid it!import { jwtVerify, createRemoteJWKSet } from 'jose';
const JWKS = createRemoteJWKSet(new URL('https://provider.com/.well-known/jwks.json'));
async function verify(token) { const { payload } = await jwtVerify(token, JWKS, { issuer: 'https://provider.com', audience: 'my-client-id', }); return payload;}But wait, what if I need to?
“But Namir, what if I have highly specific compliance requirements that standard providers can’t meet?”
That is a fair point. If you work in a niche industry with bizarre data sovereignty laws, you might have to build something custom. I’ll admit that I’ve been in a project once where using a third-party managed service was legally impossible. Even then, I still wouldn’t write the crypto logic myself. Use an existing library or a framework-level tool. There are mature options in almost every language (like Auth.js for the JavaScript ecosystem).
The real cost of custom work
When you build this yourself, you are signing up for maintenance. Security standards change. Cryptographic best practices evolve. If you roll your own OIDC implementation, you are the one responsible for patching it when a new vulnerability drops. That is a full-time job.
I prefer spending my time building features that actually help users. (Which, incidentally, is why I prefer using managed platforms for the heavy lifting.)
How to actually start
If you really want to understand how this stuff works, read the RFCs. Don’t write the code for production. Build a small experiment to see how the handshake works, realize how many moving parts there are, and then throw that code away. Use a library that is maintained by people who spend their entire lives worrying about security headers and token signatures.
What’s the most common mistake you see developers make when they try to integrate OIDC for the first time?