hapi-auth-jwt2
Advanced tools
| var test = require('tape'); | ||
| var JWT = require('jsonwebtoken'); | ||
| var secret = 'NeverShareYourSecret'; | ||
| var server = require('./basic_server'); // test server which in turn loads our module | ||
| test("Attempt to access restricted content (without auth token)", function(t) { | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado" | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 401, "No Token should fail"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Attempt to access restricted content (with an INVALID Token)", function(t) { | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { authorization: "Bearer fails.validation" } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 401, "INVALID Token should fail"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Malformed JWT", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| // var token = jwt.sign({ "id": 1 ,"name":"Old Greg" }, 'incorrectSecret'); | ||
| // console.log(token); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { authorization: "Bearer my.invalid.token" } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| // console.log(response.result); | ||
| // console.log(' '); // blank line | ||
| t.equal(response.statusCode, 401, "INVALID Token should fail"); | ||
| // t.equal(JSON.parse(response.result).msg, 'Invalid Token', "INVALID Token should fail"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Try using a token with missing characters in body", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| // delete some characters in body | ||
| var tokenData = token.split('.'); | ||
| var header = tokenData[0], | ||
| body = tokenData[1], | ||
| signature = tokenData[2]; | ||
| token = header + '.' + body.substring(0, body.length - 1) + '.' + signature; | ||
| /*console.log(" - - - - - - token - - - - -"); | ||
| console.log(token);*/ | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 401, "INVALID Token should fail"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Try using an incorrect secret to sign the JWT", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, 'incorrectSecret'); | ||
| // console.log(" - - - - - - token - - - - -") | ||
| // console.log(token); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 401, "Token signed with incorrect key fails"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| // see: https://github.com/dwyl/hapi-auth-jwt2/issues/166 | ||
| // test.only("Try using an expired token", function(t) { | ||
| // // use the token as the 'authorization' header in requests | ||
| // var token = JWT.sign({ id: 123, "name": "Charlie" }, secret, { expiresInSeconds: 1 }); | ||
| // console.log(" - - - - - - token - - - - -") | ||
| // console.log(token); | ||
| // var options = { | ||
| // method: "POST", | ||
| // url: "/privado", | ||
| // headers: { authorization: "Bearer " + token } | ||
| // }; | ||
| // // server.inject lets us simulate an http request | ||
| // setTimeout(function () { | ||
| // server.inject(options, function(response) { | ||
| // t.equal(response.statusCode, 401, "Expired token should be invalid"); | ||
| // t.equal(response.result.message, 'Token expired', 'Message should be "Token expired"'); | ||
| // t.end(); | ||
| // }); | ||
| // }, 1000); | ||
| // }); | ||
| test("Token is well formed but is allowed=false so should be denied", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| // var token = jwt.sign({ "id": 1 ,"name":"Old Greg" }, 'incorrectSecret'); | ||
| var token = JWT.sign({ id: 321, "name": "Old Gregg" }, secret); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 401, "Denied"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Access restricted content (with VALID Token)", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| // console.log(" - - - - RESPONSE: ") | ||
| // console.log(response.result); | ||
| t.equal(response.statusCode, 200, "VALID Token should succeed!"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Access restricted content (with Well-formed but invalid Token)", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, 'badsecret'); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| // console.log(" - - - - RESPONSE: ") | ||
| // console.log(response.result); | ||
| t.equal(response.statusCode, 401, "InVALID Token should Error!"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| // see: https://github.com/ideaq/hapi-auth-jwt2/issues/28 | ||
| test("Request with undefined auth header should 401", function(t) { | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { authorization: "Bearer " } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| // console.log(" - - - - RESPONSE: ") | ||
| // console.log(response.result); | ||
| t.equal(response.statusCode, 401, "InVALID Token fails (as expected)!"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Auth mode 'required' should require authentication header", function(t) { | ||
| var options = { | ||
| method: "POST", | ||
| url: "/required" | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 401, "No token header should fail in auth 'required' mode"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Auth mode 'required' should fail with invalid token", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, 'badsecret'); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/required", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| // console.log(" - - - - RESPONSE: ") | ||
| // console.log(response.result); | ||
| t.equal(response.statusCode, 401, "Invalid token should error!"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Auth mode 'required' should should pass with valid token", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/required", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| // console.log(" - - - - RESPONSE: ") | ||
| // console.log(response.result); | ||
| t.equal(response.statusCode, 200, "Valid token should succeed!"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Auth mode 'optional' should pass when no auth header specified", function(t) { | ||
| var options = { | ||
| method: "POST", | ||
| url: "/optional" | ||
| }; | ||
| server.inject(options, function(response) { | ||
| // console.log(" - - - - RESPONSE: ") | ||
| // console.log(response.result); | ||
| t.equal(response.statusCode, 200, "No auth header should pass in optional mode!"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Auth mode 'optional' should fail with invalid token", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, 'badsecret'); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/optional", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| // console.log(" - - - - RESPONSE: ") | ||
| // console.log(response.result); | ||
| t.equal(response.statusCode, 401, "Invalid token should error!"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Auth mode 'optional' should pass with valid token", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| // var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/optional", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| // console.log(" - - - - RESPONSE: ") | ||
| // console.log(response.result); | ||
| t.equal(response.statusCode, 200, "Valid token should succeed!"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Auth mode 'try' should pass when no auth header specified", function(t) { | ||
| var options = { | ||
| method: "POST", | ||
| url: "/try" | ||
| }; | ||
| server.inject(options, function(response) { | ||
| // console.log(" - - - - RESPONSE: ") | ||
| // console.log(response.result); | ||
| t.equal(response.statusCode, 200, "No auth header should pass in 'try' mode!"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Auth mode 'try' should pass with invalid token", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, 'badsecret'); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/try", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| // console.log(" - - - - RESPONSE: ") | ||
| // console.log(response.result); | ||
| t.equal(response.statusCode, 200, "Invalid token should pass in 'try' mode"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Auth mode 'try' should pass with valid token", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/try", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| // console.log(" - - - - RESPONSE: ") | ||
| // console.log(response); | ||
| t.equal(response.statusCode, 200, "Valid token should succeed!"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Scheme should set token in request.auth.token", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| var options = { | ||
| method: "GET", | ||
| url: "/token", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| // console.log(" - - - - RESPONSE: ") | ||
| // console.log(response.result); | ||
| t.equal(response.result, token, 'Token is accesible from handler'); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test.onFinish(function () { | ||
| server.stop(function(){}); | ||
| }) |
| var test = require('tape'); | ||
| var Hapi = require('hapi'); | ||
| var JWT = require('jsonwebtoken'); | ||
| var secret = 'NeverShareYourSecret'; | ||
| var keyDict = { 5678: secret }; | ||
| var server = new Hapi.Server(); | ||
| server.connection(); | ||
| test('Full token payload (header + payload + signature) is available to key lookup function using completeToken option', function (t) { | ||
| server.register(require('../'), function (err) { | ||
| t.ifError(err, 'No error registering hapi-auth-jwt2 plugin'); | ||
| server.auth.strategy('jwt', 'jwt', { | ||
| key: function (decoded, callback) { | ||
| var signatureKey = keyDict[decoded.header.x5t]; // Look dynamically for key based on JWT header field | ||
| return callback(null, signatureKey); | ||
| }, | ||
| complete: true, | ||
| validateFunc: function (decoded, request, callback) { | ||
| return callback(null, true); | ||
| }, | ||
| verifyOptions: {algorithms: ['HS256']} | ||
| }); | ||
| server.route({ | ||
| method: 'POST', | ||
| path: '/', | ||
| handler: function (request, reply) { return reply('Ok'); }, | ||
| config: { auth: 'jwt' } | ||
| }); | ||
| var options = { | ||
| method: 'POST', | ||
| url: '/', | ||
| headers: {Authorization: JWT.sign({ id: 1234 }, secret, { header: { x5t: 5678 } })} // set custom JWT header field "x5t" | ||
| }; | ||
| server.inject(options, function (response) { | ||
| t.equal(response.statusCode, 200, 'Server returned 200 status'); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| }); | ||
| test.onFinish(function () { | ||
| server.stop(function(){}); | ||
| }) |
| var test = require('tape'); | ||
| var JWT = require('jsonwebtoken'); | ||
| var secret = 'NeverShareYourSecret'; | ||
| var server = require('./basic_server.js'); | ||
| var cookie_options = '; Max-Age=31536000;'; //' Expires=Mon, 18 Jul 2016 05:29:45 GMT; Secure; HttpOnly'; | ||
| // var cookie_options = { | ||
| // ttl: 365 * 30 * 7 * 24 * 60 * 60 * 1000, // in the distant future ... | ||
| // encoding: 'none', // we already used JWT to encode | ||
| // isSecure: true, // warm & fuzzy feelings | ||
| // isHttpOnly: true, // prevent client alteration | ||
| // clearInvalid: false, // remove invalid cookies | ||
| // strictHeader: true // don't allow violations of RFC 6265 | ||
| // } | ||
| test("Attempt to access restricted content using inVALID Cookie Token", function(t) { | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, 'badsecret'); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { cookie: "token=" + token } | ||
| }; | ||
| console.log(options); | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 401, "Invalid token should error!"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Attempt to access restricted content with VALID Token but malformed Cookie", function(t) { | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { cookie: token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 400, "Valid Token but inVALID COOKIE should fial!"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Access restricted content with VALID Token Cookie", function(t) { | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { cookie: "token=" + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 200, "VALID COOKIE Token should succeed!"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Access restricted content with VALID Token Cookie (With Options!)", function(t) { | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { cookie: "token=" + token + cookie_options } | ||
| }; | ||
| // console.log(' - - - - - - - - - - - - - - - OPTIONS:') | ||
| // console.log(options); | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| // console.log(' - - - - - - - - - - - - - - - response:') | ||
| // console.log(response); | ||
| t.equal(response.statusCode, 200, "VALID COOKIE Token (With Options!) should succeed!"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| /** Regressions Tests for https://github.com/dwyl/hapi-auth-jwt2/issues/65 **/ | ||
| // supply valid Token Auth Header but invalid Cookie | ||
| // should succeed because Auth Header is first | ||
| test("Authorization Header should take precedence over any cookie", function(t) { | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { | ||
| authorization: "Bearer " + token, | ||
| cookie: "token=malformed.token" + cookie_options | ||
| } | ||
| }; | ||
| server.inject(options, function(response) { | ||
| // console.log(' - - - - - - - - - - - - - - - response:') | ||
| // console.log(response); | ||
| t.equal(response.statusCode, 200, "Ignores cookie when Auth Header is set"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| // valid google analytics cookie but invalid auth header token | ||
| // see: https://github.com/dwyl/hapi-auth-jwt2/issues/65#issuecomment-124791842 | ||
| test("Valid Google Analytics cookie should be ignored", function(t) { | ||
| var GA = "gwcm=%7B%22expires%22%3Anull%2C%22clabel%22%3A%22SbNVCILRtFcQwcrE6gM%22%2C%22backoff%22%3A1437241242%7D; _ga=GA1.2.1363734468.1432273334"; | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { | ||
| authorization: "Bearer " + token, | ||
| cookie: GA | ||
| } | ||
| }; | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 200, "Ignores Google Analytics Cookie"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Valid Google Analytics cookie should be ignored (BAD Header Token)", function(t) { | ||
| var GA = "gwcm=%7B%22expires%22%3Anull%2C%22clabel%22%3A%22SbNVCILRtFcQwcrE6gM%22%2C%22backoff%22%3A1437241242%7D; _ga=GA1.2.1363734468.1432273334"; | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, 'invalid'); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { | ||
| authorization: "Bearer " + token, | ||
| cookie: GA | ||
| } | ||
| }; | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 401, "Ignores GA but Invalid Auth Header still rejected"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| // Supply a VALID Token in Cookie A-N-D valid GA in Cookie!! | ||
| test("Valid Google Analytics cookie should be ignored (BAD Header Token)", function(t) { | ||
| var GA = "gwcm=%7B%22expires%22%3Anull%2C%22clabel%22%3A%22SbNVCILRtFcQwcrE6gM%22%2C%22backoff%22%3A1437241242%7D; _ga=GA1.2.1363734468.1432273334"; | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { | ||
| cookie: "token=" + token + '; ' + GA | ||
| } | ||
| }; | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 200, "Valid Cookie Token Succeeds (Ignores GA)"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Attempt to access restricted content with cookieKey=false", function(t) { | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privadonocookie", | ||
| headers: { cookie: "token=" + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 401, "Disabled cookie auth shouldn't accept valid token!"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Attempt to access restricted content with cookieKey=''", function(t) { | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privadonocookie2", | ||
| headers: { cookie: "=" + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 400, "Disabled cookie auth shouldn't accept valid token!"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| var test = require('tape'); | ||
| var JWT = require('jsonwebtoken'); | ||
| var secret = 'NeverShareYourSecret'; | ||
| var server = require('./custom_parameters_server.js'); | ||
| var cookie_options = '; Max-Age=31536000;'; //' Expires=Mon, 18 Jul 2016 05:29:45 GMT; Secure; HttpOnly'; | ||
| // Those tests are the same as cookie-test and url-token-test but with custom parameters in cookie or URL | ||
| test("Attempt to access restricted content using inVALID Cookie Token - custom parameters", function(t) { | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, 'badsecret'); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { cookie: "customCookieKey=" + token } | ||
| }; | ||
| console.log(options); | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 401, "Invalid token should error!"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Attempt to access restricted content with VALID Token but malformed Cookie - custom parameters", function(t) { | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { cookie: token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 400, "Valid Token but inVALID COOKIE should fial!"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Access restricted content with VALID Token Cookie - custom parameters", function(t) { | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { cookie: "customCookieKey=" + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 200, "VALID COOKIE Token should succeed!"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Access restricted content with VALID Token Cookie (With Options!) - custom parameters", function(t) { | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { cookie: "customCookieKey=" + token + cookie_options } | ||
| }; | ||
| // console.log(' - - - - - - - - - - - - - - - OPTIONS:') | ||
| // console.log(options); | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| // console.log(' - - - - - - - - - - - - - - - response:') | ||
| // console.log(response); | ||
| t.equal(response.statusCode, 200, "VALID COOKIE Token (With Options!) should succeed!"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| /** Regressions Tests for https://github.com/dwyl/hapi-auth-jwt2/issues/65 **/ | ||
| // supply valid Token Auth Header but invalid Cookie | ||
| // should succeed because Auth Header is first | ||
| test("Authorization Header should take precedence over any cookie - custom parameters", function(t) { | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { | ||
| authorization: "MyAuthScheme " + token, | ||
| cookie: "customCookieKey=malformed.token" + cookie_options | ||
| } | ||
| }; | ||
| server.inject(options, function(response) { | ||
| // console.log(' - - - - - - - - - - - - - - - response:') | ||
| // console.log(response); | ||
| t.equal(response.statusCode, 200, "Ignores cookie when Auth Header is set"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| // valid google analytics cookie but invalid auth header token | ||
| // see: https://github.com/dwyl/hapi-auth-jwt2/issues/65#issuecomment-124791842 | ||
| test("Valid Google Analytics cookie should be ignored - custom parameters", function(t) { | ||
| var GA = "gwcm=%7B%22expires%22%3Anull%2C%22clabel%22%3A%22SbNVCILRtFcQwcrE6gM%22%2C%22backoff%22%3A1437241242%7D; _ga=GA1.2.1363734468.1432273334"; | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { | ||
| authorization: "MyAuthScheme " + token, | ||
| cookie: GA | ||
| } | ||
| }; | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 200, "Ignores Google Analytics Cookie"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Valid Google Analytics cookie should be ignored (BAD Header Token) - custom parameters", function(t) { | ||
| var GA = "gwcm=%7B%22expires%22%3Anull%2C%22clabel%22%3A%22SbNVCILRtFcQwcrE6gM%22%2C%22backoff%22%3A1437241242%7D; _ga=GA1.2.1363734468.1432273334"; | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, 'invalid'); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { | ||
| authorization: "MyAuthScheme " + token, | ||
| cookie: GA | ||
| } | ||
| }; | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 401, "Ignores GA but Invalid Auth Header still rejected"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| // Supply a VALID Token in Cookie A-N-D valid GA in Cookie!! | ||
| test("Valid Google Analytics cookie should be ignored (BAD Header Token) - custom parameters", function(t) { | ||
| var GA = "gwcm=%7B%22expires%22%3Anull%2C%22clabel%22%3A%22SbNVCILRtFcQwcrE6gM%22%2C%22backoff%22%3A1437241242%7D; _ga=GA1.2.1363734468.1432273334"; | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { | ||
| cookie: "customCookieKey=" + token + '; ' + GA | ||
| } | ||
| }; | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 200, "Valid Cookie Token Succeeds (Ignores GA)"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Attempt to access restricted content (with an INVALID URL Token) - custom parameters", function(t) { | ||
| var token = "?customUrlKey=my.invalid.token"; | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado" + token | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 401, "INVALID Token should fail"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Try using an incorrect secret to sign the JWT - custom parameters", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, 'incorrectSecret'); | ||
| token = "?customUrlKey=" + token; | ||
| // console.log(" - - - - - - token - - - - -") | ||
| // console.log(token); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado" + token | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 401, "URL Token signed with incorrect key fails"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("URL Token is well formed but is allowed=false so should be denied - custom parameters", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| // var token = jwt.sign({ "id": 1 ,"name":"Old Greg" }, 'incorrectSecret'); | ||
| var token = JWT.sign({ id: 321, "name": "Old Gregg" }, secret); | ||
| token = "?customUrlKey=" + token; | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado" + token | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 401, "User is Denied"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Access restricted content (with VALID Token) - custom parameters", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| token = "?customUrlKey=" + token; | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado" + token | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 200, "VALID Token should succeed!"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Attempt to access restricted content using inVALID header tokenType - custom parameters", function(t) { | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, 'badsecret'); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { Authorization: "InvalidAuthScheme " + token } | ||
| }; | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 401, "Invalid token should error!"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Access restricted content (with VALID Token and header tokenType) - custom parameters", function(t) { | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { Authorization: "MyAuthScheme " + token } | ||
| }; | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 200, "VALID Token should succeed!"); | ||
| t.end(); | ||
| }); | ||
| }); |
| var test = require('tape'); | ||
| var Hapi = require('hapi'); | ||
| var JWT = require('jsonwebtoken'); | ||
| var secret = 'NeverShareYourSecret'; | ||
| var keyDict = { 5678: secret }; | ||
| test('When using a custom header key full token payload (header + payload + signature) is available to key lookup function using completeToken option', function (t) { | ||
| var server = new Hapi.Server(); | ||
| server.connection(); | ||
| server.register(require('../'), function (err) { | ||
| t.ifError(err, 'No error registering hapi-auth-jwt2 plugin'); | ||
| server.auth.strategy('jwt', 'jwt', { | ||
| key: function (decoded, callback) { | ||
| var signatureKey = keyDict[decoded.header.x5t]; // Look dynamically for key based on JWT header field | ||
| return callback(null, signatureKey); | ||
| }, | ||
| complete: true, | ||
| validateFunc: function (decoded, request, callback) { | ||
| return callback(null, true); | ||
| }, | ||
| verifyOptions: {algorithms: ['HS256']}, | ||
| headerKey: 'auths' | ||
| }); | ||
| server.route({ | ||
| method: 'POST', | ||
| path: '/', | ||
| handler: function (request, reply) { return reply('Ok'); }, | ||
| config: { auth: 'jwt' } | ||
| }); | ||
| var options = { | ||
| method: 'POST', | ||
| url: '/', | ||
| headers: {auths: JWT.sign({ id: 1234 }, secret, { header: { x5t: 5678 } })} // set custom JWT header field "x5t" | ||
| }; | ||
| server.inject(options, function (response) { | ||
| t.equal(response.statusCode, 200, 'Server returned 200 status'); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| }); |
| var test = require('tape'); | ||
| var JWT = require('jsonwebtoken'); | ||
| var server = require('./dynamic_key_server'); // test server which in turn loads our module | ||
| test("Access restricted content with a valid token and tenant", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| var token = JWT.sign({ id: 123, "name": "Charlie", "tenant": "dunderMifflin" }, 'michaelscott'); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| console.log(" - - - - RESPONSE: "); | ||
| console.log(response.result); | ||
| t.equal(response.statusCode, 200, "VALID Token should succeed!"); | ||
| t.equal(response.result.data.additional, 'something extra here if needed', 'extraInfo should be passed through'); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Access restricted content with an invalid token and tenant", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| var token = JWT.sign({ id: 123, "name": "Charlie", "tenant": "dunderMifflin" }, 'dwightschrute'); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| console.log(" - - - - RESPONSE: "); | ||
| console.log(response.result); | ||
| t.equal(response.statusCode, 401, "INVALID Token should fail!"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Access restricted content with a valid token and tenant but user is not allowed", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| var token = JWT.sign({ id: 321, "name": "Old Gregg", "tenant": "wernhamHogg" }, 'davidbrent'); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| console.log(" - - - - RESPONSE: "); | ||
| console.log(response.result); | ||
| t.equal(response.statusCode, 401, "Not allowed user should fail!"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Access restricted content without tenant specified in token", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, 'michaelscott'); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| console.log(" - - - - RESPONSE: "); | ||
| console.log(response.result); | ||
| t.equal(response.statusCode, 400, "No tenant specified should fail!"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Access restricted content with non-existent tenant specified", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| var token = JWT.sign({ id: 123, "name": "Charlie", "tenant": "princeFamilyPaper" }, 'michaelscott'); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| console.log(" - - - - RESPONSE: "); | ||
| console.log(response.result); | ||
| t.equal(response.statusCode, 401, "No tentant found should fail!"); | ||
| t.end(); | ||
| }); | ||
| }); |
| var test = require('tape'); | ||
| var JWT = require('jsonwebtoken'); | ||
| // var secret = 'NeverShareYourSecret'; | ||
| var server = require('./error_func_server'); // test server which in turn loads our module | ||
| test("Access a route that has no auth strategy", function(t) { | ||
| var options = { | ||
| method: "GET", | ||
| url: "/" | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 200, "GET / still works without token."); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("customVerify simulate error condition", function(t) { | ||
| var payload = { id: 123, "name": "Charlie", error: true } | ||
| var token = JWT.sign(payload, 'SecretDoesNOTGetVerified'); | ||
| var options = { | ||
| method: "GET", | ||
| url: "/required", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 500, "customVerify force error"); | ||
| t.equal(response.result.message, "An internal server error occurred", "GET /required with forced error that has not been customised"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("customVerify simulate error condition but is safely not customised", function(t) { | ||
| var payload = { id: 123, "name": "Charlie", custom_error: 'ignore'} | ||
| var token = JWT.sign(payload, 'SecretDoesNOTGetVerified'); | ||
| var options = { | ||
| method: "GET", | ||
| url: "/required", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 500, "customVerify force error"); | ||
| t.equal(response.result.message, "An internal server error occurred", "GET /required with forced error that has not been customised"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("customVerify with fail condition", function(t) { | ||
| var payload = { id: 123, "name": "Charlie", some_property: false } | ||
| var token = JWT.sign(payload, 'SecretDoesNOTGetVerified'); | ||
| var options = { | ||
| method: "GET", | ||
| url: "/required", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 401, "GET /required with customVerify rejected"); | ||
| t.equal(response.result.message, "Invalid credentials mate", "GET /required with customVerify rejected and customised error message"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Custom Verification in 'try' mode ", function(t) { | ||
| var payload = { id: 123, "name": "Charlie", some_property: true } | ||
| var token = JWT.sign(payload, 'SecretDoesNOTGetVerified'); | ||
| var options = { | ||
| method: "GET", | ||
| url: "/try", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.result.id, payload.id, 'Decoded JWT returned by handler'); | ||
| t.equal(response.statusCode, 200, "GET /try bypasses verification"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Custom Verification in 'optional' mode ", function(t) { | ||
| var payload = { id: 234, "name": "Oscar", some_property: true } | ||
| var token = JWT.sign(payload, 'SecretDoesNOTGetVerified'); | ||
| var options = { | ||
| method: "GET", | ||
| url: "/optional", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.result.id, payload.id, 'Decoded JWT returned by handler'); | ||
| t.equal(response.statusCode, 200, "GET /optional bypasses verification"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Custom Verification in 'required' mode ", function(t) { | ||
| var payload = { id: 345, "name": "Romeo", some_property: true } | ||
| var token = JWT.sign(payload, 'AnyStringWillDo'); | ||
| var options = { | ||
| method: "GET", | ||
| url: "/required", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| // console.log(response.result); | ||
| var credentials = JSON.parse(JSON.stringify(response.result)); | ||
| t.equal(credentials.id, payload.id, 'Decoded JWT is available in handler'); | ||
| t.equal(response.statusCode, 200, "GET /required bypasses verification"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| var test = require('tape'); | ||
| var JWT = require('jsonwebtoken'); | ||
| var secret = 'NeverShareYourSecret'; | ||
| var server = require('./scheme-response-server'); // test server which in turn loads our module | ||
| test("Attempt to access restricted content (without auth token)", function(t) { | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado" | ||
| }; | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 401, "No Token should fail"); | ||
| t.equal(response.headers.authorization, undefined, 'Invalid requests should not be calling the response function'); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Attempt to access restricted content (with an INVALID Token)", function(t) { | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { authorization: "Bearer fails.validation" } | ||
| }; | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 401, "INVALID Token should fail"); | ||
| t.equal(response.headers.authorization, undefined, 'Invalid requests should not be calling the response function'); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Access restricted content (with VALID Token)", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 200, "VALID Token should succeed!"); | ||
| t.equal(response.headers.authorization, 'from scheme response function', 'Valid request should finish by calling response function'); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Auth mode 'required' should require authentication header", function(t) { | ||
| var options = { | ||
| method: "POST", | ||
| url: "/required" | ||
| }; | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 401, "No token header should fail in auth 'required' mode"); | ||
| t.equal(response.headers.authorization, undefined, 'Invalid requests should not be calling the response function'); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Auth mode 'required' should should pass with valid token", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/required", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 200, "Valid token should succeed!"); | ||
| t.equal(response.headers.authorization, 'from scheme response function', 'Valid request should finish by calling response function'); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Scheme should set token in request.auth.token", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| var options = { | ||
| method: "GET", | ||
| url: "/token", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| server.inject(options, function(response) { | ||
| t.equal(response.result, token, 'Token is accesible from handler'); | ||
| t.equal(response.headers.authorization, 'from scheme response function', 'Valid request should finish by calling response function'); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Testing an error thrown from the scheme\'s response function", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| var options = { | ||
| method: "GET", | ||
| url: "/token", | ||
| headers: { | ||
| authorization: "Bearer " + token, | ||
| error: 'true' | ||
| } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 500, 'A server error happens in the scheme\'s response function'); | ||
| t.end(); | ||
| }); | ||
| }); |
| var test = require('tape'); | ||
| var JWT = require('jsonwebtoken'); | ||
| var secret = 'NeverShareYourSecret'; // set by ENV Variable | ||
| var server = require('./scopes_server'); // test server which in turn loads our module | ||
| test("Access restricted content using scopes (with VALID Token and VALID scope)", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado-with-scope", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| console.log(" - - - - RESPONSE: "); | ||
| console.log(response.result); | ||
| t.equal(response.statusCode, 200, "VALID Token should succeed!"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Access restricted content using scopes (with VALID Token and INVALID scope)", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| var token = JWT.sign({ id: 321, "name": "Old Gregg" }, secret); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado-with-scope", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| console.log(" - - - - RESPONSE: "); | ||
| console.log(response.result); | ||
| t.equal(response.statusCode, 401, "Denied"); | ||
| t.end(); | ||
| }); | ||
| }); |
| var test = require('tape'); | ||
| var JWT = require('jsonwebtoken'); | ||
| var secret = 'NeverShareYourSecret'; | ||
| var server = require('./basic_server.js'); | ||
| test("Attempt to access restricted content (without auth token)", function(t) { | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado" | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 401, "No Token supplied > fails (as expected)"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Attempt to access restricted content (with an INVALID URL Token)", function(t) { | ||
| var token = "?token=my.invalid.token"; | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado" + token | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 401, "INVALID Token should fail"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Try using an incorrect secret to sign the JWT", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, 'incorrectSecret'); | ||
| token = "?token=" + token; | ||
| // console.log(" - - - - - - token - - - - -") | ||
| // console.log(token); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado" + token | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 401, "URL Token signed with incorrect key fails"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("URL Token is well formed but is allowed=false so should be denied", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| // var token = jwt.sign({ "id": 1 ,"name":"Old Greg" }, 'incorrectSecret'); | ||
| var token = JWT.sign({ id: 321, "name": "Old Gregg" }, secret); | ||
| token = "?token=" + token; | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado" + token | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 401, "User is Denied"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Access restricted content (with VALID Token)", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| token = "?token=" + token; | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado" + token | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 200, "VALID Token should succeed!"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Using route with urlKey=false should be denied", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| token = "?token=" + token; | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privadonourl" + token | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 401, "No urlKey configured so URL-Tokens should be denied"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Using route with urlKey='' should be denied", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| token = "?=" + token; | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privadonourl2" + token | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 401, "No urlKey configured so URL-Tokens should be denied"); | ||
| t.end(); | ||
| }); | ||
| }); |
| var test = require('tape'); | ||
| var Hapi = require('hapi'); | ||
| var JWT = require('jsonwebtoken'); | ||
| var secret = 'NeverShareYourSecret'; | ||
| test('Should respond with 500 series error when validateFunc errs', function (t) { | ||
| var server = new Hapi.Server(); | ||
| server.connection(); | ||
| server.register(require('../'), function (err) { | ||
| t.ifError(err, 'No error registering hapi-auth-jwt2 plugin'); | ||
| server.auth.strategy('jwt', 'jwt', { | ||
| key: secret, | ||
| validateFunc: function (decoded, request, callback) { | ||
| return callback(new Error('ASPLODE')); | ||
| }, | ||
| verifyOptions: {algorithms: ['HS256']} | ||
| }); | ||
| server.route({ | ||
| method: 'POST', | ||
| path: '/privado', | ||
| handler: function (req, reply) { return reply('PRIVADO'); }, | ||
| config: { auth: 'jwt' } | ||
| }); | ||
| var options = { | ||
| method: 'POST', | ||
| url: '/privado', | ||
| headers: {Authorization: JWT.sign({id: 138, name: 'Test'}, secret)} | ||
| }; | ||
| server.inject(options, function (response) { | ||
| t.equal(response.statusCode, 500, 'Server returned 500 for validateFunc error'); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| }); |
| var test = require('tape'); | ||
| var JWT = require('jsonwebtoken'); | ||
| // var secret = 'NeverShareYourSecret'; | ||
| var server = require('./verify_func_server'); // test server which in turn loads our module | ||
| test("Access a route that has no auth strategy", function(t) { | ||
| var options = { | ||
| method: "GET", | ||
| url: "/" | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 200, "GET / still works without token."); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("customVerify simulate error condition", function(t) { | ||
| var payload = { id: 123, "name": "Charlie", error: true } | ||
| var token = JWT.sign(payload, 'SecretDoesNOTGetVerified'); | ||
| var options = { | ||
| method: "GET", | ||
| url: "/required", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 500, "customVerify force error"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("customVerify with fail condition", function(t) { | ||
| var payload = { id: 123, "name": "Charlie", some_property: false } | ||
| var token = JWT.sign(payload, 'SecretDoesNOTGetVerified'); | ||
| var options = { | ||
| method: "GET", | ||
| url: "/required", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 401, "GET /required with customVerify rejected"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Custom Verification in 'try' mode ", function(t) { | ||
| var payload = { id: 123, "name": "Charlie", some_property: true } | ||
| var token = JWT.sign(payload, 'SecretDoesNOTGetVerified'); | ||
| var options = { | ||
| method: "GET", | ||
| url: "/try", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.result.id, payload.id, 'Decoded JWT returned by handler'); | ||
| t.equal(response.statusCode, 200, "GET /try bypasses verification"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Custom Verification in 'optional' mode ", function(t) { | ||
| var payload = { id: 234, "name": "Oscar", some_property: true } | ||
| var token = JWT.sign(payload, 'SecretDoesNOTGetVerified'); | ||
| var options = { | ||
| method: "GET", | ||
| url: "/optional", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.result.id, payload.id, 'Decoded JWT returned by handler'); | ||
| t.equal(response.statusCode, 200, "GET /optional bypasses verification"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Custom Verification in 'required' mode ", function(t) { | ||
| var payload = { id: 345, "name": "Romeo", some_property: true } | ||
| var token = JWT.sign(payload, 'AnyStringWillDo'); | ||
| var options = { | ||
| method: "GET", | ||
| url: "/required", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| // console.log(response.result); | ||
| var credentials = JSON.parse(JSON.stringify(response.result)); | ||
| t.equal(credentials.id, payload.id, 'Decoded JWT is available in handler'); | ||
| t.equal(response.statusCode, 200, "GET /required bypasses verification"); | ||
| t.end(); | ||
| }); | ||
| }); |
+8
-6
@@ -51,8 +51,10 @@ var Boom = require('boom'); // error handling https://github.com/hapijs/boom | ||
| var tokenType = options.tokenType || 'Token'; // | ||
| if (!token) { | ||
| return reply(raiseError('unauthorized', null, 'Token')); | ||
| return reply(raiseError('unauthorized', null, tokenType)); | ||
| } | ||
| if (!extract.isValid(token)) { // quick check for validity of token format | ||
| return reply(raiseError('unauthorized', 'Invalid token format', 'Token')); | ||
| return reply(raiseError('unauthorized', 'Invalid token format', tokenType)); | ||
| } // verification is done later, but we want to avoid decoding if malformed | ||
@@ -66,3 +68,3 @@ request.auth.token = token; // keep encoded JWT available in the request lifecycle | ||
| catch(e) { // request should still FAIL if the token does not decode. | ||
| return reply(raiseError('unauthorized', 'Invalid token format', 'Token')); | ||
| return reply(raiseError('unauthorized', 'Invalid token format', tokenType)); | ||
| } | ||
@@ -84,3 +86,3 @@ | ||
| if (err) { | ||
| return reply(raiseError('unauthorized', 'Invalid token', 'Token'), null, { credentials: null }); | ||
| return reply(raiseError('unauthorized', 'Invalid token', tokenType), null, { credentials: null }); | ||
| } | ||
@@ -93,3 +95,3 @@ else { // see: http://hapijs.com/tutorials/auth for validateFunc signature | ||
| else if (!valid) { | ||
| return reply(raiseError('unauthorized', 'Invalid credentials', 'Token'), null, { credentials: credentials || decoded }); | ||
| return reply(raiseError('unauthorized', 'Invalid credentials', tokenType), null, { credentials: credentials || decoded }); | ||
| } | ||
@@ -110,3 +112,3 @@ else { | ||
| else if (!valid) { | ||
| return reply(raiseError('unauthorized', 'Invalid credentials', 'Token'), null, { credentials: decoded }); | ||
| return reply(raiseError('unauthorized', 'Invalid credentials', tokenType), null, { credentials: decoded }); | ||
| } else { | ||
@@ -113,0 +115,0 @@ return reply.continue({ credentials: credentials, artifacts: token }); |
+10
-10
| { | ||
| "name": "hapi-auth-jwt2", | ||
| "version": "7.1.0", | ||
| "version": "7.1.1", | ||
| "description": "Hapi.js Authentication Plugin/Scheme using JSON Web Tokens (JWT)", | ||
@@ -42,14 +42,14 @@ "main": "lib/index.js", | ||
| "dependencies": { | ||
| "boom": "^3.1.3", | ||
| "boom": "^3.2.2", | ||
| "cookie": "^0.3.1", | ||
| "jsonwebtoken": "^7.0.0" | ||
| "jsonwebtoken": "^7.1.9" | ||
| }, | ||
| "devDependencies": { | ||
| "aguid": "^1.0.4", | ||
| "hapi": "^13.4.1", | ||
| "istanbul": "^0.4.3", | ||
| "jshint": "^2.9.2", | ||
| "hapi": "^14.2.0", | ||
| "istanbul": "^0.4.5", | ||
| "jshint": "^2.9.3", | ||
| "pre-commit": "^1.1.3", | ||
| "tap-spec": "^4.1.1", | ||
| "tape": "^4.5.1" | ||
| "tape": "^4.6.0" | ||
| }, | ||
@@ -60,5 +60,5 @@ "engines": { | ||
| "scripts": { | ||
| "quick": "./node_modules/tape/bin/tape ./test/*.js | node_modules/tap-spec/bin/cmd.js", | ||
| "test": "istanbul cover ./node_modules/tape/bin/tape ./test/*.js | node_modules/tap-spec/bin/cmd.js", | ||
| "coverage": "istanbul cover ./node_modules/tape/bin/tape ./test/*.js && istanbul check-coverage --statements 100 --functions 100 --lines 100 --branches 100", | ||
| "quick": "./node_modules/tape/bin/tape ./test/*.test.js | node_modules/tap-spec/bin/cmd.js", | ||
| "test": "istanbul cover ./node_modules/tape/bin/tape ./test/*.test.js | node_modules/tap-spec/bin/cmd.js", | ||
| "coverage": "istanbul cover ./node_modules/tape/bin/tape ./test/*.test.js && istanbul check-coverage --statements 100 --functions 100 --lines 100 --branches 100", | ||
| "jshint": "./node_modules/jshint/bin/jshint -c .jshintrc --exclude-path .gitignore .", | ||
@@ -65,0 +65,0 @@ "start": "node example/server.js", |
+89
-16
@@ -11,10 +11,7 @@ # Hapi Auth using JSON Web Tokens (JWT) | ||
| [](https://codeclimate.com/github/dwyl/hapi-auth-jwt2) | ||
| [](http://hapijs.com) | ||
| [](http://hapijs.com) | ||
| [](http://nodejs.org/download/) | ||
| [](https://www.npmjs.com/package/hapi-auth-jwt2) | ||
| [")](https://david-dm.org/dwyl/hapi-auth-jwt2) | ||
| [](https://david-dm.org/dwyl/hapi-auth-jwt2#info=devDependencies) | ||
| [](https://www.bithound.io/github/dwyl/hapi-auth-jwt2) | ||
| [](https://gitter.im/dwyl/chat/?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) | ||
| [](https://david-dm.org/dwyl/hapi-auth-jwt2?type=dev) | ||
| [](https://www.npmjs.com/package/hapi-auth-jwt2) | ||
@@ -205,3 +202,11 @@ This node.js module (Hapi plugin) lets you use JSON Web Tokens (JWTs) | ||
| ### Useful Features | ||
| + The *encoded* JWT (token) is extracted from the headers of the request and | ||
| made available on the `request` object as `request.auth.token`, | ||
| in case you need it later on in the request lifecycle. | ||
| This feature was requested by @mcortesi in | ||
| [hapi-auth-jwt2/issues/123](https://github.com/dwyl/hapi-auth-jwt2/issues/123) | ||
| ### Understanding the Request Flow | ||
@@ -368,3 +373,3 @@ | ||
| ### Background Reading | ||
| #### Background Reading (*Cookies*) | ||
@@ -379,7 +384,9 @@ + Wikipedia has a good intro (general): https://en.wikipedia.org/wiki/HTTP_cookie | ||
| ## Frequently Asked Questions (FAQ) | ||
| ## Frequently Asked Questions (FAQ) [](https://gitter.im/dwyl/chat/?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) | ||
| 1. Do I need to include **jsonwebtoken** in my project? asked in [hapi-auth-jwt2/issues/32](https://github.com/dwyl/hapi-auth-jwt2/issues/32) | ||
| ### Do I *need* to include `jsonwebtoken` in my project? | ||
| **Q**: Must I include the **jsonwebtoken** package in my project | ||
| [given that **hapi-auth-jwt2** plugin already includes it] ? | ||
| [given that **hapi-auth-jwt2** plugin already includes it] ? asked in [hapi-auth-jwt2/issues/32](https://github.com/dwyl/hapi-auth-jwt2/issues/32) | ||
| **A**: Yes, you need to *manually* install the **jsonwebtoken** | ||
@@ -393,3 +400,5 @@ node module from NPM with `npm install jsonwebtoken --save` if you want to ***sign*** JWTs in your app. | ||
| 2. Can we supply a ***Custom Verification*** function instead of using the **JWT.verify** method? | ||
| ### ***Custom Verification*** ? | ||
| Can we supply a ***Custom Verification*** function instead of using the **JWT.verify** method? | ||
| asked by *both* [Marcus Stong](https://github.com/stongo) & [Kevin Stewart](https://github.com/kdstew) | ||
@@ -401,3 +410,70 @@ in [issue #120](https://github.com/dwyl/hapi-auth-jwt2/issues/120) and [issue #130](https://github.com/dwyl/hapi-auth-jwt2/issues/130) respectively. | ||
| <br /> | ||
| ### Can I use `hapi-auth-jwt2` with [`glue`](https://github.com/hapijs/glue) | ||
| Several people asked us if this plugin is compatible with | ||
| Hapi's "Server Composer" [`glue`](https://github.com/hapijs/glue) | ||
| The answer is ***Yes***! For an example of how to do this, | ||
| see [@avanslaars](https://github.com/avanslaars) code example: | ||
| https://github.com/dwyl/hapi-auth-jwt2/issues/151#issuecomment-218321212 | ||
| <br /> | ||
| ### How do I *invalidate* an *existing token*? | ||
| Asked by [@SanderElias](https://github.com/SanderElias) in [hapi-auth-jwt2/issues/126](https://github.com/dwyl/hapi-auth-jwt2/issues/126) | ||
| We store our JWT-based sessions in a Redis datastore and lookup the session (`jti`) for the given JWT during the `validateFunc` (*validation function*) see: https://github.com/dwyl/hapi-auth-jwt2-example/blob/791b0d3906d4deb256daf23fcf8f5021905abe9e/index.js#L25 | ||
| This means we can invalidate the session in Redis and then reject a request that uses an "old" or invalid JWT. see: https://github.com/dwyl/hapi-auth-jwt2-example/blob/791b0d3906d4deb256daf23fcf8f5021905abe9e/index.js#L25 | ||
| <br /> | ||
| ### How do I set JWT Auth to *All Routes*? | ||
| [@abeninskibede](https://github.com/abeninskibede) asked how to set all routes to use JWT Auth in [hapi-auth-jwt2/issues/149](https://github.com/dwyl/hapi-auth-jwt2/issues/149) | ||
| We tend to enable `hapi-auth-jwt2` for _all_ routes by setting the `mode` parameter to `true` (so its `required` for all endpoints) because _most_ of the endpoints in our app require the person/user to be authenticated e.g: | ||
| ```js | ||
| // setting the 3rd argument to true means 'mode' is 'required' see: http://hapijs.com/tutorials/auth#mode | ||
| server.auth.strategy('jwt', 'jwt', true, { // so JWT auth is required for all routes | ||
| key: process.env.JWT_SECRET, | ||
| validateFunc: require('./jwt2_validate_func'), | ||
| verifyOptions: { ignoreExpiration: true, algorithms: [ 'HS256' ] } | ||
| }); | ||
| ``` | ||
| > _Detailed Practical Example_: https://github.com/dwyl/hapi-login-example-postgres/blob/245a44f0e88226d99a3ad2e3dc38cc0d1750a241/lib/server.js#L33 | ||
| When you want a particular route to ***not require*** JWT auth you simply set `config: { auth: false }` e.g: | ||
| ```js | ||
| server.route({ | ||
| method: 'GET', | ||
| path: '/login', | ||
| handler: login_handler, // display login/registration form/page | ||
| config: { auth: false } // don't require people to be logged in to see the login page! (duh!) | ||
| }); | ||
| ``` | ||
| The best place to _understand_ everything about Hapi Auth is in the docs: http://hapijs.com/tutorials/auth#setting-a-default-strategy | ||
| But if you have any questions which are not answered there, feel free to [ask!](https://github.com/dwyl/hapi-auth-jwt2/issues) | ||
| <br /> | ||
| ### How to _redirect_ if a token has expired? | ||
| @traducer & @goncalvesr2 both requested how to redirect after failed Auth in | ||
| [hapi-auth-jwt2/issues/161](https://github.com/dwyl/hapi-auth-jwt2/issues/161) | ||
| and [hapi-auth-jwt2/issues/148](https://github.com/dwyl/hapi-auth-jwt2/issues/148) respectively | ||
| The [`hapi-error`](https://github.com/dwyl/hapi-error) lets | ||
| you _easily_ redirect to any url you define if the Auth check fails | ||
| (i.e. `statusCode 401`) | ||
| see: https://github.com/dwyl/hapi-error#redirecting-to-another-endpoint | ||
| (*code examples there.*) | ||
| <br /> | ||
| ## *Advanced/Alternative* Usage => Bring Your Own `verifyFunc` | ||
@@ -439,7 +515,4 @@ | ||
| `hapi-auth-jwt2` is compatible with Hapi.js versions `11.x.x` `10.x.x` `9.x.x` and `8.x.x` as there was no change to how the Hapi plugin system works | ||
| for the past two versions. | ||
| See the release notes for more details: | ||
| + Hapi Version 10: https://github.com/hapijs/hapi/issues/2764 | ||
| + Hapi Version 9: https://github.com/hapijs/hapi/issues/2682 | ||
| `hapi-auth-jwt2` is compatible with Hapi.js versions `14.x.x` `13.x.x` `12.x.x` `11.x.x` `10.x.x` `9.x.x` and `8.x.x` | ||
| as there have been ***no changes*** to how the Hapi plugin system works for a while! | ||
@@ -446,0 +519,0 @@ However in the interest of |
| var test = require('tape'); | ||
| var JWT = require('jsonwebtoken'); | ||
| var secret = 'NeverShareYourSecret'; | ||
| var server = require('./basic_server'); // test server which in turn loads our module | ||
| test("Attempt to access restricted content (without auth token)", function(t) { | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado" | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 401, "No Token should fail"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Attempt to access restricted content (with an INVALID Token)", function(t) { | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { authorization: "Bearer fails.validation" } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 401, "INVALID Token should fail"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Malformed JWT", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| // var token = jwt.sign({ "id": 1 ,"name":"Old Greg" }, 'incorrectSecret'); | ||
| // console.log(token); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { authorization: "Bearer my.invalid.token" } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| // console.log(response.result); | ||
| // console.log(' '); // blank line | ||
| t.equal(response.statusCode, 401, "INVALID Token should fail"); | ||
| // t.equal(JSON.parse(response.result).msg, 'Invalid Token', "INVALID Token should fail"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Try using a token with missing characters in body", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| // delete some characters in body | ||
| var tokenData = token.split('.'); | ||
| var header = tokenData[0], | ||
| body = tokenData[1], | ||
| signature = tokenData[2]; | ||
| token = header + '.' + body.substring(0, body.length - 1) + '.' + signature; | ||
| /*console.log(" - - - - - - token - - - - -"); | ||
| console.log(token);*/ | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 401, "INVALID Token should fail"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Try using an incorrect secret to sign the JWT", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, 'incorrectSecret'); | ||
| // console.log(" - - - - - - token - - - - -") | ||
| // console.log(token); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 401, "Token signed with incorrect key fails"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| // see: https://github.com/dwyl/hapi-auth-jwt2/issues/166 | ||
| // test.only("Try using an expired token", function(t) { | ||
| // // use the token as the 'authorization' header in requests | ||
| // var token = JWT.sign({ id: 123, "name": "Charlie" }, secret, { expiresInSeconds: 1 }); | ||
| // console.log(" - - - - - - token - - - - -") | ||
| // console.log(token); | ||
| // var options = { | ||
| // method: "POST", | ||
| // url: "/privado", | ||
| // headers: { authorization: "Bearer " + token } | ||
| // }; | ||
| // // server.inject lets us simulate an http request | ||
| // setTimeout(function () { | ||
| // server.inject(options, function(response) { | ||
| // t.equal(response.statusCode, 401, "Expired token should be invalid"); | ||
| // t.equal(response.result.message, 'Token expired', 'Message should be "Token expired"'); | ||
| // t.end(); | ||
| // }); | ||
| // }, 1000); | ||
| // }); | ||
| test("Token is well formed but is allowed=false so should be denied", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| // var token = jwt.sign({ "id": 1 ,"name":"Old Greg" }, 'incorrectSecret'); | ||
| var token = JWT.sign({ id: 321, "name": "Old Gregg" }, secret); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 401, "Denied"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Access restricted content (with VALID Token)", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| // console.log(" - - - - RESPONSE: ") | ||
| // console.log(response.result); | ||
| t.equal(response.statusCode, 200, "VALID Token should succeed!"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Access restricted content (with Well-formed but invalid Token)", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, 'badsecret'); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| // console.log(" - - - - RESPONSE: ") | ||
| // console.log(response.result); | ||
| t.equal(response.statusCode, 401, "InVALID Token should Error!"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| // see: https://github.com/ideaq/hapi-auth-jwt2/issues/28 | ||
| test("Request with undefined auth header should 401", function(t) { | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { authorization: "Bearer " } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| // console.log(" - - - - RESPONSE: ") | ||
| // console.log(response.result); | ||
| t.equal(response.statusCode, 401, "InVALID Token fails (as expected)!"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Auth mode 'required' should require authentication header", function(t) { | ||
| var options = { | ||
| method: "POST", | ||
| url: "/required" | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 401, "No token header should fail in auth 'required' mode"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Auth mode 'required' should fail with invalid token", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, 'badsecret'); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/required", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| // console.log(" - - - - RESPONSE: ") | ||
| // console.log(response.result); | ||
| t.equal(response.statusCode, 401, "Invalid token should error!"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Auth mode 'required' should should pass with valid token", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/required", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| // console.log(" - - - - RESPONSE: ") | ||
| // console.log(response.result); | ||
| t.equal(response.statusCode, 200, "Valid token should succeed!"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Auth mode 'optional' should pass when no auth header specified", function(t) { | ||
| var options = { | ||
| method: "POST", | ||
| url: "/optional" | ||
| }; | ||
| server.inject(options, function(response) { | ||
| // console.log(" - - - - RESPONSE: ") | ||
| // console.log(response.result); | ||
| t.equal(response.statusCode, 200, "No auth header should pass in optional mode!"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Auth mode 'optional' should fail with invalid token", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, 'badsecret'); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/optional", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| // console.log(" - - - - RESPONSE: ") | ||
| // console.log(response.result); | ||
| t.equal(response.statusCode, 401, "Invalid token should error!"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Auth mode 'optional' should pass with valid token", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| // var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/optional", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| // console.log(" - - - - RESPONSE: ") | ||
| // console.log(response.result); | ||
| t.equal(response.statusCode, 200, "Valid token should succeed!"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Auth mode 'try' should pass when no auth header specified", function(t) { | ||
| var options = { | ||
| method: "POST", | ||
| url: "/try" | ||
| }; | ||
| server.inject(options, function(response) { | ||
| // console.log(" - - - - RESPONSE: ") | ||
| // console.log(response.result); | ||
| t.equal(response.statusCode, 200, "No auth header should pass in 'try' mode!"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Auth mode 'try' should pass with invalid token", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, 'badsecret'); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/try", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| // console.log(" - - - - RESPONSE: ") | ||
| // console.log(response.result); | ||
| t.equal(response.statusCode, 200, "Invalid token should pass in 'try' mode"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Auth mode 'try' should pass with valid token", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/try", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| // console.log(" - - - - RESPONSE: ") | ||
| // console.log(response); | ||
| t.equal(response.statusCode, 200, "Valid token should succeed!"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Scheme should set token in request.auth.token", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| var options = { | ||
| method: "GET", | ||
| url: "/token", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| // console.log(" - - - - RESPONSE: ") | ||
| // console.log(response.result); | ||
| t.equal(response.result, token, 'Token is accesible from handler'); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test.onFinish(function () { | ||
| server.stop(function(){}); | ||
| }) |
| var test = require('tape'); | ||
| var Hapi = require('hapi'); | ||
| var JWT = require('jsonwebtoken'); | ||
| var secret = 'NeverShareYourSecret'; | ||
| var keyDict = { 5678: secret }; | ||
| var server = new Hapi.Server(); | ||
| server.connection(); | ||
| test('Full token payload (header + payload + signature) is available to key lookup function using completeToken option', function (t) { | ||
| server.register(require('../'), function (err) { | ||
| t.ifError(err, 'No error registering hapi-auth-jwt2 plugin'); | ||
| server.auth.strategy('jwt', 'jwt', { | ||
| key: function (decoded, callback) { | ||
| var signatureKey = keyDict[decoded.header.x5t]; // Look dynamically for key based on JWT header field | ||
| return callback(null, signatureKey); | ||
| }, | ||
| complete: true, | ||
| validateFunc: function (decoded, request, callback) { | ||
| return callback(null, true); | ||
| }, | ||
| verifyOptions: {algorithms: ['HS256']} | ||
| }); | ||
| server.route({ | ||
| method: 'POST', | ||
| path: '/', | ||
| handler: function (request, reply) { return reply('Ok'); }, | ||
| config: { auth: 'jwt' } | ||
| }); | ||
| var options = { | ||
| method: 'POST', | ||
| url: '/', | ||
| headers: {Authorization: JWT.sign({ id: 1234 }, secret, { header: { x5t: 5678 } })} // set custom JWT header field "x5t" | ||
| }; | ||
| server.inject(options, function (response) { | ||
| t.equal(response.statusCode, 200, 'Server returned 200 status'); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| }); | ||
| test.onFinish(function () { | ||
| server.stop(function(){}); | ||
| }) |
| var test = require('tape'); | ||
| var JWT = require('jsonwebtoken'); | ||
| var secret = 'NeverShareYourSecret'; | ||
| var server = require('./basic_server.js'); | ||
| var cookie_options = '; Max-Age=31536000;'; //' Expires=Mon, 18 Jul 2016 05:29:45 GMT; Secure; HttpOnly'; | ||
| // var cookie_options = { | ||
| // ttl: 365 * 30 * 7 * 24 * 60 * 60 * 1000, // in the distant future ... | ||
| // encoding: 'none', // we already used JWT to encode | ||
| // isSecure: true, // warm & fuzzy feelings | ||
| // isHttpOnly: true, // prevent client alteration | ||
| // clearInvalid: false, // remove invalid cookies | ||
| // strictHeader: true // don't allow violations of RFC 6265 | ||
| // } | ||
| test("Attempt to access restricted content using inVALID Cookie Token", function(t) { | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, 'badsecret'); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { cookie: "token=" + token } | ||
| }; | ||
| console.log(options); | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 401, "Invalid token should error!"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Attempt to access restricted content with VALID Token but malformed Cookie", function(t) { | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { cookie: token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 400, "Valid Token but inVALID COOKIE should fial!"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Access restricted content with VALID Token Cookie", function(t) { | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { cookie: "token=" + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 200, "VALID COOKIE Token should succeed!"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Access restricted content with VALID Token Cookie (With Options!)", function(t) { | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { cookie: "token=" + token + cookie_options } | ||
| }; | ||
| // console.log(' - - - - - - - - - - - - - - - OPTIONS:') | ||
| // console.log(options); | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| // console.log(' - - - - - - - - - - - - - - - response:') | ||
| // console.log(response); | ||
| t.equal(response.statusCode, 200, "VALID COOKIE Token (With Options!) should succeed!"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| /** Regressions Tests for https://github.com/dwyl/hapi-auth-jwt2/issues/65 **/ | ||
| // supply valid Token Auth Header but invalid Cookie | ||
| // should succeed because Auth Header is first | ||
| test("Authorization Header should take precedence over any cookie", function(t) { | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { | ||
| authorization: "Bearer " + token, | ||
| cookie: "token=malformed.token" + cookie_options | ||
| } | ||
| }; | ||
| server.inject(options, function(response) { | ||
| // console.log(' - - - - - - - - - - - - - - - response:') | ||
| // console.log(response); | ||
| t.equal(response.statusCode, 200, "Ignores cookie when Auth Header is set"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| // valid google analytics cookie but invalid auth header token | ||
| // see: https://github.com/dwyl/hapi-auth-jwt2/issues/65#issuecomment-124791842 | ||
| test("Valid Google Analytics cookie should be ignored", function(t) { | ||
| var GA = "gwcm=%7B%22expires%22%3Anull%2C%22clabel%22%3A%22SbNVCILRtFcQwcrE6gM%22%2C%22backoff%22%3A1437241242%7D; _ga=GA1.2.1363734468.1432273334"; | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { | ||
| authorization: "Bearer " + token, | ||
| cookie: GA | ||
| } | ||
| }; | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 200, "Ignores Google Analytics Cookie"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Valid Google Analytics cookie should be ignored (BAD Header Token)", function(t) { | ||
| var GA = "gwcm=%7B%22expires%22%3Anull%2C%22clabel%22%3A%22SbNVCILRtFcQwcrE6gM%22%2C%22backoff%22%3A1437241242%7D; _ga=GA1.2.1363734468.1432273334"; | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, 'invalid'); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { | ||
| authorization: "Bearer " + token, | ||
| cookie: GA | ||
| } | ||
| }; | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 401, "Ignores GA but Invalid Auth Header still rejected"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| // Supply a VALID Token in Cookie A-N-D valid GA in Cookie!! | ||
| test("Valid Google Analytics cookie should be ignored (BAD Header Token)", function(t) { | ||
| var GA = "gwcm=%7B%22expires%22%3Anull%2C%22clabel%22%3A%22SbNVCILRtFcQwcrE6gM%22%2C%22backoff%22%3A1437241242%7D; _ga=GA1.2.1363734468.1432273334"; | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { | ||
| cookie: "token=" + token + '; ' + GA | ||
| } | ||
| }; | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 200, "Valid Cookie Token Succeeds (Ignores GA)"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Attempt to access restricted content with cookieKey=false", function(t) { | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privadonocookie", | ||
| headers: { cookie: "token=" + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 401, "Disabled cookie auth shouldn't accept valid token!"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Attempt to access restricted content with cookieKey=''", function(t) { | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privadonocookie2", | ||
| headers: { cookie: "=" + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 400, "Disabled cookie auth shouldn't accept valid token!"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| var test = require('tape'); | ||
| var JWT = require('jsonwebtoken'); | ||
| var secret = 'NeverShareYourSecret'; | ||
| var server = require('./custom_parameters_server.js'); | ||
| var cookie_options = '; Max-Age=31536000;'; //' Expires=Mon, 18 Jul 2016 05:29:45 GMT; Secure; HttpOnly'; | ||
| // Those tests are the same as cookie-test and url-token-test but with custom parameters in cookie or URL | ||
| test("Attempt to access restricted content using inVALID Cookie Token - custom parameters", function(t) { | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, 'badsecret'); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { cookie: "customCookieKey=" + token } | ||
| }; | ||
| console.log(options); | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 401, "Invalid token should error!"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Attempt to access restricted content with VALID Token but malformed Cookie - custom parameters", function(t) { | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { cookie: token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 400, "Valid Token but inVALID COOKIE should fial!"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Access restricted content with VALID Token Cookie - custom parameters", function(t) { | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { cookie: "customCookieKey=" + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 200, "VALID COOKIE Token should succeed!"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Access restricted content with VALID Token Cookie (With Options!) - custom parameters", function(t) { | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { cookie: "customCookieKey=" + token + cookie_options } | ||
| }; | ||
| // console.log(' - - - - - - - - - - - - - - - OPTIONS:') | ||
| // console.log(options); | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| // console.log(' - - - - - - - - - - - - - - - response:') | ||
| // console.log(response); | ||
| t.equal(response.statusCode, 200, "VALID COOKIE Token (With Options!) should succeed!"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| /** Regressions Tests for https://github.com/dwyl/hapi-auth-jwt2/issues/65 **/ | ||
| // supply valid Token Auth Header but invalid Cookie | ||
| // should succeed because Auth Header is first | ||
| test("Authorization Header should take precedence over any cookie - custom parameters", function(t) { | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { | ||
| authorization: "MyAuthScheme " + token, | ||
| cookie: "customCookieKey=malformed.token" + cookie_options | ||
| } | ||
| }; | ||
| server.inject(options, function(response) { | ||
| // console.log(' - - - - - - - - - - - - - - - response:') | ||
| // console.log(response); | ||
| t.equal(response.statusCode, 200, "Ignores cookie when Auth Header is set"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| // valid google analytics cookie but invalid auth header token | ||
| // see: https://github.com/dwyl/hapi-auth-jwt2/issues/65#issuecomment-124791842 | ||
| test("Valid Google Analytics cookie should be ignored - custom parameters", function(t) { | ||
| var GA = "gwcm=%7B%22expires%22%3Anull%2C%22clabel%22%3A%22SbNVCILRtFcQwcrE6gM%22%2C%22backoff%22%3A1437241242%7D; _ga=GA1.2.1363734468.1432273334"; | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { | ||
| authorization: "MyAuthScheme " + token, | ||
| cookie: GA | ||
| } | ||
| }; | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 200, "Ignores Google Analytics Cookie"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Valid Google Analytics cookie should be ignored (BAD Header Token) - custom parameters", function(t) { | ||
| var GA = "gwcm=%7B%22expires%22%3Anull%2C%22clabel%22%3A%22SbNVCILRtFcQwcrE6gM%22%2C%22backoff%22%3A1437241242%7D; _ga=GA1.2.1363734468.1432273334"; | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, 'invalid'); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { | ||
| authorization: "MyAuthScheme " + token, | ||
| cookie: GA | ||
| } | ||
| }; | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 401, "Ignores GA but Invalid Auth Header still rejected"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| // Supply a VALID Token in Cookie A-N-D valid GA in Cookie!! | ||
| test("Valid Google Analytics cookie should be ignored (BAD Header Token) - custom parameters", function(t) { | ||
| var GA = "gwcm=%7B%22expires%22%3Anull%2C%22clabel%22%3A%22SbNVCILRtFcQwcrE6gM%22%2C%22backoff%22%3A1437241242%7D; _ga=GA1.2.1363734468.1432273334"; | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { | ||
| cookie: "customCookieKey=" + token + '; ' + GA | ||
| } | ||
| }; | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 200, "Valid Cookie Token Succeeds (Ignores GA)"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Attempt to access restricted content (with an INVALID URL Token) - custom parameters", function(t) { | ||
| var token = "?customUrlKey=my.invalid.token"; | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado" + token | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 401, "INVALID Token should fail"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Try using an incorrect secret to sign the JWT - custom parameters", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, 'incorrectSecret'); | ||
| token = "?customUrlKey=" + token; | ||
| // console.log(" - - - - - - token - - - - -") | ||
| // console.log(token); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado" + token | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 401, "URL Token signed with incorrect key fails"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("URL Token is well formed but is allowed=false so should be denied - custom parameters", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| // var token = jwt.sign({ "id": 1 ,"name":"Old Greg" }, 'incorrectSecret'); | ||
| var token = JWT.sign({ id: 321, "name": "Old Gregg" }, secret); | ||
| token = "?customUrlKey=" + token; | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado" + token | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 401, "User is Denied"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Access restricted content (with VALID Token) - custom parameters", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| token = "?customUrlKey=" + token; | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado" + token | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 200, "VALID Token should succeed!"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Attempt to access restricted content using inVALID header tokenType - custom parameters", function(t) { | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, 'badsecret'); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { Authorization: "InvalidAuthScheme " + token } | ||
| }; | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 401, "Invalid token should error!"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Access restricted content (with VALID Token and header tokenType) - custom parameters", function(t) { | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { Authorization: "MyAuthScheme " + token } | ||
| }; | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 200, "VALID Token should succeed!"); | ||
| t.end(); | ||
| }); | ||
| }); |
| var test = require('tape'); | ||
| var Hapi = require('hapi'); | ||
| var JWT = require('jsonwebtoken'); | ||
| var secret = 'NeverShareYourSecret'; | ||
| var keyDict = { 5678: secret }; | ||
| test('When using a custom header key full token payload (header + payload + signature) is available to key lookup function using completeToken option', function (t) { | ||
| var server = new Hapi.Server(); | ||
| server.connection(); | ||
| server.register(require('../'), function (err) { | ||
| t.ifError(err, 'No error registering hapi-auth-jwt2 plugin'); | ||
| server.auth.strategy('jwt', 'jwt', { | ||
| key: function (decoded, callback) { | ||
| var signatureKey = keyDict[decoded.header.x5t]; // Look dynamically for key based on JWT header field | ||
| return callback(null, signatureKey); | ||
| }, | ||
| complete: true, | ||
| validateFunc: function (decoded, request, callback) { | ||
| return callback(null, true); | ||
| }, | ||
| verifyOptions: {algorithms: ['HS256']}, | ||
| headerKey: 'auths' | ||
| }); | ||
| server.route({ | ||
| method: 'POST', | ||
| path: '/', | ||
| handler: function (request, reply) { return reply('Ok'); }, | ||
| config: { auth: 'jwt' } | ||
| }); | ||
| var options = { | ||
| method: 'POST', | ||
| url: '/', | ||
| headers: {auths: JWT.sign({ id: 1234 }, secret, { header: { x5t: 5678 } })} // set custom JWT header field "x5t" | ||
| }; | ||
| server.inject(options, function (response) { | ||
| t.equal(response.statusCode, 200, 'Server returned 200 status'); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| }); |
| var test = require('tape'); | ||
| var JWT = require('jsonwebtoken'); | ||
| var server = require('./dynamic_key_server'); // test server which in turn loads our module | ||
| test("Access restricted content with a valid token and tenant", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| var token = JWT.sign({ id: 123, "name": "Charlie", "tenant": "dunderMifflin" }, 'michaelscott'); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| console.log(" - - - - RESPONSE: "); | ||
| console.log(response.result); | ||
| t.equal(response.statusCode, 200, "VALID Token should succeed!"); | ||
| t.equal(response.result.data.additional, 'something extra here if needed', 'extraInfo should be passed through'); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Access restricted content with an invalid token and tenant", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| var token = JWT.sign({ id: 123, "name": "Charlie", "tenant": "dunderMifflin" }, 'dwightschrute'); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| console.log(" - - - - RESPONSE: "); | ||
| console.log(response.result); | ||
| t.equal(response.statusCode, 401, "INVALID Token should fail!"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Access restricted content with a valid token and tenant but user is not allowed", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| var token = JWT.sign({ id: 321, "name": "Old Gregg", "tenant": "wernhamHogg" }, 'davidbrent'); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| console.log(" - - - - RESPONSE: "); | ||
| console.log(response.result); | ||
| t.equal(response.statusCode, 401, "Not allowed user should fail!"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Access restricted content without tenant specified in token", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, 'michaelscott'); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| console.log(" - - - - RESPONSE: "); | ||
| console.log(response.result); | ||
| t.equal(response.statusCode, 400, "No tenant specified should fail!"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Access restricted content with non-existent tenant specified", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| var token = JWT.sign({ id: 123, "name": "Charlie", "tenant": "princeFamilyPaper" }, 'michaelscott'); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| console.log(" - - - - RESPONSE: "); | ||
| console.log(response.result); | ||
| t.equal(response.statusCode, 401, "No tentant found should fail!"); | ||
| t.end(); | ||
| }); | ||
| }); |
| var test = require('tape'); | ||
| var JWT = require('jsonwebtoken'); | ||
| // var secret = 'NeverShareYourSecret'; | ||
| var server = require('./error_func_server'); // test server which in turn loads our module | ||
| test("Access a route that has no auth strategy", function(t) { | ||
| var options = { | ||
| method: "GET", | ||
| url: "/" | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 200, "GET / still works without token."); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("customVerify simulate error condition", function(t) { | ||
| var payload = { id: 123, "name": "Charlie", error: true } | ||
| var token = JWT.sign(payload, 'SecretDoesNOTGetVerified'); | ||
| var options = { | ||
| method: "GET", | ||
| url: "/required", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 500, "customVerify force error"); | ||
| t.equal(response.result.message, "An internal server error occurred", "GET /required with forced error that has not been customised"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("customVerify simulate error condition but is safely not customised", function(t) { | ||
| var payload = { id: 123, "name": "Charlie", custom_error: 'ignore'} | ||
| var token = JWT.sign(payload, 'SecretDoesNOTGetVerified'); | ||
| var options = { | ||
| method: "GET", | ||
| url: "/required", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 500, "customVerify force error"); | ||
| t.equal(response.result.message, "An internal server error occurred", "GET /required with forced error that has not been customised"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("customVerify with fail condition", function(t) { | ||
| var payload = { id: 123, "name": "Charlie", some_property: false } | ||
| var token = JWT.sign(payload, 'SecretDoesNOTGetVerified'); | ||
| var options = { | ||
| method: "GET", | ||
| url: "/required", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 401, "GET /required with customVerify rejected"); | ||
| t.equal(response.result.message, "Invalid credentials mate", "GET /required with customVerify rejected and customised error message"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Custom Verification in 'try' mode ", function(t) { | ||
| var payload = { id: 123, "name": "Charlie", some_property: true } | ||
| var token = JWT.sign(payload, 'SecretDoesNOTGetVerified'); | ||
| var options = { | ||
| method: "GET", | ||
| url: "/try", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.result.id, payload.id, 'Decoded JWT returned by handler'); | ||
| t.equal(response.statusCode, 200, "GET /try bypasses verification"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Custom Verification in 'optional' mode ", function(t) { | ||
| var payload = { id: 234, "name": "Oscar", some_property: true } | ||
| var token = JWT.sign(payload, 'SecretDoesNOTGetVerified'); | ||
| var options = { | ||
| method: "GET", | ||
| url: "/optional", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.result.id, payload.id, 'Decoded JWT returned by handler'); | ||
| t.equal(response.statusCode, 200, "GET /optional bypasses verification"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Custom Verification in 'required' mode ", function(t) { | ||
| var payload = { id: 345, "name": "Romeo", some_property: true } | ||
| var token = JWT.sign(payload, 'AnyStringWillDo'); | ||
| var options = { | ||
| method: "GET", | ||
| url: "/required", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| // console.log(response.result); | ||
| var credentials = JSON.parse(JSON.stringify(response.result)); | ||
| t.equal(credentials.id, payload.id, 'Decoded JWT is available in handler'); | ||
| t.equal(response.statusCode, 200, "GET /required bypasses verification"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| var test = require('tape'); | ||
| var JWT = require('jsonwebtoken'); | ||
| var secret = 'NeverShareYourSecret'; | ||
| var server = require('./scheme-response-server'); // test server which in turn loads our module | ||
| test("Attempt to access restricted content (without auth token)", function(t) { | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado" | ||
| }; | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 401, "No Token should fail"); | ||
| t.equal(response.headers.authorization, undefined, 'Invalid requests should not be calling the response function'); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Attempt to access restricted content (with an INVALID Token)", function(t) { | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { authorization: "Bearer fails.validation" } | ||
| }; | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 401, "INVALID Token should fail"); | ||
| t.equal(response.headers.authorization, undefined, 'Invalid requests should not be calling the response function'); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Access restricted content (with VALID Token)", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 200, "VALID Token should succeed!"); | ||
| t.equal(response.headers.authorization, 'from scheme response function', 'Valid request should finish by calling response function'); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Auth mode 'required' should require authentication header", function(t) { | ||
| var options = { | ||
| method: "POST", | ||
| url: "/required" | ||
| }; | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 401, "No token header should fail in auth 'required' mode"); | ||
| t.equal(response.headers.authorization, undefined, 'Invalid requests should not be calling the response function'); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Auth mode 'required' should should pass with valid token", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/required", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 200, "Valid token should succeed!"); | ||
| t.equal(response.headers.authorization, 'from scheme response function', 'Valid request should finish by calling response function'); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Scheme should set token in request.auth.token", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| var options = { | ||
| method: "GET", | ||
| url: "/token", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| server.inject(options, function(response) { | ||
| t.equal(response.result, token, 'Token is accesible from handler'); | ||
| t.equal(response.headers.authorization, 'from scheme response function', 'Valid request should finish by calling response function'); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Testing an error thrown from the scheme\'s response function", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| var options = { | ||
| method: "GET", | ||
| url: "/token", | ||
| headers: { | ||
| authorization: "Bearer " + token, | ||
| error: 'true' | ||
| } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 500, 'A server error happens in the scheme\'s response function'); | ||
| t.end(); | ||
| }); | ||
| }); |
| var test = require('tape'); | ||
| var JWT = require('jsonwebtoken'); | ||
| var secret = 'NeverShareYourSecret'; // set by ENV Variable | ||
| var server = require('./scopes_server'); // test server which in turn loads our module | ||
| test("Access restricted content using scopes (with VALID Token and VALID scope)", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado-with-scope", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| console.log(" - - - - RESPONSE: "); | ||
| console.log(response.result); | ||
| t.equal(response.statusCode, 200, "VALID Token should succeed!"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Access restricted content using scopes (with VALID Token and INVALID scope)", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| var token = JWT.sign({ id: 321, "name": "Old Gregg" }, secret); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado-with-scope", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| console.log(" - - - - RESPONSE: "); | ||
| console.log(response.result); | ||
| t.equal(response.statusCode, 401, "Denied"); | ||
| t.end(); | ||
| }); | ||
| }); |
| var test = require('tape'); | ||
| var JWT = require('jsonwebtoken'); | ||
| var secret = 'NeverShareYourSecret'; | ||
| var server = require('./basic_server.js'); | ||
| test("Attempt to access restricted content (without auth token)", function(t) { | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado" | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 401, "No Token supplied > fails (as expected)"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Attempt to access restricted content (with an INVALID URL Token)", function(t) { | ||
| var token = "?token=my.invalid.token"; | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado" + token | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 401, "INVALID Token should fail"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Try using an incorrect secret to sign the JWT", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, 'incorrectSecret'); | ||
| token = "?token=" + token; | ||
| // console.log(" - - - - - - token - - - - -") | ||
| // console.log(token); | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado" + token | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 401, "URL Token signed with incorrect key fails"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("URL Token is well formed but is allowed=false so should be denied", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| // var token = jwt.sign({ "id": 1 ,"name":"Old Greg" }, 'incorrectSecret'); | ||
| var token = JWT.sign({ id: 321, "name": "Old Gregg" }, secret); | ||
| token = "?token=" + token; | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado" + token | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 401, "User is Denied"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Access restricted content (with VALID Token)", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| token = "?token=" + token; | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privado" + token | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 200, "VALID Token should succeed!"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Using route with urlKey=false should be denied", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| token = "?token=" + token; | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privadonourl" + token | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 401, "No urlKey configured so URL-Tokens should be denied"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Using route with urlKey='' should be denied", function(t) { | ||
| // use the token as the 'authorization' header in requests | ||
| var token = JWT.sign({ id: 123, "name": "Charlie" }, secret); | ||
| token = "?=" + token; | ||
| var options = { | ||
| method: "POST", | ||
| url: "/privadonourl2" + token | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 401, "No urlKey configured so URL-Tokens should be denied"); | ||
| t.end(); | ||
| }); | ||
| }); |
| var test = require('tape'); | ||
| var Hapi = require('hapi'); | ||
| var JWT = require('jsonwebtoken'); | ||
| var secret = 'NeverShareYourSecret'; | ||
| test('Should respond with 500 series error when validateFunc errs', function (t) { | ||
| var server = new Hapi.Server(); | ||
| server.connection(); | ||
| server.register(require('../'), function (err) { | ||
| t.ifError(err, 'No error registering hapi-auth-jwt2 plugin'); | ||
| server.auth.strategy('jwt', 'jwt', { | ||
| key: secret, | ||
| validateFunc: function (decoded, request, callback) { | ||
| return callback(new Error('ASPLODE')); | ||
| }, | ||
| verifyOptions: {algorithms: ['HS256']} | ||
| }); | ||
| server.route({ | ||
| method: 'POST', | ||
| path: '/privado', | ||
| handler: function (req, reply) { return reply('PRIVADO'); }, | ||
| config: { auth: 'jwt' } | ||
| }); | ||
| var options = { | ||
| method: 'POST', | ||
| url: '/privado', | ||
| headers: {Authorization: JWT.sign({id: 138, name: 'Test'}, secret)} | ||
| }; | ||
| server.inject(options, function (response) { | ||
| t.equal(response.statusCode, 500, 'Server returned 500 for validateFunc error'); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| }); |
| var test = require('tape'); | ||
| var JWT = require('jsonwebtoken'); | ||
| // var secret = 'NeverShareYourSecret'; | ||
| var server = require('./verify_func_server'); // test server which in turn loads our module | ||
| test("Access a route that has no auth strategy", function(t) { | ||
| var options = { | ||
| method: "GET", | ||
| url: "/" | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 200, "GET / still works without token."); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("customVerify simulate error condition", function(t) { | ||
| var payload = { id: 123, "name": "Charlie", error: true } | ||
| var token = JWT.sign(payload, 'SecretDoesNOTGetVerified'); | ||
| var options = { | ||
| method: "GET", | ||
| url: "/required", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 500, "customVerify force error"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("customVerify with fail condition", function(t) { | ||
| var payload = { id: 123, "name": "Charlie", some_property: false } | ||
| var token = JWT.sign(payload, 'SecretDoesNOTGetVerified'); | ||
| var options = { | ||
| method: "GET", | ||
| url: "/required", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.statusCode, 401, "GET /required with customVerify rejected"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Custom Verification in 'try' mode ", function(t) { | ||
| var payload = { id: 123, "name": "Charlie", some_property: true } | ||
| var token = JWT.sign(payload, 'SecretDoesNOTGetVerified'); | ||
| var options = { | ||
| method: "GET", | ||
| url: "/try", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.result.id, payload.id, 'Decoded JWT returned by handler'); | ||
| t.equal(response.statusCode, 200, "GET /try bypasses verification"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Custom Verification in 'optional' mode ", function(t) { | ||
| var payload = { id: 234, "name": "Oscar", some_property: true } | ||
| var token = JWT.sign(payload, 'SecretDoesNOTGetVerified'); | ||
| var options = { | ||
| method: "GET", | ||
| url: "/optional", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| t.equal(response.result.id, payload.id, 'Decoded JWT returned by handler'); | ||
| t.equal(response.statusCode, 200, "GET /optional bypasses verification"); | ||
| t.end(); | ||
| }); | ||
| }); | ||
| test("Custom Verification in 'required' mode ", function(t) { | ||
| var payload = { id: 345, "name": "Romeo", some_property: true } | ||
| var token = JWT.sign(payload, 'AnyStringWillDo'); | ||
| var options = { | ||
| method: "GET", | ||
| url: "/required", | ||
| headers: { authorization: "Bearer " + token } | ||
| }; | ||
| // server.inject lets us simulate an http request | ||
| server.inject(options, function(response) { | ||
| // console.log(response.result); | ||
| var credentials = JSON.parse(JSON.stringify(response.result)); | ||
| t.equal(credentials.id, payload.id, 'Decoded JWT is available in handler'); | ||
| t.equal(response.statusCode, 200, "GET /required bypasses verification"); | ||
| t.end(); | ||
| }); | ||
| }); |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
110433
3.2%2046
0.05%635
12.99%1
Infinity%Updated
Updated