<commit_before># Hapi Auth with JSON Web Tokens (JWT)

The ***simplest*** authentication scheme/plugin for
[Hapi.js](http://hapijs.com/) apps using JSON Web Tokens.

[![Build Status](https://travis-ci.org/dwyl/hapi-auth-jwt2.svg "Build Status = Tests Passing")](https://travis-ci.org/dwyl/hapi-auth-jwt2)
[![Test Coverage](https://codeclimate.com/github/dwyl/hapi-auth-jwt2/badges/coverage.svg "All Lines Tested")](https://codeclimate.com/github/dwyl/hapi-auth-jwt2)
[![Code Climate](https://codeclimate.com/github/dwyl/hapi-auth-jwt2/badges/gpa.svg "No Nasty Code")](https://codeclimate.com/github/dwyl/hapi-auth-jwt2)
[![bitHound Score](https://www.bithound.io/github/dwyl/hapi-auth-jwt2/badges/score.svg)](https://www.bithound.io/github/dwyl/hapi-auth-jwt2)
[![Dependency Status](https://david-dm.org/dwyl/hapi-auth-jwt2.svg "Dependencies Checked & Updated Regularly (Security is Important!)")](https://david-dm.org/dwyl/hapi-auth-jwt2)
[![Node.js Version](https://img.shields.io/node/v/hapi-auth-jwt2.svg?style=flat "Node.js 10 & 12 and io.js latest both supported")](http://nodejs.org/download/)
[![NPM Version](https://badge.fury.io/js/hapi-auth-jwt2.svg?style=flat)](https://npmjs.org/package/hapi-auth-jwt2)
[![HAPI 8.5](http://img.shields.io/badge/hapi-8.5-brightgreen.svg "Latest Hapi.js")](http://hapijs.com)


This node.js module (Hapi plugin) lets you use JSON Web Tokens (JWTs)
for authentication in your [Hapi.js](http://hapijs.com/)
web application.

If you are totally new to JWTs, we wrote an introductory post explaining  
the concepts & benefits: https://github.com/docdis/learn-json-web-tokens

If you (or anyone on your team) are unfamiliar with **Hapi.js** we have a  
quick guide for that too: https://github.com/nelsonic/learn-hapi

## Usage

We tried to make this plugin as user (developer) friendly as possible,
but if anything is unclear, please submit any questions as issues on GitHub:

https://github.com/dwyl/hapi-auth-jwt2/issues

### Install from NPM

```sh
npm install hapi-auth-jwt2 --save
```

### Example

This basic usage example should get started:


```javascript
var Hapi = require('hapi');

var people = { // our "users database"
    1: {
      id: 1,
      name: '<NAME>'
    }
};

// bring your own validation function
var validate = function (decoded, request, callback) {

    // do your checks to see if the person is valid
    if (!people[decoded.id]) {
      return callback(null, false);
    }
    else {
      return callback(null, true);
    }
};

var server = new Hapi.Server();
server.connection({ port: 8000 });
        // include our module here ↓↓
server.register(require('hapi-auth-jwt2'), function (err) {

    if(err){
      console.log(err);
    }

    server.auth.strategy('jwt', 'jwt', true,
    { key: 'NeverShareYourSecret', // Never Share your secret key
      validateFunc: validate       // validate function defined above
    });

    server.route([
      {
        method: "GET", path: "/", config: { auth: false },
        handler: function(request, reply) {
          reply({text: 'Token not required'});
        }
      },
      {
        method: 'GET', path: '/restricted', config: { auth: 'jwt' },
        handler: function(request, reply) {
          reply({text: 'You used a Token!'})
          .header("Authorization", request.headers.authorization);
        }
      }
    ]);
});

server.start();
```

Run the server with: `node example/server.js`

Now use **curl** to access the two routes:

#### No Token Required

```sh
curl -v http://localhost:8000/
```

#### Token Required

Try to access the /*restricted* content *without* supplying a Token
(*expect* to see a ***401 error***):
```sh
curl -v http://localhost:8000/restricted
```

Now access the url using the following format:
`curl -H "Authorization: <TOKEN>" http://localhost:8000/restricted`

A here's a *valid* token you can use (*copy-paste* this command):
```sh
curl -v -H "Authorization: <KEY>" \
http://localhost:8000/restricted
```

That's it.

Write your own `validateFunc` with what ever checks you want to perform
on the **decoded** token before allowing the visitor to proceed.

### Real World Example ?

If you would like to see a "***real world example***" of this plugin in use
in a ***production*** web app (API)
please see: https://github.com/dwyl/time/tree/master/api/lib

+ **app.js** ***registering*** the **hapi-auth-jw2 plugin**:
[app.js#L13](https://github.com/dwyl/time/blob/0a5ec8711840528a4960c388825fb883fabddd76/app.js#L13)
+ telling app.js where to find our **validateFunc**tion:
[app.js#L21](https://github.com/dwyl/time/blob/0a5ec8711840528a4960c388825fb883fabddd76/app.js#L21)
+ **validateFunc**tion (how we check the JWT is still valid):
[api/lib/auth_jwt_validate.js](https://github.com/dwyl/time/blob/0a5ec8711840528a4960c388825fb883fabddd76/api/lib/auth_jwt_validate.js) looks up the person's session in our ElasticSearch Database
if the [session record is ***found*** (valid) and ***not ended***](https://github.com/dwyl/time/blob/0a5ec8711840528a4960c388825fb883fabddd76/api/lib/auth_jwt_validate.js#L12) we allow the person to see the restricted content.
+ **Signing your JWTs**: in your app you need a method to *sign* the JWTs (and put them in a database
  if that's how you are *verifying* your sessions) ours is:
  [api/lib/auth_jwt_sign.js](https://github.com/dwyl/time/blob/0a5ec8711840528a4960c388825fb883fabddd76/api/lib/auth_jwt_sign.js#L18)

If you have ***any questions*** on this please post an issue/question on GitHub:
https://github.com/dwyl/hapi-auth-jwt2/issues  
(*we are here to help get you started on your journey to **hapi**ness!*)

### Production-ready Example using Redis?

Redis is *perfect* for storing session data that needs to be checked
on every authenticated request.

If you are unfamiliar with Redis or anyone on your team needs a refresher,
please checkout: https://github.com/docdis/learn-redis

The ***code*** is at: https://github.com/dwyl/hapi-auth-jwt2-example
and with tests. please ask additional questions if unclear!

Having a more real-world example was *seconded* by [@manonthemat](https://github.com/manonthemat) see:
[hapi-auth-jwt2/issues/9](https://github.com/dwyl/hapi-auth-jwt2/issues/9)


## Documentation

- `validateFunc` - (***required***) a the function which is run once the Token has been decoded
 signature `function(decoded, request, callback)` where:
    - `decoded` - (***required***) is the ***decoded*** JWT received from the client in **request.headers.authorization**
    - `request` - (***required***) is the original ***request*** received from the client  
    - `callback` - (***required***) a callback function with the signature `function(err, isValid, credentials)` where:
        - `err` - an internal error.
        - `valid` - `true` if the JWT was valid, otherwise `false`.
        - `credentials` - (***optional***) alternative credentials to be set instead of `decoded`.

### verifyOptions let you define how to Verify the Tokens (*Optional*)

While registering the **hapi-auth-jwt2** plugin you can define
the following **verifyOptions**:

*  `ignoreExpiration` - ignore expired tokens
*  `audience` - do not enforce token [*audience*](http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html#audDef)
*  `issuer` - do not require the issuer to be valid

example:
```js
server.auth.strategy('jwt', 'jwt', true,
{ key: 'NeverShareYourSecret', // Never Share your secret key
  validateFunc: validate,      // validate function defined above
  verifyOptions: { ignoreExpiration: true }  // do not reject expired tokens
});
```

Read more about this at: [jsonwebtoken verify options]( https://github.com/auth0/node-jsonwebtoken#jwtverifytoken-secretorpublickey-options-callback)

If you prefer *not* to use any of these verifyOptions simply
do not set them when registering the plugin with your app;
they are all optional.

This feature was requested in: [issues/29](https://github.com/dwyl/hapi-auth-jwt2/issues/29)

### Authentication Modes
<commit_msg>Specifying allowed algorithms for verification. Fixes #51<commit_after># Hapi Auth with JSON Web Tokens (JWT)

The ***simplest*** authentication scheme/plugin for
[Hapi.js](http://hapijs.com/) apps using JSON Web Tokens.

[![Build Status](https://travis-ci.org/dwyl/hapi-auth-jwt2.svg "Build Status = Tests Passing")](https://travis-ci.org/dwyl/hapi-auth-jwt2)
[![Test Coverage](https://codeclimate.com/github/dwyl/hapi-auth-jwt2/badges/coverage.svg "All Lines Tested")](https://codeclimate.com/github/dwyl/hapi-auth-jwt2)
[![Code Climate](https://codeclimate.com/github/dwyl/hapi-auth-jwt2/badges/gpa.svg "No Nasty Code")](https://codeclimate.com/github/dwyl/hapi-auth-jwt2)
[![bitHound Score](https://www.bithound.io/github/dwyl/hapi-auth-jwt2/badges/score.svg)](https://www.bithound.io/github/dwyl/hapi-auth-jwt2)
[![Dependency Status](https://david-dm.org/dwyl/hapi-auth-jwt2.svg "Dependencies Checked & Updated Regularly (Security is Important!)")](https://david-dm.org/dwyl/hapi-auth-jwt2)
[![Node.js Version](https://img.shields.io/node/v/hapi-auth-jwt2.svg?style=flat "Node.js 10 & 12 and io.js latest both supported")](http://nodejs.org/download/)
[![NPM Version](https://badge.fury.io/js/hapi-auth-jwt2.svg?style=flat)](https://npmjs.org/package/hapi-auth-jwt2)
[![HAPI 8.5](http://img.shields.io/badge/hapi-8.5-brightgreen.svg "Latest Hapi.js")](http://hapijs.com)


This node.js module (Hapi plugin) lets you use JSON Web Tokens (JWTs)
for authentication in your [Hapi.js](http://hapijs.com/)
web application.

If you are totally new to JWTs, we wrote an introductory post explaining  
the concepts & benefits: https://github.com/docdis/learn-json-web-tokens

If you (or anyone on your team) are unfamiliar with **Hapi.js** we have a  
quick guide for that too: https://github.com/nelsonic/learn-hapi

## Usage

We tried to make this plugin as user (developer) friendly as possible,
but if anything is unclear, please submit any questions as issues on GitHub:

https://github.com/dwyl/hapi-auth-jwt2/issues

### Install from NPM

```sh
npm install hapi-auth-jwt2 --save
```

### Example

This basic usage example should get started:


```javascript
var Hapi = require('hapi');

var people = { // our "users database"
    1: {
      id: 1,
      name: '<NAME>'
    }
};

// bring your own validation function
var validate = function (decoded, request, callback) {

    // do your checks to see if the person is valid
    if (!people[decoded.id]) {
      return callback(null, false);
    }
    else {
      return callback(null, true);
    }
};

var server = new Hapi.Server();
server.connection({ port: 8000 });
        // include our module here ↓↓
server.register(require('hapi-auth-jwt2'), function (err) {

    if(err){
      console.log(err);
    }

    server.auth.strategy('jwt', 'jwt', true,
    { key: 'NeverShareYourSecret', // Never Share your secret key
      validateFunc: validate       // validate function defined above
    });

    server.route([
      {
        method: "GET", path: "/", config: { auth: false },
        handler: function(request, reply) {
          reply({text: 'Token not required'});
        }
      },
      {
        method: 'GET', path: '/restricted', config: { auth: 'jwt' },
        handler: function(request, reply) {
          reply({text: 'You used a Token!'})
          .header("Authorization", request.headers.authorization);
        }
      }
    ]);
});

server.start();
```

Run the server with: `node example/server.js`

Now use **curl** to access the two routes:

#### No Token Required

```sh
curl -v http://localhost:8000/
```

#### Token Required

Try to access the /*restricted* content *without* supplying a Token
(*expect* to see a ***401 error***):
```sh
curl -v http://localhost:8000/restricted
```

Now access the url using the following format:
`curl -H "Authorization: <TOKEN>" http://localhost:8000/restricted`

A here's a *valid* token you can use (*copy-paste* this command):
```sh
curl -v -H "Authorization: <KEY>" \
http://localhost:8000/restricted
```

That's it.

Write your own `validateFunc` with what ever checks you want to perform
on the **decoded** token before allowing the visitor to proceed.

### Real World Example ?

If you would like to see a "***real world example***" of this plugin in use
in a ***production*** web app (API)
please see: https://github.com/dwyl/time/tree/master/api/lib

+ **app.js** ***registering*** the **hapi-auth-jw2 plugin**:
[app.js#L13](https://github.com/dwyl/time/blob/0a5ec8711840528a4960c388825fb883fabddd76/app.js#L13)
+ telling app.js where to find our **validateFunc**tion:
[app.js#L21](https://github.com/dwyl/time/blob/0a5ec8711840528a4960c388825fb883fabddd76/app.js#L21)
+ **validateFunc**tion (how we check the JWT is still valid):
[api/lib/auth_jwt_validate.js](https://github.com/dwyl/time/blob/0a5ec8711840528a4960c388825fb883fabddd76/api/lib/auth_jwt_validate.js) looks up the person's session in our ElasticSearch Database
if the [session record is ***found*** (valid) and ***not ended***](https://github.com/dwyl/time/blob/0a5ec8711840528a4960c388825fb883fabddd76/api/lib/auth_jwt_validate.js#L12) we allow the person to see the restricted content.
+ **Signing your JWTs**: in your app you need a method to *sign* the JWTs (and put them in a database
  if that's how you are *verifying* your sessions) ours is:
  [api/lib/auth_jwt_sign.js](https://github.com/dwyl/time/blob/0a5ec8711840528a4960c388825fb883fabddd76/api/lib/auth_jwt_sign.js#L18)

If you have ***any questions*** on this please post an issue/question on GitHub:
https://github.com/dwyl/hapi-auth-jwt2/issues  
(*we are here to help get you started on your journey to **hapi**ness!*)

### Production-ready Example using Redis?

Redis is *perfect* for storing session data that needs to be checked
on every authenticated request.

If you are unfamiliar with Redis or anyone on your team needs a refresher,
please checkout: https://github.com/docdis/learn-redis

The ***code*** is at: https://github.com/dwyl/hapi-auth-jwt2-example
and with tests. please ask additional questions if unclear!

Having a more real-world example was *seconded* by [@manonthemat](https://github.com/manonthemat) see:
[hapi-auth-jwt2/issues/9](https://github.com/dwyl/hapi-auth-jwt2/issues/9)


## Documentation

- `validateFunc` - (***required***) a the function which is run once the Token has been decoded
 signature `function(decoded, request, callback)` where:
    - `decoded` - (***required***) is the ***decoded*** JWT received from the client in **request.headers.authorization**
    - `request` - (***required***) is the original ***request*** received from the client  
    - `callback` - (***required***) a callback function with the signature `function(err, isValid, credentials)` where:
        - `err` - an internal error.
        - `valid` - `true` if the JWT was valid, otherwise `false`.
        - `credentials` - (***optional***) alternative credentials to be set instead of `decoded`.

### verifyOptions let you define how to Verify the Tokens (*Optional*)

While registering the **hapi-auth-jwt2** plugin you can define
the following **verifyOptions**:

*  `ignoreExpiration` - ignore expired tokens
*  `audience` - do not enforce token [*audience*](http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html#audDef)
*  `issuer` - do not require the issuer to be valid
*  `algorithms` - list of allowed algorithms

example:
```js
server.auth.strategy('jwt', 'jwt', true,
{ key: 'NeverShareYourSecret', // Never Share your secret key
  validateFunc: validate,      // validate function defined above
  verifyOptions: { ignoreExpiration: true }  // do not reject expired tokens
});
```

Read more about this at: [jsonwebtoken verify options]( https://github.com/auth0/node-jsonwebtoken#jwtverifytoken-secretorpublickey-options-callback)

For [security reasons](https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/) you might want to specify the allowed algorithms you used when signing the tokens:
```js
server.auth.strategy('jwt', 'jwt', true,
{ key: 'NeverShareYourSecret', // Never Share your secret key
  validateFunc: validate,      // validate function defined above
  verifyOptions: { algorithms: [ 'HS256' ] }  // only allow HS256 algorithm
});
```

If you prefer *not* to use any of these verifyOptions simply
do not set them when registering the plugin with your app;
they are all optional.

This feature was requested in: [issues/29](https://github.com/dwyl/hapi-auth-jwt2/issues/29)

### Authentication Modes

{'fraction_non_alphanumeric': 0.14653716216216217, 'fraction_numerical': 0.026363416988416988, 'mean_word_length': 4.066320293398533, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 9, 'https://': 59, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1904026', 'n_tokens_mistral': 5735, 'n_tokens_neox': 5378, 'n_words': 1558}