Authenticate Hasura API calls with Okta JWT

Shanmuganathan Vijayaraman
4 min readFeb 27, 2023

--

The prime intention of this article is to use Okta’s JWT to authenticate Hasura API calls. I had to search to get this done and wished to document it as none have. This integration was quite simple, with both Hasura and Okta providing clear instructions on what to do. You can consider this blog as the TL;DR version of their documentation.

Something that looks nice and relevant
Photo by Apollo Photography on Unsplash

This blog is meant for a quick read and hence not going to talk about what Okta and Hasura are.

I created new Okta and Hasura Cloud accounts for this POC. Hasura Cloud comes with a starter instance of Neon out of the box, which makes life so easy. In addition, I’ve put together a simple React app that integrates with both Hasura and Okta. Okta secures all routes in this app. Once the page is launched, it executes a graphQL query to pull data from the Customer table (which comes by default as part of Neon setup).

What’s required for Hasura to decode the JWT?

Following are the basics required for the integration to work well.

  1. Prepare Hasura — Hasura should be able to understand the JWT shared by Okta which is taken care of by sharing the JWK URI to Hasura.
  2. Prepare Okta — The JWT should specify the role to be assigned to the user (This POC revolves around passing the default role for the user as part of the JWT claims. There does exist an alternate mechanism to pass the role as part of the request header).

Prepare Hasura

Launch Hasura cloud and reach the settings screen for the new app you’ve created. Click on the Env vars section and add a new environment variable.

Key: HASURA_GRAPHQL_JWT_SECRET
Value: {
"jwk_url": "https://<Your OKTA Domain>/oauth2/<Auth server Id>/v1/keys"
}

Prepare Okta

Launch Okta and reach the Claims screen of your Authorization server. Click the add claims button to add the following claim

Name: https://hasura.io/jwt/claims
Include in token type : Access Token
Value type: Expression
Value: {"x-hasura-default-role": "APP_USER", "x-hasura-allowed-roles": Arrays.flatten("APP_USER")}

Now, what’s expected?

When the access token received from Okta is passed to Hasura as a Bearer token, Hasura will allow the request to process with role set to APP_USER. This wouldn’t work out of the box as Hasura doesn’t have a clue on what APP_USER role does. We should change the permissions in the required tables to make this work.

Adding Role Permissions

Go to the permissions tab for the Customer table (via Hasura Console’s data tab), add the APP_USER role and assign Select permission. Do the same for all tables that have a relationship with the Customer table.

Modifying table permissions

This will let the query to execute when invoked with this role.

Let’s see if this works

Pass access token in the request header and do not pass Hasura admin secret anymore.

Pass Access token in the Header

Let’s launch the app to see how this works.

Upon launching localhost:3000, the app takes you to Okta login page.

Once you’ve logged in successfully, the app prints the access token details on screen.

Navigate to localhost:3000/home to see the graphQL request execute successfully by passing the access token as Authorization Bearer.

Let’s comment out the Authorization token to see what happens

Hasura rejects the request as no valid Authorization header or admin secret found in the header.

That was quick without much of a hassle. Hope this doc was precise. The React app used for this demo can be found here.

--

--