UNPKG

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