1.0.22 • Published 9 years ago

passport-auth-jwt v1.0.22

Weekly downloads
1
License
MIT
Repository
github
Last release
9 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

9 years ago

1.0.21

10 years ago

1.0.20

10 years ago

1.0.19

10 years ago

1.0.17

10 years ago

1.0.16

10 years ago

1.0.15

10 years ago

1.0.12

10 years ago

1.0.11

10 years ago

1.0.10

10 years ago

1.0.9

10 years ago

1.0.8

10 years ago

1.0.7

10 years ago

1.0.6

10 years ago

1.0.5

10 years ago

1.0.3

10 years ago

1.0.1

10 years ago

1.0.0

10 years ago

2.0.0

10 years ago