1 | var jwt = require('jsonwebtoken');
|
2 | var assert = require('assert');
|
3 |
|
4 | var expressjwt = require('../lib');
|
5 | var UnauthorizedError = require('../lib/errors/UnauthorizedError');
|
6 |
|
7 | describe('failure tests', function () {
|
8 | var req = {};
|
9 | var res = {};
|
10 |
|
11 | it('should throw if options not sent', function() {
|
12 | try {
|
13 | expressjwt();
|
14 | } catch(e) {
|
15 | assert.ok(e);
|
16 | assert.equal(e.message, 'secret should be set');
|
17 | }
|
18 | });
|
19 |
|
20 | it('should throw if no authorization header and credentials are required', function() {
|
21 | expressjwt({secret: 'shhhh', credentialsRequired: true})(req, res, function(err) {
|
22 | assert.ok(err);
|
23 | assert.equal(err.code, 'credentials_required');
|
24 | });
|
25 | });
|
26 |
|
27 | it('support unless skip', function() {
|
28 | req.originalUrl = '/index.html';
|
29 | expressjwt({secret: 'shhhh'}).unless({path: '/index.html'})(req, res, function(err) {
|
30 | assert.ok(!err);
|
31 | });
|
32 | });
|
33 |
|
34 | it('should skip on CORS preflight', function() {
|
35 | var corsReq = {};
|
36 | corsReq.method = 'OPTIONS';
|
37 | corsReq.headers = {
|
38 | 'access-control-request-headers': 'sasa, sras, authorization'
|
39 | };
|
40 | expressjwt({secret: 'shhhh'})(corsReq, res, function(err) {
|
41 | assert.ok(!err);
|
42 | });
|
43 | });
|
44 |
|
45 | it('should throw if authorization header is malformed', function() {
|
46 | req.headers = {};
|
47 | req.headers.authorization = 'wrong';
|
48 | expressjwt({secret: 'shhhh'})(req, res, function(err) {
|
49 | assert.ok(err);
|
50 | assert.equal(err.code, 'credentials_bad_format');
|
51 | });
|
52 | });
|
53 |
|
54 | it('should throw if authorization header is not Bearer', function() {
|
55 | req.headers = {};
|
56 | req.headers.authorization = 'Basic foobar';
|
57 | expressjwt({secret: 'shhhh'})(req, res, function(err) {
|
58 | assert.ok(err);
|
59 | assert.equal(err.code, 'credentials_bad_scheme');
|
60 | });
|
61 | });
|
62 |
|
63 | it('should next if authorization header is not Bearer and credentialsRequired is false', function() {
|
64 | req.headers = {};
|
65 | req.headers.authorization = 'Basic foobar';
|
66 | expressjwt({secret: 'shhhh', credentialsRequired: false})(req, res, function(err) {
|
67 | assert.ok(typeof err === 'undefined');
|
68 | });
|
69 | });
|
70 |
|
71 | it('should throw if authorization header is not well-formatted jwt', function() {
|
72 | req.headers = {};
|
73 | req.headers.authorization = 'Bearer wrongjwt';
|
74 | expressjwt({secret: 'shhhh'})(req, res, function(err) {
|
75 | assert.ok(err);
|
76 | assert.equal(err.code, 'invalid_token');
|
77 | });
|
78 | });
|
79 |
|
80 | it('should throw if jwt is an invalid json', function() {
|
81 | req.headers = {};
|
82 | req.headers.authorization = 'Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.yJ1c2VybmFtZSI6InNhZ3VpYXIiLCJpYXQiOjE0NzEwMTg2MzUsImV4cCI6MTQ3MzYxMDYzNX0.foo';
|
83 | expressjwt({secret: 'shhhh'})(req, res, function(err) {
|
84 | assert.ok(err);
|
85 | assert.equal(err.code, 'invalid_token');
|
86 | });
|
87 | });
|
88 |
|
89 | it('should throw if authorization header is not valid jwt', function() {
|
90 | var secret = 'shhhhhh';
|
91 | var token = jwt.sign({foo: 'bar'}, secret);
|
92 |
|
93 | req.headers = {};
|
94 | req.headers.authorization = 'Bearer ' + token;
|
95 | expressjwt({secret: 'different-shhhh'})(req, res, function(err) {
|
96 | assert.ok(err);
|
97 | assert.equal(err.code, 'invalid_token');
|
98 | assert.equal(err.message, 'invalid signature');
|
99 | });
|
100 | });
|
101 |
|
102 | it('should throw if audience is not expected', function() {
|
103 | var secret = 'shhhhhh';
|
104 | var token = jwt.sign({foo: 'bar', aud: 'expected-audience'}, secret);
|
105 |
|
106 | req.headers = {};
|
107 | req.headers.authorization = 'Bearer ' + token;
|
108 | expressjwt({secret: 'shhhhhh', audience: 'not-expected-audience'})(req, res, function(err) {
|
109 | assert.ok(err);
|
110 | assert.equal(err.code, 'invalid_token');
|
111 | assert.equal(err.message, 'jwt audience invalid. expected: not-expected-audience');
|
112 | });
|
113 | });
|
114 |
|
115 | it('should throw if token is expired', function() {
|
116 | var secret = 'shhhhhh';
|
117 | var token = jwt.sign({foo: 'bar', exp: 1382412921 }, secret);
|
118 |
|
119 | req.headers = {};
|
120 | req.headers.authorization = 'Bearer ' + token;
|
121 | expressjwt({secret: 'shhhhhh'})(req, res, function(err) {
|
122 | assert.ok(err);
|
123 | assert.equal(err.code, 'invalid_token');
|
124 | assert.equal(err.inner.name, 'TokenExpiredError');
|
125 | assert.equal(err.message, 'jwt expired');
|
126 | });
|
127 | });
|
128 |
|
129 | it('should throw if token issuer is wrong', function() {
|
130 | var secret = 'shhhhhh';
|
131 | var token = jwt.sign({foo: 'bar', iss: 'http://foo' }, secret);
|
132 |
|
133 | req.headers = {};
|
134 | req.headers.authorization = 'Bearer ' + token;
|
135 | expressjwt({secret: 'shhhhhh', issuer: 'http://wrong'})(req, res, function(err) {
|
136 | assert.ok(err);
|
137 | assert.equal(err.code, 'invalid_token');
|
138 | assert.equal(err.message, 'jwt issuer invalid. expected: http://wrong');
|
139 | });
|
140 | });
|
141 |
|
142 | it('should use errors thrown from custom getToken function', function() {
|
143 | var secret = 'shhhhhh';
|
144 | var token = jwt.sign({foo: 'bar'}, secret);
|
145 |
|
146 | function getTokenThatThrowsError() {
|
147 | throw new UnauthorizedError('invalid_token', { message: 'Invalid token!' });
|
148 | }
|
149 |
|
150 | expressjwt({
|
151 | secret: 'shhhhhh',
|
152 | getToken: getTokenThatThrowsError
|
153 | })(req, res, function(err) {
|
154 | assert.ok(err);
|
155 | assert.equal(err.code, 'invalid_token');
|
156 | assert.equal(err.message, 'Invalid token!');
|
157 | });
|
158 | });
|
159 |
|
160 |
|
161 | it('should throw error when signature is wrong', function() {
|
162 | var secret = "shhh";
|
163 | var token = jwt.sign({foo: 'bar', iss: 'http://www'}, secret);
|
164 |
|
165 | var newContent = new Buffer("{foo: 'bar', edg: 'ar'}").toString('base64');
|
166 | var splitetToken = token.split(".");
|
167 | splitetToken[1] = newContent;
|
168 | var newToken = splitetToken.join(".");
|
169 |
|
170 |
|
171 | req.headers = [];
|
172 | req.headers.authorization = 'Bearer ' + newToken;
|
173 | expressjwt({secret: secret})(req,res, function(err) {
|
174 | assert.ok(err);
|
175 | assert.equal(err.code, 'invalid_token');
|
176 | assert.equal(err.message, 'invalid token');
|
177 | });
|
178 | });
|
179 |
|
180 | it('should throw error if token is expired even with when credentials are not required', function() {
|
181 | var secret = 'shhhhhh';
|
182 | var token = jwt.sign({foo: 'bar', exp: 1382412921}, secret);
|
183 |
|
184 | req.headers = {};
|
185 | req.headers.authorization = 'Bearer ' + token;
|
186 | expressjwt({ secret: secret, credentialsRequired: false })(req, res, function(err) {
|
187 | assert.ok(err);
|
188 | assert.equal(err.code, 'invalid_token');
|
189 | assert.equal(err.message, 'jwt expired');
|
190 | });
|
191 | });
|
192 |
|
193 | it('should throw error if token is invalid even with when credentials are not required', function() {
|
194 | var secret = 'shhhhhh';
|
195 | var token = jwt.sign({foo: 'bar', exp: 1382412921}, secret);
|
196 |
|
197 | req.headers = {};
|
198 | req.headers.authorization = 'Bearer ' + token;
|
199 | expressjwt({ secret: "not the secret", credentialsRequired: false })(req, res, function(err) {
|
200 | assert.ok(err);
|
201 | assert.equal(err.code, 'invalid_token');
|
202 | assert.equal(err.message, 'invalid signature');
|
203 | });
|
204 | });
|
205 |
|
206 | });
|
207 |
|
208 | describe('work tests', function () {
|
209 | var req = {};
|
210 | var res = {};
|
211 |
|
212 | it('should work if authorization header is valid jwt', function() {
|
213 | var secret = 'shhhhhh';
|
214 | var token = jwt.sign({foo: 'bar'}, secret);
|
215 |
|
216 | req.headers = {};
|
217 | req.headers.authorization = 'Bearer ' + token;
|
218 | expressjwt({secret: secret})(req, res, function() {
|
219 | assert.equal('bar', req.user.foo);
|
220 | });
|
221 | });
|
222 |
|
223 | it('should work with nested properties', function() {
|
224 | var secret = 'shhhhhh';
|
225 | var token = jwt.sign({foo: 'bar'}, secret);
|
226 |
|
227 | req.headers = {};
|
228 | req.headers.authorization = 'Bearer ' + token;
|
229 | expressjwt({secret: secret, requestProperty: 'auth.token'})(req, res, function() {
|
230 | assert.equal('bar', req.auth.token.foo);
|
231 | });
|
232 | });
|
233 |
|
234 | it('should work if authorization header is valid with a buffer secret', function() {
|
235 | var secret = new Buffer('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', 'base64');
|
236 | var token = jwt.sign({foo: 'bar'}, secret);
|
237 |
|
238 | req.headers = {};
|
239 | req.headers.authorization = 'Bearer ' + token;
|
240 | expressjwt({secret: secret})(req, res, function() {
|
241 | assert.equal('bar', req.user.foo);
|
242 | });
|
243 | });
|
244 |
|
245 | it('should set userProperty if option provided', function() {
|
246 | var secret = 'shhhhhh';
|
247 | var token = jwt.sign({foo: 'bar'}, secret);
|
248 |
|
249 | req.headers = {};
|
250 | req.headers.authorization = 'Bearer ' + token;
|
251 | expressjwt({secret: secret, userProperty: 'auth'})(req, res, function() {
|
252 | assert.equal('bar', req.auth.foo);
|
253 | });
|
254 | });
|
255 |
|
256 | it('should work if no authorization header and credentials are not required', function() {
|
257 | req = {};
|
258 | expressjwt({ secret: 'shhhh', credentialsRequired: false })(req, res, function(err) {
|
259 | assert(typeof err === 'undefined');
|
260 | });
|
261 | });
|
262 |
|
263 | it('should not work if no authorization header', function() {
|
264 | req = {};
|
265 | expressjwt({ secret: 'shhhh' })(req, res, function(err) {
|
266 | assert(typeof err !== 'undefined');
|
267 | });
|
268 | });
|
269 |
|
270 | it('should work with a custom getToken function', function() {
|
271 | var secret = 'shhhhhh';
|
272 | var token = jwt.sign({foo: 'bar'}, secret);
|
273 |
|
274 | req.headers = {};
|
275 | req.query = {};
|
276 | req.query.token = token;
|
277 |
|
278 | function getTokenFromQuery(req) {
|
279 | return req.query.token;
|
280 | }
|
281 |
|
282 | expressjwt({
|
283 | secret: secret,
|
284 | getToken: getTokenFromQuery
|
285 | })(req, res, function() {
|
286 | assert.equal('bar', req.user.foo);
|
287 | });
|
288 | });
|
289 |
|
290 | it('should work with a secretCallback function that accepts header argument', function() {
|
291 | var secret = 'shhhhhh';
|
292 | var secretCallback = function(req, headers, payload, cb) {
|
293 | assert.equal(headers.alg, 'HS256');
|
294 | assert.equal(payload.foo, 'bar');
|
295 | process.nextTick(function(){ return cb(null, secret) });
|
296 | }
|
297 | var token = jwt.sign({foo: 'bar'}, secret);
|
298 |
|
299 | req.headers = {};
|
300 | req.headers.authorization = 'Bearer ' + token;
|
301 | expressjwt({secret: secretCallback})(req, res, function() {
|
302 | assert.equal('bar', req.user.foo);
|
303 | });
|
304 | });
|
305 | });
|