Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: mikenicholson/passport-jwt
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 6ff2a4a63ff6e3475fc0fb28207221e9ca4d3d48
Choose a base ref
...
head repository: mikenicholson/passport-jwt
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 8f543a96f70c8356a13003c2c433b30a62f53a2b
Choose a head ref

Commits on Jan 14, 2017

  1. fix some formatting

    jacksonhoose authored Jan 14, 2017
    Copy the full SHA
    b0cbe8b View commit details

Commits on Jan 15, 2017

  1. Merge pull request #92 from jacksonhoose/patch-1

    fix some formatting
    mikenicholson authored Jan 15, 2017
    Copy the full SHA
    82aee9d View commit details

Commits on Mar 12, 2017

  1. Copy the full SHA
    c135b28 View commit details

Commits on Mar 23, 2017

  1. Add support for secret/key provider

    Greg Poole committed Mar 23, 2017
    Copy the full SHA
    fbbf17e View commit details

Commits on Mar 24, 2017

  1. Change from a promise to a callback, update docs

    Greg Poole committed Mar 24, 2017
    Copy the full SHA
    3b55a13 View commit details
  2. Fix pointless whitepsace changes

    Greg Poole committed Mar 24, 2017
    Copy the full SHA
    4fb82ff View commit details

Commits on Mar 25, 2017

  1. Add all versions supported by passportjs

    Plus a few new ones that are not in the passportjs .travis.yml yet.
    mikenicholson committed Mar 25, 2017
    Copy the full SHA
    5b9d0e4 View commit details
  2. These versions are too old.

    No plan to support them anyways.
    mikenicholson committed Mar 25, 2017
    Copy the full SHA
    b9ff244 View commit details

Commits on Mar 26, 2017

  1. Fix failing tests

    Greg Poole committed Mar 26, 2017
    Copy the full SHA
    a698173 View commit details

Commits on Mar 27, 2017

  1. Copy the full SHA
    ba75de2 View commit details
  2. Copy the full SHA
    5b8b5f3 View commit details
  3. Copy the full SHA
    2a0f01b View commit details
  4. Copy the full SHA
    2eba070 View commit details

Commits on May 7, 2017

  1. Enhancement to options:

    Added `jsonWebTokenOptions` to options, which allows one to pass
    additional options to node-jsonwebtoken verifier. This way there
    won't be a need to change passport-jwt for any other custom
    option used in the verifier.
    itayadler committed May 7, 2017
    2
    Copy the full SHA
    c5df9c2 View commit details

Commits on May 9, 2017

  1. Copy the full SHA
    09673a9 View commit details

Commits on Jun 15, 2017

  1. Copy the full SHA
    39af785 View commit details

Commits on Jul 24, 2017

  1. Copy the full SHA
    b1d7ccc View commit details
  2. Calculate auth_scheme.toLowerCase() once

    No need to do this for every request.
    mikenicholson committed Jul 24, 2017
    Copy the full SHA
    d127fd8 View commit details
  3. Merge branch 'pr-118-case-insensitive-auth-scheme'

    Make comparison of scheme in auth header case-insensitive
    Closes #118
    mikenicholson committed Jul 24, 2017
    Copy the full SHA
    c1dccf8 View commit details
  4. Copy the full SHA
    4a7416c View commit details
  5. Merge branch 'pr-113-jwtOptions'

    Added jsonWebTokenOptions to options, which allows one to pass
    additional options to node-jsonwebtoken verifier. This way there
    won't be a need to change passport-jwt for any other custom
    option used in the verifier.
    
    Closes #113
    mikenicholson committed Jul 24, 2017
    Copy the full SHA
    98a7a09 View commit details

Commits on Jul 28, 2017

  1. Copy the full SHA
    b3846ef View commit details
  2. Cleanup of PR #108.

    Moves the logic that calls secretOrKeyProvider out of verify_jwt.js
    and back into lib/strategy.js. verify_jwt.js was intended to be a
    simple call-through function for the real verfier from jsonwebtoken.
    
    Changes the signature of secretOrKeyProvider to (request, token, done)
    from (token, done) to support a wider range of use cases.
    
    Updates tests for the above behavior.
    mikenicholson committed Jul 28, 2017
    Copy the full SHA
    a236e40 View commit details
  3. Copy the full SHA
    1bb3d5b View commit details
  4. Copy the full SHA
    ef0cecd View commit details
  5. Travis docs don't specifically mention v8

    but will this work?
    mikenicholson committed Jul 28, 2017
    Copy the full SHA
    80e049c View commit details

Commits on Aug 2, 2017

  1. Get rid of JWT as the default auth scheme.

    Per #87 'jwt' was not a great choice of default value for the
    authorization scheme since RFC6750 explicitly states that 'bearer'
    is the proper scheme, at least in the context of OAuth 2.0.
    
    Since this change breaks backwards compatibility I tried to be very
    explicit.  extractors.fromAuthHeader() was removed and replaced with
    the more explicit 'extractors.fromAuthHeaderAsBearerToken()'.
    
    Anyone wanting to maintain passport-jwt 2.* behavior may use the
    follinwg extractor instead of fromAuthHeader():
    
        extractors.fromAuthHeaderWithScheme('jwt')
    
    The legacy (v 1.*) extractor, extractors.versionOneCompatibilit() still
    iuses 'JWT' as the default auth scheme.
    
    Fixes #87
    mikenicholson committed Aug 2, 2017
    Copy the full SHA
    d5af311 View commit details

Commits on Aug 16, 2017

  1. Copy the full SHA
    3a07c77 View commit details
  2. Merge branch 'pr108-secret-key-provider'

    Adds ability for secretOrKey to be provided by a function
    called on every request
    mikenicholson committed Aug 16, 2017
    Copy the full SHA
    cfa4db3 View commit details
  3. Update package version

    mikenicholson committed Aug 16, 2017
    Copy the full SHA
    28ffbb0 View commit details

Commits on Oct 16, 2017

  1. Copy the full SHA
    cfb13c0 View commit details

Commits on Oct 27, 2017

  1. Copy the full SHA
    5fc1cd8 View commit details
  2. Copy the full SHA
    3401015 View commit details
  3. Copy the full SHA
    f39b87f View commit details
  4. Copy the full SHA
    6d4b3fa View commit details

Commits on Dec 26, 2017

  1. Copy the full SHA
    d2d950e View commit details
  2. Copy the full SHA
    685fffe View commit details

Commits on Mar 13, 2018

  1. Update jsonwebtoken dependency to latest.

    Add package-lock.json as well.
    mikenicholson committed Mar 13, 2018
    Copy the full SHA
    5497660 View commit details
  2. Copy the full SHA
    f381cea View commit details
  3. Update version to 4.0.0

    mikenicholson committed Mar 13, 2018
    Copy the full SHA
    8f543a9 View commit details
Showing with 1,249 additions and 136 deletions.
  1. +9 −3 .travis.yml
  2. +28 −56 README.md
  3. +70 −0 docs/migrating.md
  4. +7 −5 lib/extract_jwt.js
  5. +24 −0 lib/helpers/assign.js
  6. +59 −44 lib/strategy.js
  7. +1 −1 lib/verify_jwt.js
  8. +913 −0 package-lock.json
  9. +2 −2 package.json
  10. +4 −0 test/auth_header-test.js
  11. +13 −4 test/extrators-test.js
  12. +12 −1 test/strategy-init-test.js
  13. +21 −7 test/strategy-validation-test.js
  14. +86 −13 test/strategy-verify-test.js
12 changes: 9 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
language: node_js
node_js:
- "0.10"
- "8"
- "7"
- "6"
- "6.1"
- "5.11"
- "5"
- "4"
- "3" # io.js
- "2" # io.js
- "1" # io.js
- "0.12"
- "0.10"
84 changes: 28 additions & 56 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@


# passport-jwt

[![Build Status](https://travis-ci.org/themikenicholson/passport-jwt.svg?branch=master)](https://travis-ci.org/themikenicholson/passport-jwt)
[![Code Climate](https://codeclimate.com/github/themikenicholson/passport-jwt/badges/gpa.svg)](https://codeclimate.com/github/themikenicholson/passport-jwt)

A [Passport](http://passportjs.org/) strategy for authenticating with a
[JSON Web Token](http://jwt.io).

This module lets you authenticate endpoints using a JSON web token. It is
intended to be used to secure RESTful endpoints without sessions.

## Supported By

If you want to quickly add secure token-based authentication to Node.js apps, feel free to check out Auth0's Node.js SDK and free plan at [auth0.com/overview](https://auth0.com/overview?utm_source=GHsponsor&utm_medium=GHsponsor&utm_campaign=passport-jwt&utm_content=auth) <img alt='Auth0 Logo' src='https://s3.amazonaws.com/passport-jwt-img/Auth0+logo.svg'/>

## Install

npm install passport-jwt
@@ -25,12 +28,15 @@ The JWT authentication strategy is constructed as follows:
`options` is an object literal containing options to control how the token is
extracted from the request or verified.

* `secretOrKey` is a REQUIRED string or buffer containing the secret
* `secretOrKey` is a string or buffer containing the secret
(symmetric) or PEM-encoded public key (asymmetric) for verifying the token's
signature.

signature. REQUIRED unless `secretOrKeyProvider` is provided.
* `secretOrKeyProvider` is a callback in the format `function secretOrKeyProvider(request, rawJwtToken, done)`,
which should call `done` with a secret or PEM-encoded public key (asymmetric) for the given key and request combination.
`done` accepts arguments in the format `function done(err, secret)`. Note it is up to the implementer to decode rawJwtToken.
REQUIRED unless `secretOrKey` is provided.
* `jwtFromRequest` (REQUIRED) Function that accepts a request as the only
parameter and returns either the JWT as a string or *null*. See
parameter and returns either the JWT as a string or *null*. See
[Extracting the JWT from the request](#extracting-the-jwt-from-the-request) for
more details.
* `issuer`: If defined the token issuer (iss) will be verified against this
@@ -41,6 +47,8 @@ extracted from the request or verified.
* `ignoreExpiration`: if true do not validate the expiration of the token.
* `passReqToCallback`: If true the request will be passed to the verify
callback. i.e. verify(request, jwt_payload, done_callback).
* `jsonWebTokenOptions`: passport-jwt is verifying the token using [jsonwebtoken](https://github.com/auth0/node-jsonwebtoken).
Pass here an options object for any other option you can pass the jsonwebtoken verifier. (i.e maxAge)

`verify` is a function with the parameters `verify(jwt_payload, done)`

@@ -49,25 +57,25 @@ extracted from the request or verified.
done(error, user, info)

An example configuration which reads the JWT from the http
Authorization header with the scheme 'JWT':
Authorization header with the scheme 'bearer':

```js
var JwtStrategy = require('passport-jwt').Strategy,
ExtractJwt = require('passport-jwt').ExtractJwt;
var opts = {}
opts.jwtFromRequest = ExtractJwt.fromAuthHeader();
opts.jwtFromRequest = ExtractJwt.fromAuthHeaderAsBearerToken();
opts.secretOrKey = 'secret';
opts.issuer = "accounts.examplesoft.com";
opts.audience = "yoursite.net";
opts.issuer = 'accounts.examplesoft.com';
opts.audience = 'yoursite.net';
passport.use(new JwtStrategy(opts, function(jwt_payload, done) {
User.findOne({id: jwt_payload.sub}, function(err, user) {
if (err) {
return done(err, false);
}
if (user) {
done(null, user);
return done(null, user);
} else {
done(null, false);
return done(null, false);
// or you could create a new account
}
});
@@ -81,7 +89,7 @@ possible the JWT is parsed from the request by a user-supplied callback passed i
`jwtFromRequest` parameter. This callback, from now on referred to as an extractor,
accepts a request object as an argument and returns the encoded JWT string or *null*.

#### Included extractors
#### Included extractors

A number of extractor factory functions are provided in passport-jwt.ExtractJwt. These factory
functions return a new extractor configured with the given parameters.
@@ -94,15 +102,15 @@ functions return a new extractor configured with the given parameters.
URL query parameter.
* ```fromAuthHeaderWithScheme(auth_scheme)``` creates a new extractor that looks for the JWT in the
authorization header, expecting the scheme to match auth_scheme.
* ```fromAuthHeader()``` creates a new extractor that looks for the JWT in the authorization header
with the scheme 'JWT'
* ```fromAuthHeaderAsBearerToken()``` creates a new extractor that looks for the JWT in the authorization header
with the scheme 'bearer'
* ```fromExtractors([array of extractor functions])``` creates a new extractor using an array of
extractors provided. Each extractor is attempted in order until one returns a token.

### Writing a custom extractor function

If the supplied extractors don't meet your needs you can easily provide your own callback. For
example, if you are using the cookie-parser middleware and want to extract the JWT in a cookie
example, if you are using the cookie-parser middleware and want to extract the JWT in a cookie
you could use the following function as the argument to the jwtFromRequest option:

```
@@ -121,7 +129,7 @@ var cookieExtractor = function(req) {
Use `passport.authenticate()` specifying `'JWT'` as the strategy.

```js
app.post('/profile', passport.authenticate('jwt', { session: false}),
app.post('/profile', passport.authenticate('jwt', { session: false }),
function(req, res) {
res.send(req.user.profile);
}
@@ -145,46 +153,10 @@ Finally, the URL query parameters will be checked for a field matching either
`options.tokenQueryParameterName` or `auth_token` if the option was not
specified.

## Migrating from version 1.x.x to 2.x.x

The v2 API is not backwards compatible with v1, specifically with regards to the introduction
of the concept of JWT extractor functions. If you require the legacy behavior in v1 you can use
the extractor function ```versionOneCompatibility(options)```

*options* is an object with any of the three custom JWT extraction options present in the v1
constructor:
* `tokenBodyField`: Field in a request body to search for the JWT.
Default is auth_token.
* `tokenQueryParameterName`: Query parameter name containing the token.
Default is auth_token.
* `authScheme`: Expected authorization scheme if token is submitted through
the HTTP Authorization header. Defaults to JWT

If in v1 you constructed the strategy like this:

```js
var JwtStrategy = require('passport-jwt').Strategy;
var opts = {}
opts.tokenBodyField = "MY_CUSTOM_BODY_FIELD";
opts.secretOrKey = 'secret';
opts.issuer = "accounts.examplesoft.com";
opts.audience = "yoursite.net";
passport.use(new JwtStrategy(opts, verifyFunction));
```

Identical behavior can be achieved under v2 with the versionOneCompatibility extractor:

```js
var JwtStrategy = require('passport-jwt').Strategy,
ExtractJwt = require('passport-jwt').ExtractJwt;
var opts = {}
opts.jwtFromRequest = ExtractJwt.versionOneCompatibility({ tokenBodyField = "MY_CUSTOM_BODY_FIELD" });
opts.opts.secretOrKey = 'secret';
opts.issuer = "accounts.examplesoft.com";
opts.audience = "yoursite.net";
passport.use(new JwtStrategy(opts, verifyFunction));
```
## Migrating

The the [Migration Guide](docs/migrating.md) for help upgrading to the latest
major version of passport-jwt

## Tests

70 changes: 70 additions & 0 deletions docs/migrating.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Migration Guide

The following instructions should help in migrating to a new major version of
passport-jwt.

## Migrating from 3.x.x to 4.x.x

Version 4.0.0 was released to update [jsonwebtoken's](https://github.com/auth0/node-jsonwebtoken)
major version from v7 to v8 in order to fix a security issue (see
[#147](https://github.com/themikenicholson/passport-jwt/issues/147)).

Users of `passport-jwt` are exposed to the API of `jsonwebtoken` through the `jsonWebTokenOptions`
constructor option. Therefore, a major version rev of `jsonwebtoken` triggered a major version rev
of `passport-jwt`.

See the
[jsonwebtoken v7-v8 Migration Notes](https://github.com/auth0/node-jsonwebtoken/wiki/Migration-Notes:-v7-to-v8)
for the full details. The change in units for the `maxAge` attribute of `jsonWebTokenOptions` is
likely to impact the greatest number of `passport-jwt` users.

## Migrating from 2.x.x to 3.x.x

Version 3.0.0 removes the `ExtractJwt.fromAuthHeader()` extractor function that would extract
JWT's from `Authorization` headers with the auth scheme 'jwt'. The default authorization scheme
of 'jwt' as the was not RFC 6750 compliant. The extractor was replaced with
`ExtractJwt.fromAuthHeaderAsBearerToken()`. The removal of `ExtractJwt.fromAuthHeader()` was done
to clearly change the API so any code relying on the old API would clearly break, hopefully saving
people some debugging time.

If you want to maintain the behavior of `ExtractJwt.fromAuthHeader()` when switching to v3.3.0, simply
replace it with `ExtractJwt.fromAuthHeaderWithScheme('jwt')` in your implementation.

## Migrating from version 1.x.x to 2.x.x

The v2 API is not backwards compatible with v1, specifically with regards to the introduction
of the concept of JWT extractor functions. If you require the legacy behavior in v1 you can use
the extractor function ```versionOneCompatibility(options)```

*options* is an object with any of the three custom JWT extraction options present in the v1
constructor:
* `tokenBodyField`: Field in a request body to search for the JWT.
Default is auth_token.
* `tokenQueryParameterName`: Query parameter name containing the token.
Default is auth_token.
* `authScheme`: Expected authorization scheme if token is submitted through
the HTTP Authorization header. Defaults to JWT
If in v1 you constructed the strategy like this:

```js
var JwtStrategy = require('passport-jwt').Strategy;
var opts = {}
opts.tokenBodyField = 'MY_CUSTOM_BODY_FIELD';
opts.secretOrKey = 'secret';
opts.issuer = 'accounts.examplesoft.com';
opts.audience = 'yoursite.net';
passport.use(new JwtStrategy(opts, verifyFunction));
```

Identical behavior can be achieved under v2 with the versionOneCompatibility extractor:

```js
var JwtStrategy = require('passport-jwt').Strategy,
ExtractJwt = require('passport-jwt').ExtractJwt;
var opts = {}
opts.jwtFromRequest = ExtractJwt.versionOneCompatibility({ tokenBodyField = 'MY_CUSTOM_BODY_FIELD' });
opts.opts.secretOrKey = 'secret';
opts.issuer = 'accounts.examplesoft.com';
opts.audience = 'yoursite.net';
passport.use(new JwtStrategy(opts, verifyFunction));
```
12 changes: 7 additions & 5 deletions lib/extract_jwt.js
Original file line number Diff line number Diff line change
@@ -6,7 +6,8 @@ var url = require('url'),
// Note: express http converts all headers
// to lower case.
var AUTH_HEADER = "authorization",
DEFAULT_AUTH_SCHEME = "JWT";
LEGACY_AUTH_SCHEME = "JWT",
BEARER_AUTH_SCHEME = 'bearer';


var extractors = {};
@@ -50,12 +51,13 @@ extractors.fromUrlQueryParameter = function (param_name) {


extractors.fromAuthHeaderWithScheme = function (auth_scheme) {
var auth_scheme_lower = auth_scheme.toLowerCase();
return function (request) {

var token = null;
if (request.headers[AUTH_HEADER]) {
var auth_params = auth_hdr.parse(request.headers[AUTH_HEADER]);
if (auth_params && auth_scheme === auth_params.scheme) {
if (auth_params && auth_scheme_lower === auth_params.scheme.toLowerCase()) {
token = auth_params.value;
}
}
@@ -65,8 +67,8 @@ extractors.fromAuthHeaderWithScheme = function (auth_scheme) {



extractors.fromAuthHeader = function () {
return extractors.fromAuthHeaderWithScheme(DEFAULT_AUTH_SCHEME);
extractors.fromAuthHeaderAsBearerToken = function () {
return extractors.fromAuthHeaderWithScheme(BEARER_AUTH_SCHEME);
};


@@ -102,7 +104,7 @@ extractors.fromExtractors = function(extractors) {
* tokenQueryParameterName: Query parameter name containing the token. Default is auth_token.
*/
extractors.versionOneCompatibility = function (options) {
var authScheme = options.authScheme || DEFAULT_AUTH_SCHEME,
var authScheme = options.authScheme || LEGACY_AUTH_SCHEME,
bodyField = options.tokenBodyField || 'auth_token',
queryParam = options.tokenQueryParameterName || 'auth_token';

24 changes: 24 additions & 0 deletions lib/helpers/assign.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// note: This is a polyfill to Object.assign to support old nodejs versions (0.10 / 0.12) where
// Object.assign doesn't exist.
// Source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
module.exports = function(target, varArgs) {
if (target == null) { // TypeError if undefined or null
throw new TypeError('Cannot convert undefined or null to object');
}

var to = Object(target);

for (var index = 1; index < arguments.length; index++) {
var nextSource = arguments[index];

if (nextSource != null) { // Skip over if undefined or null
for (var nextKey in nextSource) {
// Avoid bugs when hasOwnProperty is shadowed
if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
to[nextKey] = nextSource[nextKey];
}
}
}
}
return to;
};
Loading