Auth0 Actions in action

I eagerly look forward to the end credits of the Marvel movies because they tease you with tidbits of the next movie. In the last post, I made a passing reference to the Auth0 Action Hackathon, in which I was the runner-up. This project deserves its own blog post because its a great showcase for how you can swiftly pair an off-the-shelf industry-grade Auth0 Action from the Auth0 Marketplace, with a custom-built Auth0 Action that secures your unique login posture, and assemble them to make them work together. It also wowed the hackathon judges !!!

How Vaccinated are you? Integration with COWIN #

With in-person events gradually increasing in number, as event organizers, we have to follow local #COVID19 guidelines and policies. That is also one of avowed goals of Visage. In India. that means we have to verify an attendee's vaccination status with the country's online portal for it, COWIN.

In September'21, the Ministry of Health and Family Welfare had announced a COWIN API called as Know Your Customer/Client Vaccination status[KYC-VS]

It is a set of 3 protected API where you need to register before hand with your company details before access is given.

Open API spec of the COWIN KYC-VS API

Given that the Govt do not want their systems to be unduly stressed, and it is geo-fenced, I am using the nifty Mock Server feature of Postman to simulate interactions with the COWIN API.

For our purposes, we will be using the Postman Collection of the COWIN KYC-VS API.

Postman Collection of the COWIN KYC-VS API

The collection has 3 requests:

  1. Generate OTP

    COWIN KYC-VS API requires you to generate an OTP before you can use the other APIs. The API is a POST request to the following endpoint:

    https://cdn-api.co-vin.in/api/v3/vaccination/generateOTP

    The request body is a JSON object with the following properties:

    {
    "mobile": "string",
    "name": "string"
    }

    The mobile field is the mobile number, and the name is the full name of the person whose vaccination status you want to check.

    In the response, you will receive a transaction ID, which you will need to use in the next request.

    {
    "txnId": "string"
    }
  2. Validate OTP

    Once you have the OTP, you can validate it with the following API:


    https://cdn-api.co-vin.in/api/v3/vaccination/confirmOTP

    The request body is a JSON object with the following properties:

    {
    "otp": "string",
    "txnId": "string"
    }

    The otp field is the OTP you received that has been SHA-256 encoded, and the txnId is the transaction ID you received in the previous request.

    If successful, you will receive a jwt-based bearer token, which you will need to use in the next request.

    {
    "token": "string"
    }
  3. Get Vaccination Status

    Once the authentication handshake is successfully validated, you can use the bearer token to get the vaccinationstatus of the person whose mobile number you used in the first request.


    https://cdn-api.co-vin.in/api/v3​/vaccination​/status

    The response body is a JSON object with the following properties:

    {
    "vaccination_status": "0/1/2"
    }

    The field vaccination_status can have only one of the following values:

    • 0: Not Vaccinated
    • 1: Partially Vaccinated
    • 2: Fully Vaccinated

Auth0 is where the Action is #

Custom Action: KYC-VS #

Now that we have the Postman Collection of the COWIN KYC-VS API, we can use it in Auth0. We will be creating a custom Auth0 Action to encapsulate the entire interaction with the COWIN KYC-VS API.

  1. Initially, we are going to make a call to the "generateOTP" method of the API, providing the mobile number and name of the person whose vaccination status we want to check.

    To do this, we are going to add "axios" as a dependency to make those HTTP calls.

    Axios is a promise-based HTTP client that works both in the browser and in a node.js environment. It basically provides a single API for dealing with XMLHttpRequests and node's http interface. Also, all the Auth0 Actions example have it as the HTTP client. So while in Rome.πŸ˜‰

    Auth0 Action editor showing the latest version of axios in the dependencies tab and require statement in the code tab

        const axios = require('axios');

    One of the great thing about the Auth0 Action editor is that it has a built-in Postman-like environment where you can test your code. This is a great developer productivity feature that shortens your dev feedback loop. Think about this..... the alternate would be logging in via a test app, and then checking the logs....been there, done that and it's so cumbersome.

    Auth0 Action editor showing the test tab with the event object pre-populated with dummy data

    Once you click on the Play icon on the top left [highlighted within the green box], then the Test Tab slides out with Event object pre-populated with dummy data, which you can edit.

    Clicking the Run button just below the Event object will execute the action and after a few seconds, the Test Results tab will pop out from the bottom to show the results of the execution. I have been quite liberal with the console.log statements so as to show the results of the execution.

    We can confirm from the Postman that the txnId is the same as the one that was sent.

    Postman Mock Server editor showing the generateotp payload and json

  2. Next up, we need to create a SHA-256 of the OTP.

    The eagle-eyed amongst you would have spotted that Auth0 Action has Node.js 16 as its runtime. That means, we can use the native crypto module to create the SHA-256 hash.

    Auth0 Action Editor

    After importing the crypto module [highlighted in red below], we can use the createHash method to create a SHA-256 hash of the OTP[highlighted in yellow]. We are then invoking the confirmOTP of the COWIN API with a payload that consists of the hashed OTP along with the transaction ID received in the previous step. In response, we get the JWT token.

    Auth0 Action Editor

    The hashed OTP is the same as the one that on COWIN API portal

    API Setu site

    Homework: Put on your sleuthing hat, and see if you can decrypt the hashed OTP to reverse engineer the COWIN_OTP secret I used.

  3. Finally, we use the JWT token to get the vaccination status of the person whose mobile number we used in the first step.

    Auth0 Action Editor

    The JWT token is sent as part of the Bearer token [highlighted in green]. Crucially, we store the vaccination status received as part of the payload, in the app metadata [highlighted in red]

    We are storing the vaccination data in the app metadata and not in the user metadata because the latter can be updated by the user, and thats not what we want.
    Auth0 docs

Market place Action: Yoonik Face Recognition #

The next step is to literally put a face to the vaccination status. Yoonik is a modular SaaS platform that brings Developer-first Face Authentication to any user on any device in minutes.

  1. You need to create a Yoonik account, and post-that, an API key. You will need to copy the API key and the accompanying API secret, to configure the Yoonik Auth0 Action in the next step.

  2. Next, we need to create a new Auth0 Action. We will be using the Yoonik Face Recognition action. Add the action to the Login Flow from the marketplace and then simply drag and drop it to the Flow editor. Follow the instruction in the Installation tab of the Yoonik Action in the Auth0 Marketplace to configure the action and you are in business. Its this simplicity of a mere drag & drop, and configuration to get an enterprise-grade Face Authentication that got me hooked. This is a great example of how you can use the Auth0 Action Marketplace to extend the functionality of your Auth0 tenant.

Auth0 Action editor with the Yoonik Auth0 Action highlighted

Codebase #

Time being of the essence in a hackathon, I had used the default Auth0 SPA Javascript quickstart project to showcase the whole solution. If you follow the instructions in the quickstart, you will have a working Auth0 tenant with a SPA application. You can either clone the GitHub repo or better still, download the project after logging in, and Auth0 will conveniently pre-fill up the auth_config.json file with the details of your Auth0 tenant.

If every thing went well, you should be able to see the following screen when you run the project.
Simple Login Page with the Auth0 logo and a Login button at the top right corner of the page

Next up, as mentioned in the Yoonik Auth0 Action installation instruction, you need to setup a custom application that implements the Yoonik Face Capture SDK. Yoonik have kindly provided a sample Python Flask application that does the same.

Assuming you have gone with the default port of 3031, you need to add that URI to the callback and logout URL of your application in the Auth0 dashboard.

Auth0 dashboard with the Yoonik Face Capture callback and logout URL underlined in red

Once click on the blue login button, you will be presented with the Auth0 Universal Login Box

Auth0 Universal Login Box

On a successful login, your browser will be redirected to the Yoonik Face Capture application.

Yoonik Face Capture Application with the Yoonik logo and "Take selfie" button just below it

On clicking the Take Selfie button, your browser will ask for permission to access your webcam.

Browser asking for permission to access the webcam

Once you grant the permission, you will be presented with a screen that will ask you to take a selfie.

Yoonik Face Capture streaming the webcam feed and the browser Developer Tools console is opened on the side

Perusing the browser console, you can glean that the Yoonik Face Capture application is loading the model, and attempting to detect a face. Once it detects a face, it will send the image to the Yoonik API for processing. If the image matches successfully with the one in the Yoonik database, you will be redirected to the Auth0 callback URL. If the image does not match, you will be presented with an error message.

Yoonik Face Capture error message

Yoonik Face Capture Application will present a successful message if the image matches with the one in the Yoonik database, and you will be presented with a link to proceed further.

Yoonik Face Capture success message

You can verify in the Auth0 portal from the user's app metadata that he/she has been successfully logged in via Yoonik, and their vaccination status has been updated.

Auth0 Dashboard with User Metadata and App Metadata highlighted

On the login page, the sample Auth0 SPA application will display the gravatar image of the the logged in user. If there is no picture associated with the user, it will display the initial of the user's name.

Auth0 JS Template successful login page with the gravatar image highlighted in red box and the browser

From a UX perspective, there is no indicator of the vaccination status of the user. And even if we wanted to display it, we can't because, as evident from the browser console, the Auth0 SPA Javascript SDK does not expose the app metadata to the client. Also, the app is configured in Auth0 dashboard for the ID token sent as a JWT payload to the client to be OIDC conformant; COVID vaccination status, while looming large over our life from 2021, is not part of the OIDC spec. Thats what we see in the browser console.

Auth0 dashboard with OAuth tab opened and the JWT fields and OIDC conformant toggle highlighted in red

We will enhance our custom Auth0 Action by adding a custom claim to the ID token [highlighted in red], and verify the test results[highlighted in yellow]

Auth0 Action Editor with the vaccination status added to the IDToken highlighted in red, and the results highlighted in yellow

If we re-login into the app, after deploying the action, the ID token will now have the vaccination status as a custom claim.

Auth0 Profile page with the vaccination status custom claim highlighted in red

On the index page we will add two Font Awesome syringes icon next to the user's profile image.

Index.html code with two added font awesome icon elements highlighted in red box

Then on the javascript side, we will get the vaccination status and toggle the visibility of the syringe icons based on the vaccination status.

UI.js code with vaccination status and syringe icon toggle highlighted

Voila! We now have a working Auth0 SPA application that can display the vaccination status of the user.

Auth0 SPA app showing two syringe icons next to user profile image

What about when the user has taken only a single vaccination dose? Let's modify the vaccination status in the Postman.

Postman editor showing the vaccination status set to 1

Re-login into the app, and you will see that there is only one syringe icon next to the user's profile image.

Auth0 SPA app showing a single syringe icon next to user profile image

Finally, what about when the user has not taken any vaccination dose? After modifying the vaccination status in Postman, re-logging into the app, and we see that there are no syringe icons next to the user's profile image.

Auth0 SPA app not showing any syringe icon next to the profile pic

Gotchas #

  1. One thing that ate a lot of crucial time during the hackathon was a Javascript bug that never cropped up when testing in the Action Editor.

    Auth0 Editor with testing result pane open from the bottomm

    So while testing in the editor it was working fine, but post deploying and using in the app, it was failing. Presently this bug is not manifesting with the Node 16 runtime.

  2. If you revert to a past version of an action and run the test in editor, it will still execute the previously deployed version of the action. Only if you make a change and save it, will it run the latest version of the action.`

πŸ™πŸ™πŸ™

Since you've made it this far, sharing this article on your favorite social media network would be highly appreciated πŸ’–! For feedback, please ping us on Twitter.

Published