How to Validate OKTA JWT Token in Express Js

Krishna KV
Technology Specialist
January 20, 2019
Rate this article
Views    5675

In my previous article, I have explained how to enable JWT based authentication in an Angular Application with OKTA. In this article, we can see how to validated the JWT Token (created with OKTA) in an Express Js Application and secure the API endpoints.

Let’s start creating a file named authentication.module.ts and perform the below activities.

Steps Covered

  • Whitelist the base URL in the configuration file.
  • Decode and Retrieve the Username & Email  from the token.
  • Validate the JWT Token against the Client ID.
  • Display the Base API Path information without authentication.
import * as express from 'express';
import { find } from 'lodash';
import { IConfig, AppSetting, Environment } from '../config';
import { Api } from './api';
const OktaJwtVerifier = require('@okta/jwt-verifier');
const jwtWeb = require('jsonwebtoken');
export class AuthenticationModule {

    public static isExcluded(req, res) {

        let config: IConfig = AppSetting.getConfig();

        let exclude = config.AppSettings['exclude'];
        let result = find(exclude, (s) => {

            return req.url.startsWith(s);
        });
        // To exclude authentication for swagger in dev mode
        let ref = req.headers['referer'] ? req.headers['referer'] : '';
        let testing = AppSetting.Env === Environment.Dev && ref.indexOf('swagger') !== -1;
        return testing || result;
    }

    public static authenticate(app: express.Express) {
        app.use(function (req, res, next) {
            let config = AppSetting.getConfig();
            let auth = req.headers['x-access-token'] || req.query['token'];
            if (req.url === '/') {
                return res.json({
                    name: config.AppConfig.name,
                    version: config.AppConfig.version,
                });
            } else if (AuthenticationModule.isExcluded(req, res)) {
                let userid = null;
                if (auth) {
                    let decode = jwtWeb.decode(auth);
                    userid = AuthenticationModule.setHeader(decode, req);
                    AuthenticationModule.validateOkta(config, auth, req, res, next);
                }
                next();
            } else {
                return Api.unauthorized(req, res, 'Invalid Token');
            }
        });

    }
    public static validateOkta(config: IConfig, token, req, res, next) {
        const oktaJwtVerifier = new OktaJwtVerifier({
            issuer: config.OktaConfig.url,
            assertClaims: {
                cid: config.OktaConfig.clientI
            }
        });
        oktaJwtVerifier.verifyAccessToken(token)
            .then(jwt => {
                let userid = AuthenticationModule.setHeader(jwt.claims, req);
                if (userid) {
                    next();
                } else {
                    Api.unauthorized(req, res, 'Invalid userId');
                }

            })
            .catch(err => {
                console.log('error', err);
                Api.unauthorized(req, res, err);
            });
    }

    private static setHeader(claims, req) {
        if (!claims) {
            return null;
        }
        let userid = claims ? claims.preferred_username : null;
        let email = claims ? claims.email : null;
        let name = claims ? claims.name : null;
        let id = userid.split('@');
        id = id ? id[0] : null;
        req.headers['user'] = id;
        req.headers['user-email'] = email;
        req.headers['user-name'] = name;
        return id;

    }
}

Include the authentication Module in expressApi.ts

private configureMiddleware() {
        this.app.use(json({ limit: '50mb' }));
        this.app.use(compression());
        this.app.use(urlencoded({ limit: '50mb', extended: true }));
        AuthenticationModule.authenticate(this.app);
        Logger.configureLogger(this.app);
    }

Update the values in the configuration files.

"appSettings": {
      "excludedUrl": [
        "info"
      ]
    },
    "oktaConfig": {
      "url": "https://dev-142636.oktapreview.com/oauth2/",
      "clientId": ""
    },

excludedUrl - used to view the API without authentication. 
url - The Okta URL for validating. 
clientId- The client id used in the Angular App. 

If you try to access the Base URL http://localhost:40401, it will display the API Information.  
{
"name": "express-api",
"version": "1.0.0"
}

http://localhost:40401/customers
It will display the error message 

{
"message": "Unauthorized",
"error": "Invalid Token"
}

How to pass the OKTA JWT token for authentication

Start the angular application and copy the token from network tab and use as below in the post man.

post man

Download the demo from GitHub

In the next article, we can look into how to auto refresh the token without expiration.

Subscribe To Our Newsletter
Loading

Leave a comment