1 |
|
2 |
|
3 | # passport-jwt
|
4 |
|
5 | [![Build Status](https://travis-ci.org/themikenicholson/passport-jwt.svg?branch=master)](https://travis-ci.org/themikenicholson/passport-jwt)
|
6 |
|
7 | A [Passport](http://passportjs.org/) strategy for authenticating with a
|
8 | [JSON Web Token](http://jwt.io).
|
9 |
|
10 | This module lets you authenticate endpoints using a JSON web token. It is
|
11 | intended to be used to secure RESTful endpoints without sessions.
|
12 |
|
13 | ## Install
|
14 |
|
15 | npm install passport-jwt
|
16 |
|
17 | ## Usage
|
18 |
|
19 | ### Configure Strategy
|
20 |
|
21 | The JWT authentication strategy is constructed as follows:
|
22 |
|
23 | new JwtStrategy(options, verify)
|
24 |
|
25 | `options` is an object literal containing options to control how the token is
|
26 | extracted from the request or verified.
|
27 |
|
28 | * `secretOrKey` is a REQUIRED string or buffer containing the secret
|
29 | (symmetric) or PEM-encoded public key (asymmetric) for verifying the token's
|
30 | signature.
|
31 |
|
32 | * `jwtFromRequest` (REQUIRED) Function that accepts a request as the only
|
33 | parameter and returns either the JWT as a string or *null*. See
|
34 | [Extracting the JWT from the request](#extracting-the-jwt-from-the-request) for
|
35 | more details.
|
36 | * `issuer`: If defined the token issuer (iss) will be verified against this
|
37 | value.
|
38 | * `audience`: If defined, the token audience (aud) will be verified against
|
39 | this value.
|
40 | * `algorithms`: List of strings with the names of the allowed algorithms. For instance, ["HS256", "HS384"].
|
41 | * `ignoreExpiration`: if true do not validate the expiration of the token.
|
42 | * `passReqToCallback`: If true the request will be passed to the verify
|
43 | callback. i.e. verify(request, jwt_payload, done_callback).
|
44 |
|
45 | `verify` is a function with the parameters `verify(jwt_payload, done)`
|
46 |
|
47 | * `jwt_payload` is an object literal containing the decoded JWT payload.
|
48 | * `done` is a passport error first callback accepting arguments
|
49 | done(error, user, info)
|
50 |
|
51 | An example configuration which reads the JWT from the http
|
52 | Authorization header with the scheme 'JWT':
|
53 |
|
54 | ```js
|
55 | var JwtStrategy = require('passport-jwt').Strategy,
|
56 | ExtractJwt = require('passport-jwt').ExtractJwt;
|
57 | var opts = {}
|
58 | opts.jwtFromRequest = ExtractJwt.fromAuthHeader();
|
59 | opts.secretOrKey = 'secret';
|
60 | opts.issuer = "accounts.examplesoft.com";
|
61 | opts.audience = "yoursite.net";
|
62 | passport.use(new JwtStrategy(opts, function(jwt_payload, done) {
|
63 | User.findOne({id: jwt_payload.sub}, function(err, user) {
|
64 | if (err) {
|
65 | return done(err, false);
|
66 | }
|
67 | if (user) {
|
68 | done(null, user);
|
69 | } else {
|
70 | done(null, false);
|
71 | // or you could create a new account
|
72 | }
|
73 | });
|
74 | }));
|
75 | ```
|
76 |
|
77 | ### Extracting the JWT from the request
|
78 |
|
79 | There are a number of ways the JWT may be included in a request. In order to remain as flexible as
|
80 | possible the JWT is parsed from the request by a user-supplied callback passed in as the
|
81 | `jwtFromRequest` parameter. This callback, from now on referred to as an extractor,
|
82 | accepts a request object as an argument and returns the encoded JWT string or *null*.
|
83 |
|
84 | #### Included extractors
|
85 |
|
86 | A number of extractor factory functions are provided in passport-jwt.ExtractJwt. These factory
|
87 | functions return a new extractor configured with the given parameters.
|
88 |
|
89 | * ```fromHeader(header_name)``` creates a new extractor that looks for the JWT in the given http
|
90 | header
|
91 | * ```fromBodyField(field_name)``` creates a new extractor that looks for the JWT in the given body
|
92 | field. You must have a body parser configured in order to use this method.
|
93 | * ```fromUrlQueryParameter(param_name)``` creates a new extractor that looks for the JWT in the given
|
94 | URL query parameter.
|
95 | * ```fromAuthHeaderWithScheme(auth_scheme)``` creates a new extractor that looks for the JWT in the
|
96 | authorization header, expecting the scheme to match auth_scheme.
|
97 | * ```fromAuthHeader()``` creates a new extractor that looks for the JWT in the authorization header
|
98 | with the scheme 'JWT'
|
99 | * ```fromExtractors([array of extractor functions])``` creates a new extractor using an array of
|
100 | extractors provided. Each extractor is attempted in order until one returns a token.
|
101 |
|
102 | ### Writing a custom extractor function
|
103 |
|
104 | If the supplied extractors don't meet your needs you can easily provide your own callback. For
|
105 | example, if you are using the cookie-parser middleware and want to extract the JWT in a cookie
|
106 | you could use the following function as the argument to the jwtFromRequest option:
|
107 |
|
108 | ```
|
109 | var cookieExtractor = function(req) {
|
110 | var token = null;
|
111 | if (req && req.cookies)
|
112 | {
|
113 | token = req.cookies['jwt'];
|
114 | }
|
115 | return token;
|
116 | };
|
117 | ```
|
118 |
|
119 | ### Authenticate requests
|
120 |
|
121 | Use `passport.authenticate()` specifying `'JWT'` as the strategy.
|
122 |
|
123 | ```js
|
124 | app.post('/profile', passport.authenticate('jwt', { session: false}),
|
125 | function(req, res) {
|
126 | res.send(req.user.profile);
|
127 | }
|
128 | );
|
129 | ```
|
130 |
|
131 | ### Include the JWT in requests
|
132 |
|
133 | The strategy will first check the request for the standard *Authorization*
|
134 | header. If this header is present and the scheme matches `options.authScheme`
|
135 | or 'JWT' if no auth scheme was specified then the token will be retrieved from
|
136 | it. e.g.
|
137 |
|
138 | Authorization: JWT JSON_WEB_TOKEN_STRING.....
|
139 |
|
140 | If the authorization header with the expected scheme is not found, the request
|
141 | body will be checked for a field matching either `options.tokenBodyField` or
|
142 | `auth_token` if the option was not specified.
|
143 |
|
144 | Finally, the URL query parameters will be checked for a field matching either
|
145 | `options.tokenQueryParameterName` or `auth_token` if the option was not
|
146 | specified.
|
147 |
|
148 | ## Migrating from version 1.x.x to 2.x.x
|
149 |
|
150 | The v2 API is not backwards compatible with v1, specifically with regards to the introduction
|
151 | of the concept of JWT extractor functions. If you require the legacy behavior in v1 you can use
|
152 | the extractor function ```versionOneCompatibility(options)```
|
153 |
|
154 | *options* is an object with any of the three custom JWT extraction options present in the v1
|
155 | constructor:
|
156 | * `tokenBodyField`: Field in a request body to search for the JWT.
|
157 | Default is auth_token.
|
158 | * `tokenQueryParameterName`: Query parameter name containing the token.
|
159 | Default is auth_token.
|
160 | * `authScheme`: Expected authorization scheme if token is submitted through
|
161 | the HTTP Authorization header. Defaults to JWT
|
162 |
|
163 | If in v1 you constructed the strategy like this:
|
164 |
|
165 | ```js
|
166 | var JwtStrategy = require('passport-jwt').Strategy;
|
167 | var opts = {}
|
168 | opts.tokenBodyField = "MY_CUSTOM_BODY_FIELD";
|
169 | opts.secretOrKey = 'secret';
|
170 | opts.issuer = "accounts.examplesoft.com";
|
171 | opts.audience = "yoursite.net";
|
172 | passport.use(new JwtStrategy(opts, verifyFunction));
|
173 | ```
|
174 |
|
175 | Identical behavior can be achieved under v2 with the versionOneCompatibility extractor:
|
176 |
|
177 | ```js
|
178 | var JwtStrategy = require('passport-jwt').Strategy,
|
179 | ExtractJwt = require('passport-jwt').ExtractJwt;
|
180 | var opts = {}
|
181 | opts.jwtFromRequest = ExtractJwt.versionOneCompatibility({ tokenBodyField = "MY_CUSTOM_BODY_FIELD" });
|
182 | opts.opts.secretOrKey = 'secret';
|
183 | opts.issuer = "accounts.examplesoft.com";
|
184 | opts.audience = "yoursite.net";
|
185 | passport.use(new JwtStrategy(opts, verifyFunction));
|
186 | ```
|
187 |
|
188 |
|
189 | ## Tests
|
190 |
|
191 | npm install
|
192 | npm test
|
193 |
|
194 | To generate test-coverage reports:
|
195 |
|
196 | npm install -g istanbul
|
197 | npm run-script testcov
|
198 | istanbul report
|
199 |
|
200 | ## License
|
201 |
|
202 | The [MIT License](http://opensource.org/licenses/MIT)
|
203 |
|
204 | Copyright (c) 2015 Mike Nicholson
|