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
How to Become a Proofreader (with or without a degree)
Netflix subscriber share U.S. 2023 | Statista
Xre-02022
Thor Majestic 23A Floor Plan
Botw Royal Guard
Horoscopes and Astrology by Yasmin Boland - Yahoo Lifestyle
Mr Tire Rockland Maine
Urinevlekken verwijderen: De meest effectieve methoden - Puurlv
Tight Tiny Teen Scouts 5
Zendaya Boob Job
Günstige Angebote online shoppen - QVC.de
What Is A Good Estimate For 380 Of 60
Inevitable Claymore Wow
Industry Talk: Im Gespräch mit den Machern von Magicseaweed
Espn Horse Racing Results
Video shows two planes collide while taxiing at airport | CNN
Royal Cuts Kentlands
Apply for a credit card
Craigslist Maui Garage Sale
Hdmovie 2
Never Give Up Quotes to Keep You Going
Melendez Imports Menu
Scream Queens Parents Guide
Air Quality Index Endicott Ny
Anotherdeadfairy
Mini Handy 2024: Die besten Mini Smartphones | Purdroid.de
Everything To Know About N Scale Model Trains - My Hobby Models
Apparent assassination attempt | Suspect never had Trump in sight, did not get off shot: Officials
Panolian Batesville Ms Obituaries 2022
Weathervane Broken Monorail
Cosas Aesthetic Para Decorar Tu Cuarto Para Imprimir
Gopher Carts Pensacola Beach
Eegees Gift Card Balance
Armor Crushing Weapon Crossword Clue
Kaiser Infozone
Dumb Money, la recensione: Paul Dano e quel film biografico sul caso GameStop
Gerber Federal Credit
Worlds Hardest Game Tyrone
The Wichita Beacon from Wichita, Kansas
Xemu Vs Cxbx
Staar English 1 April 2022 Answer Key
Skip The Games Ventura
Cross-Border Share Swaps Made Easier Through Amendments to India’s Foreign Exchange Regulations - Transatlantic Law International
Enjoy4Fun Uno
Craigslist Gigs Wichita Ks
Michael Jordan: A timeline of the NBA legend
Telugu Moviez Wap Org
Lacy Soto Mechanic
Displacer Cub – 5th Edition SRD
Pas Bcbs Prefix
Craigslist Sparta Nj
Grandma's Portuguese Sweet Bread Recipe Made from Scratch
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.