Open nakamorichi opened 8 years ago
Hi, It's a two step process. You'll first have to define in your swagger spec[1] how your endpoint is secured (via and api key for example) and then in your server code, you'll have to implement a security handler for it [2]. remember that Swagger doesn't explicitly know about JWT (JWT is just another way of encoding a token) so you'll have to teach it to work with it :)
You could use apiKey and name the header Authorization, which you can read as req.headers.authorization
from the req option of the security handler, extract the value, and parse it using a JWT library[1] and that's about it.
[1] http://swagger.io/specification/#securitySchemeObject [2] https://github.com/swagger-api/swagger-node/issues/228#issuecomment-163805253 [3] https://github.com/auth0/node-jsonwebtoken
This code worked for me
var ejwt = require('express-jwt');
// Initialize express-jwt
var jwt = ejwt({
secret: new Buffer(process.env.AUTH0_CLIENT_SECRET, 'base64'),
audience: process.env.AUTH0_CLIENT_ID
});
// Set up the token security handler
var config = {
appRoot: __dirname, // required config
swaggerSecurityHandlers: {
token: function(req, authOrSecDef, scopesOrApiKey, cb) {
jwt(req, req.res, function(err) {
if (req.user == undefined) {
return cb(new Error('access denied - user does not exist in auth0'));
}
else {
console.log(req.user); // Contains { iss: 'https://xxx.auth0.com/', sub: 'auth0|xxx', ... }
return cb(null);
}
}
}
}
};
@jlyon: thanks -- note for whoever follows this: there's a missing )
in the above pasted code to close off the jwt(…
block.
This is how we did it:
import * as fs from 'fs';
import * as path from 'path';
import * as swaggerTools from 'swagger-tools';
import * as passport from 'passport';
export function setupSwagger(app) {
// resolve the spec
const spath = path.resolve('./dist/spec.json');
const file = fs.readFileSync(spath, 'utf8');
const spec = JSON.parse(file);
// setup middleware swagger middleware in express
swaggerTools.initializeMiddleware(spec, (middleware) => {
app.use(middleware.swaggerUi());
app.use(middleware.swaggerMetadata());
app.use(setupSwaggerSecurity(middleware));
app.use(middleware.swaggerValidator({
validateResponse: true
}));
});
};
function setupSwaggerSecurity(middleware) {
return middleware.swaggerSecurity({
jwt_token: (req, authOrSecDef, scopes, callback) => {
passport.authenticate('jwt', { session: false }, (err, user, info) => {
if(err) callback(new Error('Error in passport authenticate'));
if(!user) callback(new Error('Failed to authenticate oAuth token'));
req.user = user;
return callback();
})(req, null, callback);
}
});
};
then in passport:
import * as config from 'config';
import * as passport from 'passport';
import { Strategy as JwtStrategy, ExtractJwt } from 'passport-jwt';
let opts = {
jwtFromRequest: ExtractJwt.fromAuthHeader(),
secretOrKey: config.get('auth.jwt_secret').toString()
};
function verify(payload, done) {
const id = payload.sub;
return id !== undefined;
/*
User.findOne({ id: jwt_payload.sub }, (err, user) => {
if (err) return done(err, false);
if (user) {
done(null, user);
} else {
done(null, false);
// or you could create a new account
}
});
*/
};
export function setupAuth(app) {
app.use(passport.initialize());
passport.use(new JwtStrategy(opts, verify));
};
Demo project here: https://github.com/swimlane/node-microservice-demo/tree/master/petstore
After generating a swagger-node project (in my case Hapi), how do I configure JWT authentication for the routes (preferably by using hapi-auth-jwt2 or similar plugin)? Also, what is the preferred way to handle route authorization?