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 Much Ca$h Do I Bring To Europe?
How to Turn Off Screen Mirroring | Step-by-Step Guide –
Bleak Faith: Forsaken – im Test (PS5)
Time in Baltimore, Maryland, United States now
فیلم رهگیر دوبله فارسی بدون سانسور نماشا
Euro (EUR), aktuální kurzy měn
Soap2Day Autoplay
30% OFF Jellycat Promo Code - September 2024 (*NEW*)
Mivf Mdcalc
Rochester Ny Missed Connections
Sitcoms Online Message Board
Revitalising marine ecosystems: D-Shape’s innovative 3D-printed reef restoration solution - StartmeupHK
Myql Loan Login
2135 Royalton Road Columbia Station Oh 44028
Johnston v. State, 2023 MT 20
Alejos Hut Henderson Tx
Kitty Piggy Ssbbw
Puretalkusa.com/Amac
Delaware Skip The Games
Traveling Merchants Tack Diablo 4
Big Lots Weekly Advertisem*nt
Sef2 Lewis Structure
Wics News Springfield Il
Roanoke Skipthegames Com
Panolian Batesville Ms Obituaries 2022
Meet the Characters of Disney’s ‘Moana’
O'reilly's In Mathis Texas
Is Henry Dicarlo Leaving Ktla
Japanese Emoticons Stars
R/Mp5
Sun Haven Pufferfish
Aliciabibs
Case Funeral Home Obituaries
The best Verizon phones for 2024
Vivek Flowers Chantilly
Property Skipper Bermuda
Craigslist Gigs Wichita Ks
Kornerstone Funeral Tulia
Indio Mall Eye Doctor
A Comprehensive 360 Training Review (2021) — How Good Is It?
Join MileSplit to get access to the latest news, films, and events!
O'reilly's Palmyra Missouri
How to Quickly Detect GI Stasis in Rabbits (and what to do about it) | The Bunny Lady
The best specialist spirits store | Spirituosengalerie Stuttgart
Giovanna Ewbank Nua
Mynord
From Grindr to Scruff: The best dating apps for gay, bi, and queer men in 2024
The Cutest Photos of Enrique Iglesias and Anna Kournikova with Their Three Kids
Hughie Francis Foley – Marinermath
Tanger Outlets Sevierville Directory Map
Bloons Tower Defense 1 Unblocked
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.