-
Notifications
You must be signed in to change notification settings - Fork 126
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #183 from HomePass/master
Add custom error raising.
- Loading branch information
Showing
5 changed files
with
217 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
var Hapi = require('hapi'); | ||
var secret = 'NeverShareYourSecret'; | ||
|
||
// for debug options see: http://hapijs.com/tutorials/logging | ||
var debug; | ||
// debug = { debug: { 'request': ['error', 'uncaught'] } }; | ||
debug = { debug: false }; | ||
var server = new Hapi.Server(debug); | ||
server.connection(); | ||
|
||
var sendToken = function(req, reply) { | ||
return reply(req.auth.token); | ||
}; | ||
|
||
var privado = function(req, reply) { | ||
return reply(req.auth.credentials); | ||
}; | ||
|
||
// defining our own validate function lets us do something | ||
// useful/custom with the decodedToken before reply(ing) | ||
var customVerifyFunc = function (decoded, request, callback) { | ||
if(decoded.error) { | ||
return callback(new Error('customVerify fails!')); | ||
} | ||
else if (decoded.custom_error) { | ||
return callback(new Error(decoded.custom_error)); | ||
} | ||
else if (decoded.some_property) { | ||
return callback(null, true, decoded); | ||
} | ||
else { | ||
return callback(null, false, decoded); | ||
} | ||
}; | ||
|
||
var customErrorFunc = function (errorContext) { | ||
var result = errorContext; | ||
if (errorContext.message.toString().search(/ignore/) >= 0) { | ||
result = null; | ||
} else if (errorContext.errorType === 'unauthorized') { | ||
result.message = "Invalid credentials mate"; | ||
} | ||
return result; | ||
}; | ||
|
||
server.register(require('../'), function () { | ||
|
||
server.auth.strategy('jwt', 'jwt', { | ||
verifyFunc: customVerifyFunc, // no validateFunc or key required. | ||
errorFunc: customErrorFunc | ||
}); | ||
|
||
server.route([ | ||
{ method: 'GET', path: '/', handler: sendToken, config: { auth: false } }, | ||
{ method: 'GET', path: '/required', handler: privado, config: { auth: { mode: 'required', strategy: 'jwt' } } }, | ||
{ method: 'GET', path: '/optional', handler: privado, config: { auth: { mode: 'optional', strategy: 'jwt' } } }, | ||
{ method: 'GET', path: '/try', handler: privado, config: { auth: { mode: 'try', strategy: 'jwt' } } } | ||
]); | ||
|
||
}); | ||
|
||
module.exports = server; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
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(); | ||
}); | ||
}); | ||
|