Validating Microsoft Entra ID generated OAuth tokens

In this post, I'll explain how you can validate OAuth tokens generated by Microsoft Entra ID in your custom apps.

By Last Updated: June 24, 2024 5 minutes read

If you create an application or API that is secured with Microsoft Entra ID, you are likely going to require a consumer of your application to provide an OAuth access token in order to access your application or API. The caller would have to obtain this token from Entra ID by first authenticating with Entra ID and then request a token for your application.

For the rest of this post, I’m going to assume you are working with a REST API, but everything applies to an application as well.

But anyone can create an OAuth access token. It’s just a JSON object that has a set schema and then base64 encoded. There’s nothing secure about it.

What legitimizes its use as a security token is that the creator of the token digitally signs the token with a public-private key pair. The creator of the token uses their private key and includes the result in the OAuth access token in the JWT (JavaScript Web Token) format.

If you’ve elected to use Entra ID to secure your REST API, you have established a trust with Entra ID. Therefore, when you receive the OAuth access token from the caller, you should first validate two things:

  1. This token was generated by Entra ID & its contents have not been altered
  2. This token is intended to be used only by “me”

Validating the intended audience

The second part of this validation process is very simple. You need to check the audience part of the JWT token. This is listed as the aud property and it contains the URI of the audience the token is intended for.

Confused? Think of this like the street address of your home. A key used to unlock your front door has this address on it. A key with a different address should not be “validated” and allowed to open your front door because it is intended to be used with someone else’s front door (aka: a different audience).

You can ensure the audience property in the token was set by Entra ID because you previously validated that the token was generated by Entra ID and it’s contents have not been altered.

Wait… we skipped that part… let’s jump back…

Validating Entra ID JWT tokens

So… how you do validate an Entra ID JWT token? A JWT token contains three sections:

  • header: specifies the algorithm used to digitally sign the token & type of the token
  • payload: the data in the JWT token… what we want to work with
  • verification signature: this part contains the digital signature of the token that was generated by Entra ID’s private key.

The way you validate the authenticity of the JWT token’s data is by using Entra ID’s public key to verify the signature. If it works, you know the contents were signed with the private key. If not, you can’t be sure of it so you should treat the JWT token as an invalid token.

So… back to the question: how you do validate an Entra ID JWT token?

You first need to obtain the Entra ID public key. To do this, start by calling the public Entra ID OpenID configuration endpoint:

Within the JSON response, you’ll see a property jwks_uri which is the URI that contains the JSON Web Key Set for Entra ID. For Entra ID, that URI is

Results of a request for the OpenID configuration with Postman

Results of a request for the OpenID configuration with Postman

When you go there, you’ll see an array of keys. Each key has a set of properties. I’m only interested in a few of these, but you can learn about all properties here if you’re interested.

What you’re looking for is a key that has the same thumbprint of the x.509 certificate (SHA-1 thumbprint) that’s listed in the header of the JWT token you got from Entra ID. How do you get that?

I’m going to use the site to easily decode a real JWT token I got from calling the Microsoft Graph. Look at the header value:

Locate the KID property

Locate the KID property

Using the kid property, I can tell that’s the key I’m looking for. So going back to the JSON Web Key Set URL for Entra ID, I’ll find the matching key.

Locate the matching KID and x5c certificate

Locate the matching KID and x5c certificate

Once you find the key, take the value and wrap it in the begin & end certificate markers: -----BEGIN CERTIFICATE-----<newline><key><newline>-----END CERTIFICATE-----.

This new string is what you can use as the public key to validate a JWT token. For instance, using the npm package jsonwebtoken, you can do it like this:

import jwt = require('jsonwebtoken');

const decodedValidToken = (accessToken: string) => {
  const key: string = '-----BEGIN CERTIFICATE-----\nMIIDBTCCAe...\n-----END CERTIFICATE-----';

  // decode & verify token
  return jwt.verify(accessToken, key);

const authorizationHeader: string = req.headers.authorization;
const decodedToken = (decodedValidToken(authorizationHeader.replace('Bearer ','')) as any);

If no errors were thrown and you got a token back, you have yourself a validated JWT token that you can trust was created by Entra ID and has not been tampered since Entra ID generated it!

If errors were thrown, you can check for specific issues with the validation process, as documented in the jsonwebtoken npm package: Errors & Codes