JsonWebTokenError = function (message, error) { Error.call(this, message); Error.captureStackTrace(this, this.constructor); this.name = 'JsonWebTokenError'; this.message = message; if (error) this.inner = error; }
n/a
NotBeforeError = function (message, date) { JsonWebTokenError.call(this, message); this.name = 'NotBeforeError'; this.date = date; }
n/a
TokenExpiredError = function (message, expiredAt) { JsonWebTokenError.call(this, message); this.name = 'TokenExpiredError'; this.expiredAt = expiredAt; }
n/a
decode = function (jwt, options) { options = options || {}; var decoded = jws.decode(jwt, options); if (!decoded) { return null; } var payload = decoded.payload; //try parse the payload if(typeof payload === 'string') { try { var obj = JSON.parse(payload); if(typeof obj === 'object') { payload = obj; } } catch (e) { } } //return header if `complete` option is enabled. header includes claims //such as `kid` and `alg` used to select the key within a JWKS needed to //verify the signature if (options.complete === true) { return { header: decoded.header, payload: payload, signature: decoded.signature }; } return payload; }
...
var cert = fs.readFileSync('public.pem'); // get public key
jwt.verify(token, cert, { algorithms: ['RS256'] }, function (err, payload) {
// if token alg != RS256, err == invalid signature
});
```
### jwt.decode(token [, options])
(Synchronous) Returns the decoded payload without verifying if the signature is valid.
__Warning:__ This will __not__ verify whether the signature is valid. You should __not__ use this for untrusted messages. You most
likely want to use `jwt.verify` instead.
`token` is the JsonWebToken string
...
sign = function (payload, secretOrPrivateKey, options, callback) { options = options || {}; var isObjectPayload = typeof payload === 'object' && !Buffer.isBuffer(payload); var header = xtend({ alg: options.algorithm || 'HS256', typ: isObjectPayload ? 'JWT' : undefined, kid: options.keyid }, options.header); function failure(err) { if (callback) { return callback(err); } throw err; } if (typeof payload === 'undefined') { return failure(new Error('payload is required')); } else if (isObjectPayload) { var payload_validation_result = registered_claims_schema.validate(payload); if (payload_validation_result.error) { return failure(payload_validation_result.error); } payload = xtend(payload); } else { var invalid_options = options_for_objects.filter(function (opt) { return typeof options[opt] !== 'undefined'; }); if (invalid_options.length > 0) { return failure(new Error('invalid ' + invalid_options.join(',') + ' option for ' + (typeof payload ) + ' payload')); } } if (typeof payload.exp !== 'undefined' && typeof options.expiresIn !== 'undefined') { return failure(new Error('Bad "options.expiresIn" option the payload already has an "exp" property.')); } if (typeof payload.nbf !== 'undefined' && typeof options.notBefore !== 'undefined') { return failure(new Error('Bad "options.notBefore" option the payload already has an "nbf" property.')); } var validation_result = sign_options_schema.validate(options); if (validation_result.error) { return failure(validation_result.error); } var timestamp = payload.iat || Math.floor(Date.now() / 1000); if (!options.noTimestamp) { payload.iat = timestamp; } else { delete payload.iat; } if (typeof options.notBefore !== 'undefined') { payload.nbf = timespan(options.notBefore); if (typeof payload.nbf === 'undefined') { return failure(new Error('"notBefore" should be a number of seconds or string representing a timespan eg: "1d", "20h", 60')); } } if (typeof options.expiresIn !== 'undefined' && typeof payload === 'object') { payload.exp = timespan(options.expiresIn, timestamp); if (typeof payload.exp === 'undefined') { return failure(new Error('"expiresIn" should be a number of seconds or string representing a timespan eg: "1d", "20h", 60')); } } Object.keys(options_to_payload).forEach(function (key) { var claim = options_to_payload[key]; if (typeof options[key] !== 'undefined') { if (typeof payload[claim] !== 'undefined') { return failure(new Error('Bad "options.' + key + '" option. The payload already has an "' + claim + '" property.')); } payload[claim] = options[key]; } }); var encoding = options.encoding || 'utf8'; if (typeof callback === 'function') { callback = callback && once(callback); jws.createSign({ header: header, privateKey: secretOrPrivateKey, payload: payload, encoding: encoding }).once('error', callback) .once('done', function (signature) { callback(null, signature); }); } else { return jws.sign({header: header, payload: payload, secret: secretOrPrivateKey, encoding: encoding}); } }
...
```bash
$ npm install jsonwebtoken
```
# Usage
### jwt.sign(payload, secretOrPrivateKey, options, [callback])
(Asynchronous) If a callback is supplied, callback is called with the `err` or the JWT.
(Synchronous) Returns the JsonWebToken as string
`payload` could be an object literal, buffer or string. *Please note that* `exp` is only set if the payload is an object literal
.
...
verify = function (jwtString, secretOrPublicKey, options, callback) { if ((typeof options === 'function') && !callback) { callback = options; options = {}; } if (!options) { options = {}; } //clone this object since we are going to mutate it. options = xtend(options); var done; if (callback) { done = function() { var args = Array.prototype.slice.call(arguments, 0); return process.nextTick(function() { callback.apply(null, args); }); }; } else { done = function(err, data) { if (err) throw err; return data; }; } if (options.clockTimestamp && typeof options.clockTimestamp !== 'number') { return done(new JsonWebTokenError('clockTimestamp must be a number')); } var clockTimestamp = options.clockTimestamp || Math.floor(Date.now() / 1000); if (!jwtString){ return done(new JsonWebTokenError('jwt must be provided')); } if (typeof jwtString !== 'string') { return done(new JsonWebTokenError('jwt must be a string')); } var parts = jwtString.split('.'); if (parts.length !== 3){ return done(new JsonWebTokenError('jwt malformed')); } var hasSignature = parts[2].trim() !== ''; if (!hasSignature && secretOrPublicKey){ return done(new JsonWebTokenError('jwt signature is required')); } if (hasSignature && !secretOrPublicKey) { return done(new JsonWebTokenError('secret or public key must be provided')); } if (!hasSignature && !options.algorithms) { options.algorithms = ['none']; } if (!options.algorithms) { options.algorithms = ~secretOrPublicKey.toString().indexOf('BEGIN CERTIFICATE') || ~secretOrPublicKey.toString().indexOf('BEGIN PUBLIC KEY') ? [ 'RS256','RS384','RS512','ES256','ES384','ES512' ] : ~secretOrPublicKey.toString().indexOf('BEGIN RSA PUBLIC KEY') ? [ 'RS256','RS384','RS512' ] : [ 'HS256','HS384','HS512' ]; } var decodedToken; try { decodedToken = jws.decode(jwtString); } catch(err) { return done(err); } if (!decodedToken) { return done(new JsonWebTokenError('invalid token')); } var header = decodedToken.header; if (!~options.algorithms.indexOf(header.alg)) { return done(new JsonWebTokenError('invalid algorithm')); } var valid; try { valid = jws.verify(jwtString, header.alg, secretOrPublicKey); } catch (e) { return done(e); } if (!valid) return done(new JsonWebTokenError('invalid signature')); var payload; try { payload = decode(jwtString); } catch(err) { return done(err); } if (typeof payload.nbf !== 'undefined' && !options.ignoreNotBefore) { if (typeof payload.nbf !== 'number') { return done(new JsonWebTokenError('invalid nbf value')); } if (payload.nbf > clockTimestamp + (options.clockTolerance || 0)) { return done(new NotBeforeError('jwt not active', new Date(payload.nbf * 1000))); } } if (typeof payload.exp !== 'undefined' && !options.ignoreExpiration) { if (typeof payload.exp !== 'number') { return done(new JsonWebTokenError('invalid exp value')); } if (clockTimestamp >= payload.exp + (options.clockTolerance || 0)) { return done(new TokenExpiredError('jwt expired', new Date(payload.exp * 1000))); } } if (options.audience) { var audiences = Array.isArray(options.audience)? options.audience : [options.audience]; var target = Array.isArray(payload.aud) ? payload.aud : [payload.aud]; var match = target.some(function(aud) { return audiences.indexOf(aud) != -1; }); if (!match) return done(new JsonWebTokenError('jwt audience invalid. expected: ' + audiences.join(' or '))); } if (options.issuer) { var invalid_issuer = (typeof options.issuer === 'string' && payload.iss !== options.issuer) || (Array.isArray(options.issuer) && options.issuer.indexOf(payload.iss) === -1); if (invalid_issuer) { return done(new JsonWebTokenError('jwt issuer inv ...
...
//or even better:
jwt.sign({
data: 'foobar'
}, 'secret', { expiresIn: '1h' });
```
### jwt.verify(token, secretOrPublicKey, [options, callback])
(Asynchronous) If a callback is supplied, function acts asynchronously. Callback is passed the decoded payload if the signature
and optional expiration, audience, or issuer are valid. If not, it will be passed the error.
(Synchronous) If a callback is not supplied, function acts synchronously. Returns the payload decoded if the signature (and, optionally
, expiration, audience, issuer) are valid. If not, it will throw the error.
`token` is the JsonWebToken string
...
JsonWebTokenError = function (message, error) { Error.call(this, message); Error.captureStackTrace(this, this.constructor); this.name = 'JsonWebTokenError'; this.message = message; if (error) this.inner = error; }
n/a
constructor = function (message, error) { Error.call(this, message); Error.captureStackTrace(this, this.constructor); this.name = 'JsonWebTokenError'; this.message = message; if (error) this.inner = error; }
n/a
NotBeforeError = function (message, date) { JsonWebTokenError.call(this, message); this.name = 'NotBeforeError'; this.date = date; }
n/a
constructor = function (message, date) { JsonWebTokenError.call(this, message); this.name = 'NotBeforeError'; this.date = date; }
n/a
TokenExpiredError = function (message, expiredAt) { JsonWebTokenError.call(this, message); this.name = 'TokenExpiredError'; this.expiredAt = expiredAt; }
n/a
constructor = function (message, expiredAt) { JsonWebTokenError.call(this, message); this.name = 'TokenExpiredError'; this.expiredAt = expiredAt; }
n/a