JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 3
  • Score
    100M100P100Q45148F
  • License MIT

Passport authentication strategy using JSON Web Tokens

Package Exports

  • passport-auth-jwt

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (passport-auth-jwt) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

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