Tsoa: Authentication with @Security('Auth0') from express-jwt

Created on 30 Sep 2019  路  1Comment  路  Source: lukeautry/tsoa


I wanted to implement authentication on my express API that is generated with tsoa. At the moment I'm using the express-jwt middleware in my old express API without tsoa. I get a JWT from Auth0.com.

Authentication needs to happen route specific an thus I followed the documentation and tried to use @Security() method.

express-jwt verifies if the Authorization: Bearer jwt-token-xxxxxxxxx (passed in request.headers) is valid AND sets the found user properties to req.user.

What's the best practice to implement jwt-token verification in tsoa coming from express-jwt?

Sorting

  • I'm submitting a ...

    • [X ] support request
  • I confirm that I

    • [X ] used the search to make sure that a similar issue hasn't already been submit

Expected Behavior

My old implementation looked like:

const jwt = require('express-jwt');
const jwksRsa = require('jwks-rsa'); 

 const checkJwt =  jwt({
        secret: jwksRsa.expressJwtSecret({
          cache: true,
          rateLimit: true,
          jwksRequestsPerMinute: 5,
          jwksUri: `https://xxxxxx.eu.auth0.com/.well-known/jwks.json`
        }),
        // Validate the audience and the issuer.
        audience: 'XXXXXXXX-XXXXXXX',
        issuer: `https://xxxxxx.eu.auth0.com/`,
        algorithms: ['RS256']
      });

// Route using checkJwt middleware
router.get('/:userId', checkJwt, async (req, res) => {
         ...
});

Context (Environment)

Version of the library: tsoa 2.5.3, tsoa-node 8.4.1
Version of NodeJS: 8.10.0

  • Confirm you were using yarn not npm: [ ] npm works on my machine Linux Ubuntu 18.04

Most helpful comment

I found a way to solve my issue:

I added the token in the header in this format:
Authorization: jwt-token-xxxxxxxxxxxxx
and removed the 'Bearer' Authorization: Bearer jwt-token-xxxxxxxxxxxxx

// Auth.ts
import * as express from 'express';
import * as jwt from 'jsonwebtoken';
import * as jwksRsa from 'jwks-rsa';

export function expressAuthentication(
  request: express.Request,
  securityName: string,
  scopes?: string[]
): Promise<any> {
  if (securityName === 'auth0') {
    const token = request.headers['authorization'];

    return new Promise((resolve, reject) => {
      if (!token) {
        reject(new Error('No token provided'));
      }

      var client = jwksRsa({
        cache: true,
        rateLimit: true,
        jwksRequestsPerMinute: 5,
        jwksUri: 'https://xxxxxx.eu.auth0.com/.well-known/jwks.json'
      });

      function getKey(header: any, callback: any) {
        client.getSigningKey(header.kid, function(err, key: any) {
          var signingKey = key.publicKey || key.rsaPublicKey;
          callback(null, signingKey);
        });
      }

      jwt.verify(token, getKey, function(err: any, decoded: any) {
        if (err) {
          reject(err);
        } else {
          if (decoded.aud != 'XXXXXXXX-XXXXXXX') {
            reject(new Error('JWT error'));
          }
          if (decoded.iss != 'https://xxxxxx.eu.auth0.com/') {
            reject(new Error('JWT error'));
          }
          resolve(decoded);
        }
      });
    });
  }
}
// Secure_Route_Controller.ts

@Route('/secure')
export class TodoController extends Controller {
  @Security('auth0')
  @Get()
  public async getAll(@Request() request: any): Promise<ITodo[]> {
    console.log(request.user);

      ...
  }

>All comments

I found a way to solve my issue:

I added the token in the header in this format:
Authorization: jwt-token-xxxxxxxxxxxxx
and removed the 'Bearer' Authorization: Bearer jwt-token-xxxxxxxxxxxxx

// Auth.ts
import * as express from 'express';
import * as jwt from 'jsonwebtoken';
import * as jwksRsa from 'jwks-rsa';

export function expressAuthentication(
  request: express.Request,
  securityName: string,
  scopes?: string[]
): Promise<any> {
  if (securityName === 'auth0') {
    const token = request.headers['authorization'];

    return new Promise((resolve, reject) => {
      if (!token) {
        reject(new Error('No token provided'));
      }

      var client = jwksRsa({
        cache: true,
        rateLimit: true,
        jwksRequestsPerMinute: 5,
        jwksUri: 'https://xxxxxx.eu.auth0.com/.well-known/jwks.json'
      });

      function getKey(header: any, callback: any) {
        client.getSigningKey(header.kid, function(err, key: any) {
          var signingKey = key.publicKey || key.rsaPublicKey;
          callback(null, signingKey);
        });
      }

      jwt.verify(token, getKey, function(err: any, decoded: any) {
        if (err) {
          reject(err);
        } else {
          if (decoded.aud != 'XXXXXXXX-XXXXXXX') {
            reject(new Error('JWT error'));
          }
          if (decoded.iss != 'https://xxxxxx.eu.auth0.com/') {
            reject(new Error('JWT error'));
          }
          resolve(decoded);
        }
      });
    });
  }
}
// Secure_Route_Controller.ts

@Route('/secure')
export class TodoController extends Controller {
  @Security('auth0')
  @Get()
  public async getAll(@Request() request: any): Promise<ITodo[]> {
    console.log(request.user);

      ...
  }
Was this page helpful?
0 / 5 - 0 ratings

Related issues

jeremyVignelles picture jeremyVignelles  路  3Comments

JimmyBjorklund picture JimmyBjorklund  路  5Comments

rustam-crunch picture rustam-crunch  路  5Comments

strongpauly picture strongpauly  路  3Comments

taicho picture taicho  路  5Comments