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?
I'm submitting a ...
I confirm that I
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) => {
...
});
Version of the library: tsoa 2.5.3, tsoa-node 8.4.1
Version of NodeJS: 8.10.0
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);
...
}
Most helpful comment
I found a way to solve my issue:
I added the token in the header in this format:
Authorization: jwt-token-xxxxxxxxxxxxxand removed the 'Bearer'
Authorization: Bearer jwt-token-xxxxxxxxxxxxx