UNPKG

5.09 kBJavaScriptView Raw
1'use strict';
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.hasSubscribedApiAccess = hasSubscribedApiAccess;
7exports.useJwt = useJwt;
8
9var _jsonwebtoken = require('jsonwebtoken');
10
11var _jsonwebtoken2 = _interopRequireDefault(_jsonwebtoken);
12
13var _passport = require('passport');
14
15var _passport2 = _interopRequireDefault(_passport);
16
17var _passportJwt = require('passport-jwt');
18
19function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
20
21var DEFAULT_EXPIRY_TIME = 1000 * 60 * 60; // 1h
22
23function hasSubscribedApiAccess(scope, req, res, next, logger) {
24 _passport2.default.authenticate('jwt', { session: false }, function (err, user, info) {
25 if (err) {
26 logger.warn('error authenticating user', err);
27 return res.status(400).json({
28 error: 'Unexpected error validating your auth token',
29 errorCode: 'INVALID_JWT_TOKEN'
30 });
31 }
32 if (!user) {
33 logger.warn('JWT didnt match any user (invalid?)', info);
34 return res.status(401).json({
35 error: 'Auth token invalid or expired',
36 errorCode: 'INVALID_JWT_TOKEN'
37 });
38 }
39 if (scope === 'admin') {
40 if (!user.admin) {
41 logger.warn('requested admin scope, but user was not admin:', user);
42 return res.status(401).json({
43 error: 'Requires additional privileges'
44 });
45 }
46 if (!user.active) {
47 logger.warn('requested active scope, but user was not active:', user);
48 return res.status(401).json({
49 error: 'Requires additional privileges'
50 });
51 }
52 }
53 if (scope === 'active') {
54 if (!user.active) {
55 logger.warn('requested active scope, but user was not active:', user);
56 return res.status(401).json({
57 error: 'Requires additional privileges'
58 });
59 }
60 }
61 req.user = user;
62 next();
63 })(req, res, next);
64}
65
66function useJwt(app, config) {
67 // unpack
68 var db = config.db,
69 jwtSecret = config.jwtSecret,
70 localAuthenticate = config.localAuthenticate,
71 routePath = config.routePath;
72
73 var usersCollection = db.collection('users');
74
75 // JWT creator
76 function createJWTforUser(user) {
77 var expiry = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Date.now() + DEFAULT_EXPIRY_TIME;
78
79 if (!user) {
80 return null;
81 }
82 return {
83 token: _jsonwebtoken2.default.sign({
84 // we only need to keep the fields necessary to asses privilege level
85 user: {
86 id: user.id,
87 email: user.email,
88 active: user.active,
89 admin: user.admin
90 },
91 // jwt uses seconds, not ms
92 exp: Math.round(expiry / 1000)
93 }, jwtSecret),
94 expiry: expiry
95 };
96 }
97 // strategy
98 var localJwtStrategy = new _passportJwt.Strategy({
99 jwtFromRequest: _passportJwt.ExtractJwt.fromAuthHeader(),
100 secretOrKey: jwtSecret
101 }, function (jwtPayload, next) {
102 next(null, jwtPayload.user);
103 return;
104 });
105 // use
106 _passport2.default.use(localJwtStrategy);
107 // api auth token
108 var jwtAuthenticate = function jwtAuthenticate(req, res, next) {
109 var user = req.user;
110 var _req$body = req.body,
111 email = _req$body.email,
112 isJwtNext = _req$body.isJwtNext;
113
114 if (!user) {
115 res.status(401).json({ error: 'You need to be logged in.' });
116 return;
117 }
118 if (!email) {
119 return res.status(400).json({
120 error: 'Email required'
121 });
122 }
123 // NOTE: assumption that user used local sign up
124 usersCollection.findOne({ 'local.email': email }).then(function (matchedUser) {
125 if (!matchedUser) {
126 return res.status(400).json({
127 error: 'No authorised user'
128 });
129 }
130
131 var _createJWTforUser = createJWTforUser({
132 active: matchedUser.active,
133 admin: matchedUser.admin,
134 id: matchedUser.id,
135 email: email
136 }),
137 token = _createJWTforUser.token,
138 expiry = _createJWTforUser.expiry;
139
140 var json = {
141 authToken: token,
142 authTokenExpiry: expiry
143 };
144 if (isJwtNext) {
145 // Object.assign(req.body, json)
146 req.headers.authorization = 'JWT ' + token;
147 next();
148 } else {
149 res.json(json);
150 }
151 return;
152 });
153 };
154 // apis
155 // NOTE: authenticate api we rely on having req.user available here,
156 // to only grant new auth token if the posted email belongs to the logged in user.
157 // This means we can currently not renew api auth tokens outside of the specific domain
158 // this server lives on.
159 app.post(routePath + '/authenticate', jwtAuthenticate);
160 // token api needs to have email and password credentials
161 if (localAuthenticate) {
162 app.post(routePath + '/token', localAuthenticate, function (req, res, next) {
163 if (req.user) {
164 console.log('req.body', req.body);
165 next();
166 } else {
167 res.json({ error: 'not a valid user' });
168 }
169 }, jwtAuthenticate);
170 }
171 return { createJWTforUser: createJWTforUser,
172 jwtAuthenticate: jwtAuthenticate
173 };
174}
\No newline at end of file