Skip to content

Commit

Permalink
Merge pull request #7 from solepano/addJwtOptions
Browse files Browse the repository at this point in the history
pass options to jwt.verify to be able to verify audience and issuer. Also fix example.
  • Loading branch information
dschenkelman committed Dec 12, 2016
2 parents 8f17741 + 0975c05 commit a1cdfa7
Show file tree
Hide file tree
Showing 5 changed files with 499 additions and 17 deletions.
19 changes: 18 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ JSON Web Token authentication requires verifying a signed token. The `'jwt'` sch
- `credentials` - a credentials object passed back to the application in `request.auth.credentials`. Typically, `credentials` are only
included when `isValid` is `true`, but there are cases when the application needs to know who tried to authenticate even when it fails
(e.g. with authentication mode `'try'`).
- `audience` (optional): string or array of strings of valid values for the `aud` field.
- `issuer` (optional): string or array of strings of valid values for the `iss` field.
- `algorithms` (optional): List of strings with the names of the allowed algorithms. For instance, `["HS256", "RS256"]`.
- `subject` (optional): string of valid values for the `sub` field

See the example folder for an executable example.

Expand Down Expand Up @@ -45,7 +49,7 @@ var privateKey = 'BbZJjyoXAdr8BUZuiKKARWimKfrSmQ6fv8kZ7OFfc';
var token = jwt.sign({ accountId: 123 }, privateKey);


var validate = function (decodedToken, callback) {
var validate = function (decodedToken, extraInfo, callback) {

var error,
credentials = accounts[decodedToken.accountId] || {};
Expand Down Expand Up @@ -90,3 +94,16 @@ server.register(require('hapi-auth-jwt'), function (error) {
server.start();

```

You can specify audience, issuer, algorithms and/or subject as well:

```javascript
server.auth.strategy('token', 'jwt', {
key: privateKey,
validateFunc: validate,
audience: 'http://myapi/protected',
issuer: 'http://issuer',
algorithms: ['RS256'],
subject: 'myRequiredSubject'
});
```
11 changes: 9 additions & 2 deletions example/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,17 @@ var token = jwt.sign({ accountId: 123 }, privateKey);

// use this token to build your web request. You'll need to add it to the headers as 'authorization'. And you will need to prefix it with 'Bearer '
console.log('token: ' + token);
console.log();
console.log('=== Sample call to secure endpoint: ===');
console.log("curl 'http://localhost:8080/tokenRequired' -H 'Content-Type:application/json' -H 'Authorization: Bearer " + token + "'");
console.log();
console.log('=== Sample call to public endpoint: ===');
console.log("curl 'http://localhost:8080/noTokenRequired' -H 'Content-Type:application/json'");

var validate = function (decodedToken, callback) {
var validate = function (decodedToken, extraInfo, callback) {

console.log(decodedToken); // should be {accountId : 123}.
console.log('decodedToken',decodedToken); // should be {accountId : 123}.
console.log('extraInfo',extraInfo);

if (decodedToken) {
console.log(decodedToken.accountId.toString());
Expand Down
30 changes: 20 additions & 10 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,18 @@
var Boom = require('boom');
var Hoek = require('hoek');
var jwt = require('jsonwebtoken');
var Joi = require('joi');

var optionsSchema = Joi.object().keys({
key: Joi.alternatives().try(Joi.binary(),Joi.func()).required(),
validateFunc: Joi.func(),
algorithms: Joi.array().items(Joi.string()),
audience: Joi.alternatives().try(Joi.string(),Joi.array().items(Joi.string())),
issuer: Joi.alternatives().try(Joi.string(),Joi.array().items(Joi.string())),
subject: Joi.string()
}).label('jwt auth strategy options');

// Declare internals

var internals = {};


Expand All @@ -26,8 +34,11 @@ function isFunction(functionToCheck) {

internals.implementation = function (server, options) {

Hoek.assert(options, 'Missing jwt auth strategy options');
Hoek.assert(options.key, 'Missing required private key in configuration');
var validationResult = Joi.validate(options, optionsSchema);

if (validationResult.error){
throw new Error(validationResult.error.message);
}

var settings = Hoek.clone(options);

Expand Down Expand Up @@ -62,13 +73,11 @@ internals.implementation = function (server, options) {

getKey(request, token, function(err, key, extraInfo){
if (err) { return reply(Boom.wrap(err)); }

// handle err
jwt.verify(token, key, function(err, decoded) {
if(err && err.message === 'jwt expired') {
return reply(Boom.unauthorized('Expired token received for JSON Web Token validation', 'Bearer'));
} else if (err) {
return reply(Boom.unauthorized('Invalid signature received for JSON Web Token validation', 'Bearer'));
jwt.verify(token, key, settings, function(err, decoded) {

if(err) {
return reply(Boom.unauthorized( 'JSON Web Token validation failed: ' + err.message, 'Bearer'));
}

if (!settings.validateFunc) {
Expand Down Expand Up @@ -102,5 +111,6 @@ internals.implementation = function (server, options) {
}
};

return scheme;
return scheme;

};
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@
"dependencies": {
"boom": "2.x.x",
"hoek": "2.x.x",
"joi": "^10.0.1",
"jsonwebtoken": "^5.4.1"
},
"devDependencies": {
"boom": "2.x.x",
"code": "1.x.x",
"hapi": "11.x.x",
"lab": "5.x.x",
Expand Down
Loading

0 comments on commit a1cdfa7

Please sign in to comment.