Validate an OpenID Connect JWT using a public key in JWKS (2024)

Validate an OpenID Connect JWT using a public key in JWKS (1)

Axel Navarro for Cloud(x);

Posted on

Validate an OpenID Connect JWT using a public key in JWKS (4) Validate an OpenID Connect JWT using a public key in JWKS (5) Validate an OpenID Connect JWT using a public key in JWKS (6) Validate an OpenID Connect JWT using a public key in JWKS (7) Validate an OpenID Connect JWT using a public key in JWKS (8)

#javascript #node #security #webdev

You may have used OpenID Connect in the Front-end, where an IDP (IDentity Provider) authenticates a user, gives you a bunch of tokens in the browser and then you can add the Authorization header to your HTTP requests to your own Back-End because you trust this IDP. But what happens when you can't find where you can verify the id_token (or access_token) using some endpoint in the IDP?

Well, I found how an OpenID Connect id_token should be validated. It wasn't straightforward in my case: I had to do a lot of research to validate my id_token. Let's see how to make this easy using Node.js and the jsonwebtoken npm package made by Auth0.

Understanding JWT to know how to validate it

A JSON Web Token (JWT) is a string built with 2 JSON objects encoded in base64 and a signature; these parts are joined by a period (.) with the following structure: <header>.<payload>.<signature>.

💡 This is why a JWT always starts with ey, because it is the result of encoding {" using base64, which is the beginning of any JSON.

In the header part we can find which signature algorithm was used in the alg parameter (e.g. RS256) to sign the JWT, and the kid parameter tells which Key ID from the JSON Web Key Set (JWKS) was used for a given token.

🧠 Remember that when the JWT header has a Key ID (kid), JWKS is used.

And here is where the problem starts. Where do I find the JWKS to get the public key so we can verify the integrity of this token? 😫

The issuer

The issuer is the one who created and signed the JWT, and we can know this by checking the value iss in the payload of our JWT - using jwt.decode from jsonwebtoken.

const jwt = require('jsonwebtoken');const payload = jwt.decode('<your_jwt_here>');console.log(payload.iss);

Alternatively, you can paste your JWT into https://jwt.io (don't worry, it's a safe website from Auth0), and iss is there too!

In OpenID Connect, the issuer should be a URL, but it could just be the name of the IDP. In that case you should read more docs to find where the JWKS URI is. 😭

For our example we can use https://sandrino.auth0.com as an issuer, so you can know the OpenID configuration using the well-know URI https://sandrino.auth0.com/.well-known/openid-configuration, and in the jwks_uri attribute is where you can find the JWKS for our issuer. You can check this same value in another issuer https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration, the jwks_uri is there too! 😉

const jwt = require('jsonwebtoken');const printJwksUri = async (issuer) => { const response = await fetch(`${issuer}/.well-known/openid-configuration`); const {jwks_uri} = await response.json(); console.log(jwks_uri);};const token = '<your_jwt>';const {iss} = jwt.decode(token);printJwksUri(iss);

We have the JWKS URI programmatically in Node.js! 🥳

Verifying the token

Now that we know enough about JWKS, we can write a Node.js code to validate an OpenID token that discovers the JWKS URI if you don't know where it is.

const {promisify} = require('node:util');const jwt = require('jsonwebtoken');const jwksClient = require('jwks-rsa');const fetchJwksUri = async (issuer) => { const response = await fetch(`${issuer}/.well-known/openid-configuration`); const {jwks_uri} = await response.json(); return jwks_uri;};const getKey = (jwksUri) => (header, callback) => { const client = jwksClient({jwksUri}); client.getSigningKey(header.kid, (err, key) => { if (err) { return callback(err); } callback(null, key.publicKey || key.rsaPublicKey); });};/** * Verify an OpenID Connect ID Token * @param {string} token - The JWT Token to verify */const verify = async token => { const {iss: issuer} = jwt.decode(token); const jwksUri = await fetchJwksUri(issuer); return promisify(jwt.verify)(token, getKey(jwksUri));};const token = '<your_jwt>';verify(token) .then(() => console.log('Token verified successfully.')) .catch(console.error);

⚠️ Did you notice that I didn't check who is the issuer? This code will accept any of them, even a malicious one. 😨 To control this just accept issuers from an allowed list.

const allowedIssuers = [ 'https://login.microsoftonline.com/common/v2.0', 'https://sandrino.auth0.com',];const fetchJwksUri = async (issuer) => { if (!allowedIssuers.includes(issuer)) { throw new Error(`The issuer ${issuer} is not trusted here!`); } const response = await fetch(`${issuer}/.well-known/openid-configuration`); const {jwks_uri} = await response.json(); return jwks_uri;};

With this little change you're safe now 🔒

Conclusion

Like I mentioned in this post, these well-known URIs are a standard method to get information for specific features, and issuers should implement the /.well-known/openid-configuration to integrate it easier to your authentication flow.

🧠 OpenID Connect is a safe way to authenticate users, but you always have to verify the token's integrity in the Back-End side and check if it was created by a trusted issuer.

🔑 Remember that this scenario only works with JWKS (when the certificate is pre-distributed to the clients the JWT header has x5t instead of kid). You can find examples with public.pem files in the jsonwebtoken package.

🪙 Bonus tip if you use Autenticar service from the Argentinian government, a.k.a AFIP Clave Fiscal, you can use this code to validate the id_token with the JWKS.

Validate an OpenID Connect JWT using a public key in JWKS (2024)
Top Articles
HODL vs Staking What is the best strategy?
Crypto During A Recession: Here's What To Expect | Bankrate
Barstool Sports Gif
Ron Martin Realty Cam
Hotels Near 625 Smith Avenue Nashville Tn 37203
Blorg Body Pillow
Access-A-Ride – ACCESS NYC
Occupational therapist
Goodbye Horses: The Many Lives of Q Lazzarus
Repentance (2 Corinthians 7:10) – West Palm Beach church of Christ
How To Do A Springboard Attack In Wwe 2K22
America Cuevas Desnuda
Is Sportsurge Safe and Legal in 2024? Any Alternatives?
Phenix Food Locker Weekly Ad
Craigslist Labor Gigs Albuquerque
Programmieren (kinder)leicht gemacht – mit Scratch! - fobizz
Animal Eye Clinic Huntersville Nc
Willam Belli's Husband
Nick Pulos Height, Age, Net Worth, Girlfriend, Stunt Actor
Zack Fairhurst Snapchat
ZURU - XSHOT - Insanity Mad Mega Barrel - Speelgoedblaster - Met 72 pijltjes | bol
Hdmovie 2
Decosmo Industrial Auctions
Keci News
Timeforce Choctaw
Japanese Mushrooms: 10 Popular Varieties and Simple Recipes - Japan Travel Guide MATCHA
Form F-1 - Registration statement for certain foreign private issuers
6 Most Trusted Pheromone perfumes of 2024 for Winning Over Women
Sherburne Refuge Bulldogs
Kirsten Hatfield Crime Junkie
Barista Breast Expansion
Wat is een hickmann?
Criterion Dryer Review
27 Fantastic Things to do in Lynchburg, Virginia - Happy To Be Virginia
Rs3 Bring Leela To The Tomb
Aid Office On 59Th Ashland
Life Insurance Policies | New York Life
The value of R in SI units is _____?
What Is Xfinity and How Is It Different from Comcast?
Babbychula
Litter-Robot 3 Pinch Contact & DFI Kit
Giantess Feet Deviantart
Indiana Wesleyan Transcripts
Keeper Of The Lost Cities Series - Shannon Messenger
The best bagels in NYC, according to a New Yorker
Conan Exiles Colored Crystal
Lebron James Name Soundalikes
Dayton Overdrive
Www.homedepot .Com
Cvs Minute Clinic Women's Services
WHAT WE CAN DO | Arizona Tile
Latest Posts
Article information

Author: Kareem Mueller DO

Last Updated:

Views: 5815

Rating: 4.6 / 5 (46 voted)

Reviews: 85% of readers found this page helpful

Author information

Name: Kareem Mueller DO

Birthday: 1997-01-04

Address: Apt. 156 12935 Runolfsdottir Mission, Greenfort, MN 74384-6749

Phone: +16704982844747

Job: Corporate Administration Planner

Hobby: Mountain biking, Jewelry making, Stone skipping, Lacemaking, Knife making, Scrapbooking, Letterboxing

Introduction: My name is Kareem Mueller DO, I am a vivacious, super, thoughtful, excited, handsome, beautiful, combative person who loves writing and wants to share my knowledge and understanding with you.