1.0.22 • Published 8 years ago

passport-auth-jwt v1.0.22

Weekly downloads
1
License
MIT
Repository
github
Last release
8 years ago

passport-auth-jwt

A Passport strategy for authenticating with a JSON Web Token.

This module lets you authenticate endpoints using a JSON web token. It is intended to be used to secure RESTful endpoints without sessions.

Install

npm install passport-auth-jwt

Usage

Sorry this is a personal library for locking my system. And I to open the handler requirements.

The flow

User <-> Device <-> Provider

Note:

  • User This is your user
  • Device This is your application/website
  • Provider This is your system, RESTful endpoint

Configure

/**
* Config
*/
var passport = require('passport');
var passportAuthJWT = require('passport-auth-jwt');
config.passport.hook = require('./helper/auth-jwt-hook');
var PassportMoney = new passportAuthJWT(config.passport);
passport.use(PassportMoney.strategy());
// config.passport

{
			clientId: 'client_id',
			extractJwtOpts: {
				authScheme: 'AuthJWT',
				tokenBodyField: 'access_token',
				tokenQueryParameterName: 'access_token'
			},
			requestTokenEndpoint: '/auth/request-token',
			refreshTokenEndpoint: '/auth/refresh-token',
			tokenEndpoint: '/auth/token',
			ignoreRequestTokenUrl: ['/'],
			secret: '5f2c6556-2483-4254-a0e6-d8aec4069caa',
			accessTokenExpire: 7 * 86400, // 7 days = 7 * 24 * 3600;
			refreshTokenExpire: 10 * 365 * 86400, // 10 year
			requestTokenExpire: 3600 // 1h
		}
// ./helper/auth-jwt-hook

'use strict';

const mongoose = require('mongoose');
const uuid = require('node-uuid');
const jwt = require('jsonwebtoken');
const async = require('async');
const moment = require('moment');
const _ = require('lodash');

const PassportError = function (done, err) {
	if (err) {
		console.log(err);
	}

	return done({error: err}, false);
};

const ClientSchema = mongoose.model('ClientKey');
const UserSchema = mongoose.model('User');
const RefreshTokenSchema = mongoose.model('RefreshToken');

const Error = require('../config/error');

// restify get path;
var getPath = function (req) {
	return req.route ? req.route.path : req.path;
};

var urlRequireForRequestToken = ['/auth/token', '/facebook-register', '/google-register', '/register', '/forgot-password'];

var AuthJWTHook = {
	verify: function (config) {
		return function (req, jwt_payload, done) {
			console.log('payload', jwt_payload);

			// Logic
			if (req.authenticate.client === jwt_payload.client_id) {
				switch (jwt_payload.type) {
					case 'request-token':
						AuthJWTHook._verifyRequestToken(req, jwt_payload, done, config);
						break;
					case 'refresh-token':
						AuthJWTHook._verifyRefreshToken(req, jwt_payload, done, config);
						break;
					case 'access-token':
						done(null, jwt_payload);
						break;
					default:
						PassportError(done);
				}
			} else {
				PassportError(done);
			}
		}
	},

	// Set userId to req
	passportCallback: function (req, res, next) {
		return function (err, user, info) {
			if (user) {
				req.userId = user.userId;
				next();
			} else {
				next(err || info);
			}
		};
	},

	requestTokenCallback: function (req, res, next) {
		return function (error, token) {
			res.send(token);
		}
	},

	/*
	 more in req
	 req.authenticate = {
	 client: '14235l4tjgksdsjdlkfs',
	 secret: '3o432492rjfksdfjslkdfjsdkl'
	 };

	 */
	generateRequestToken: function (req, res, next, config) {
		var clientInfo = req.authenticate;

		ClientSchema.findOne({
			client: clientInfo.client,
			secret: clientInfo.secret,
			isDisabled: false
		}, function (error, client) {
			if (client) {
				var token = AuthJWTHook._generateJWTToken(
					'request-token', config.secret, `${config.requestTokenExpire}s`, {
						clientId: client._id,
						client_id: client.client
					}
				);
				res.send({status: true, request_token: token});
			} else {
				res.send({
					status: false,
					message: Error['OAUTH_ERROR_CLIENT_SECRET_NOT_VALIDATE']
				});
			}
		});
	},

	generateAccessToken: function (req, res, next, config) {
		// Logic for generate token
		return function (error, tokenInfo) {
			if (tokenInfo && tokenInfo.type === 'request-token') {
				var client_id = tokenInfo.client_id;
				var clientId = tokenInfo.clientId;
				var postData = req.body;

				AuthJWTHook._login(clientId, client_id, postData, config, function (error, data) {
					if (error) {
						res.send({
							status: false,
							message: error
						});
					} else {
						res.send({
							status: true,
							access_token: data.access_token,
							expire: data.expire,
							refresh_token: data.refresh_token
						});
					}
				});
			} else {

				res.send({
					status: false,
					message: Error['OAUTH_ERROR_CLIENT_SECRET_NOT_VALIDATE']
				});
			}
		};
	},

	generateRefreshToken: function (req, res, next, config) {
		return function (error, tokenInfo) {
			if (tokenInfo && tokenInfo.type === 'refresh-token') {
				AuthJWTHook._generateToken(
					tokenInfo.clientId,
					tokenInfo.client_id,
					tokenInfo.userId,
					config.secret,
					tokenInfo.key,
					config,
					function (error, results) {
						if (error) {
							res.send({
								status: false,
								message: Error['']
							});
						} else {
							res.send({
								status: true,
								access_token: results.access_token.token,
								expire: results.access_token.expire,
								refresh_token: results.refresh_token
							});
						}
					},
					tokenInfo.deviceKey
				);
			} else {
				res.send({
					status: false,
					message: Error['OAUTH_ERROR_CLIENT_SECRET_NOT_VALIDATE']
				});
			}
		};
	},

	_generateToken: function (clientId, client_id, userId, secret, key, config, callback, deviceKey) {
		async.parallel({
			refresh_token: function (callback) {
				AuthJWTHook._createRefreshToken(
					clientId, client_id, userId, secret, config, callback, deviceKey
				);
			},
			access_token: function (callback) {
				AuthJWTHook._createAccessToken(
					clientId, client_id, userId, secret, config, callback, deviceKey
				);
			},
			clean_refresh_token: function (callback) {
				if (key) {
					AuthJWTHook._cleanRefreshToken(key, callback);
				} else {
					callback(null, true);
				}
			}
		}, callback);
	},

	_createRefreshToken: function (clientId, client_id, userId, secret, config, callback, deviceKey) {
		var key = uuid.v4();

		var token = AuthJWTHook._generateJWTToken('refresh-token', secret, `${config.refreshTokenExpire}s`, {
			clientId: clientId,
			client_id: client_id,
			userId: userId,
			key: key,
			deviceKey: deviceKey
		});

		// logic more...
	},

	_cleanRefreshToken: function (key, callback) {
		// Logic for clean refresh token

	},

	_createAccessToken: function (clientId, client_id, userId, secret, config, callback, deviceKey) {
		var attachInfo = {
			clientId: clientId,
			client_id: client_id,
			userId: userId,
			code: deviceKey
		};

		var token = AuthJWTHook._generateJWTToken('access-token', secret, `${config.accessTokenExpire}s`, attachInfo);

		callback(null, {
			token: token,
			expire: AuthJWTHook._getExpire(config.accessTokenExpire)
		});
	},

	_verifyRequestToken: function (req, jwt_payload, done, config) {
		if (urlRequireForRequestToken.indexOf(getPath(req)) > -1) {
			done(null, jwt_payload);
		} else {
			PassportError(done);
		}
	},

	_verifyRefreshToken: function (req, jwt_payload, done, config) {
		// Valid refresh token

		console.log('OK');

		if (config.refreshTokenEndpoint === getPath(req) && jwt_payload.deviceKey) {
			// Logic for verufy refresh token
		} else {
			console.log(error);
			PassportError(done, error);
		}
	},

	_generateJWTToken: function (type, secret, expire, extraData) {
		extraData = extraData || {};

		var token_payload = {
			type: type,
			code: uuid.v4()
		};

		token_payload = Object.assign(token_payload, extraData);

		return jwt.sign(token_payload, secret, {
			expiresIn: expire
		});
	},

	_getExpire: function (day) {
		return moment().add(day, 's').format('X');
	},

	_login: function (clientId, client_id, postData, config, callback) {
		// Login function....
		AuthJWTHook._generateToken(...)
	}
};

module.exports = AuthJWTHook;

Authenticate requests

Use PassportMoney.authenticate() specifying 'JWT' as the strategy.

app.post('/profile', PassportMoney.authenticate({ session: false}),
    function(req, res) {
        res.send(req.user.profile);
    }
);

If you have any questions please create issues on Github. I will try to help

1.0.22

8 years ago

1.0.21

8 years ago

1.0.20

8 years ago

1.0.19

8 years ago

1.0.17

8 years ago

1.0.16

8 years ago

1.0.15

8 years ago

1.0.12

8 years ago

1.0.11

8 years ago

1.0.10

8 years ago

1.0.9

8 years ago

1.0.8

8 years ago

1.0.7

8 years ago

1.0.6

8 years ago

1.0.5

8 years ago

1.0.3

8 years ago

1.0.1

8 years ago

1.0.0

8 years ago

2.0.0

8 years ago