Skip to main content

Creating a JWT

When to create a JWT?#

The first step is to create a JWT from the microservice that will be sending the request (let's call this microservice M1). This JWT will be verified by other microservices when M1 sends them a request. Since this JWT remains static per microservice, the best time to create this is on process starts - i.e. when M1 starts.

What to add in the JWT?#

The JWT can contain any information you like, but at a minimum, it needs to contain information proving that it is a microservice that is allowed to query other microservices in your infrastructure. This is needed since you may issue a JWT to an end user as well, and they should not be able to query any microservice directly.

We can add the following claim in the JWT to "mark" the JWT as one that is meant for microservice auth only:

{..., "source": "microservice", ...}

In the receiving microservice (M2), we can then verify the JWT and check that this claim is present before serving the request.

Code for creating a JWT#

First, we need to initialise the JWT recipe in the supertokens.init function call:

import supertokens from "supertokens-node"
import jwt from "supertokens-node/recipe/jwt"

supertokens.init({
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "..."
},
supertokens: {
connectionURI: "...", // location of the core
apiKey: "..." // provide the core's API key if configured
},
recipeList: [
jwt.init()
]
})
important
  • The value of apiDomain should be the domain part of the JWKS URL that will be used to verify the JWT (from M2). This should ideally be the domain of the microservice that has all the other SuperTokens' recipes initialised in them.
  • If this microservice does not initialise any other recipe, the values of appName and websiteDomain don't matter.

After this, you can use the JWT recipe to create your own JWT whenever required:

import jwt from "supertokens-node/recipe/jwt"

async function createJWT(payload: any) {
let jwtResponse = await jwt.createJWT({
...payload,
source: "microservice"
});
if (jwtResponse.status === "OK") {
// Send JWT as Authorization header to M2
return jwtResponse.jwt;
}
throw new Error("Unable to create JWT. Should never come here.")
}
note

By default, the lifetime of the JWT will be a 100 years. You can pass a second argument to the createJWT function indicating a custom lifetime (in seconds) for the JWT.

note

By default, the JWT is signed by a static key, not subject to the key rotation normally applied to access tokens. You can pass false as the third argument to the createJWT function to use use the dynamic keys.

What to do with the JWT?#

Once the JWT is created, you can store it in a (globally accessible) variable and access it when you want to talk to a microservice. You can add the JWT as an Authorization: Bearer token like so:

curl --location --request POST 'https://microservice_location/path' \
--header 'Authorization: Bearer eyJraWQiOiI0YTE...rCFPcIRgzu_bChIIpFdA' \
--header 'Content-Type: application/json' \
--data-raw '{
"request": "payload"
}'