Skip to content

Commit

Permalink
rename 'decode' to 'unsafeDecode'
Browse files Browse the repository at this point in the history
'decode' is often reached to by well-meaning developers who assume that the call is safe. Unfortunately, this leads to untrusted JWTs being accepted as otherwise acceptable input.

Renaming 'decode' to 'unsafeDecode' signals to the end user that the method they are calling is indeed unsafe without them having to remember the difference between 'decode' and 'verify'.
  • Loading branch information
Dan Pantry committed Sep 2, 2020
1 parent 5f10bf9 commit d85caec
Show file tree
Hide file tree
Showing 10 changed files with 25 additions and 25 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ jwt.verify(token, getKey, options, function(err, decoded) {

```

### jwt.decode(token [, options])
### jwt.unsafeDecode(token [, options])

(Synchronous) Returns the decoded payload without verifying if the signature is valid.

Expand All @@ -251,10 +251,10 @@ Example

```js
// get the decoded payload ignoring signature, no secretOrPrivateKey needed
var decoded = jwt.decode(token);
var decoded = jwt.unsafeDecode(token);

// get the decoded payload and header
var decoded = jwt.decode(token, {complete: true});
var decoded = jwt.unsafeDecode(token, {complete: true});
console.log(decoded.header);
console.log(decoded.payload)
```
Expand Down
2 changes: 1 addition & 1 deletion index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
module.exports = {
decode: require('./decode'),
unsafeDecode: require('./decode'),
verify: require('./verify'),
sign: require('./sign'),
JsonWebTokenError: require('./lib/JsonWebTokenError'),
Expand Down
2 changes: 1 addition & 1 deletion test/buffer.tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ describe('buffer payload', function () {
it('should work', function () {
var payload = new Buffer('TkJyotZe8NFpgdfnmgINqg==', 'base64');
var token = jwt.sign(payload, "signing key");
assert.equal(jwt.decode(token), payload.toString());
assert.equal(jwt.unsafeDecode(token), payload.toString());
});
});
6 changes: 3 additions & 3 deletions test/claim-exp.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ describe('expires', function() {
// TODO an exp of -Infinity should fail validation
it('should set null "exp" when given -Infinity', function (done) {
signWithExpiresIn(undefined, {exp: -Infinity}, (err, token) => {
const decoded = jwt.decode(token);
const decoded = jwt.unsafeDecode(token);
testUtils.asyncCheck(done, () => {
expect(err).to.be.null;
expect(decoded).to.have.property('exp', null);
Expand All @@ -246,7 +246,7 @@ describe('expires', function() {
// TODO an exp of Infinity should fail validation
it('should set null "exp" when given value Infinity', function (done) {
signWithExpiresIn(undefined, {exp: Infinity}, (err, token) => {
const decoded = jwt.decode(token);
const decoded = jwt.unsafeDecode(token);
testUtils.asyncCheck(done, () => {
expect(err).to.be.null;
expect(decoded).to.have.property('exp', null);
Expand All @@ -257,7 +257,7 @@ describe('expires', function() {
// TODO an exp of NaN should fail validation
it('should set null "exp" when given value NaN', function (done) {
signWithExpiresIn(undefined, {exp: NaN}, (err, token) => {
const decoded = jwt.decode(token);
const decoded = jwt.unsafeDecode(token);
testUtils.asyncCheck(done, () => {
expect(err).to.be.null;
expect(decoded).to.have.property('exp', null);
Expand Down
6 changes: 3 additions & 3 deletions test/claim-iat.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ describe('issue at', function() {
signWithIssueAt(testCase.iat, testCase.options, (err, token) => {
testUtils.asyncCheck(done, () => {
expect(err).to.be.null;
expect(jwt.decode(token).iat).to.equal(testCase.expectedIssueAt);
expect(jwt.unsafeDecode(token).iat).to.equal(testCase.expectedIssueAt);
});
});
});
Expand Down Expand Up @@ -254,7 +254,7 @@ describe('issue at', function() {
const payload = 'string payload';
const options = {algorithm: 'none'};
testUtils.signJWTHelper(payload, 'secret', options, (err, token) => {
const decoded = jwt.decode(token);
const decoded = jwt.unsafeDecode(token);
testUtils.asyncCheck(done, () => {
expect(err).to.be.null;
expect(decoded).to.equal(payload);
Expand All @@ -266,7 +266,7 @@ describe('issue at', function() {
const payload = '{}';
const options = {algorithm: 'none', header: {typ: 'JWT'}};
testUtils.signJWTHelper(payload, 'secret', options, (err, token) => {
const decoded = jwt.decode(token);
const decoded = jwt.unsafeDecode(token);
testUtils.asyncCheck(done, () => {
expect(err).to.equal(null);
expect(JSON.stringify(decoded)).to.equal(payload);
Expand Down
8 changes: 4 additions & 4 deletions test/claim-nbf.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ describe('not before', function() {
// TODO an nbf of -Infinity should fail validation
it('should set null "nbf" when given -Infinity', function (done) {
signWithNotBefore(undefined, {nbf: -Infinity}, (err, token) => {
const decoded = jwt.decode(token);
const decoded = jwt.unsafeDecode(token);
testUtils.asyncCheck(done, () => {
expect(err).to.be.null;
expect(decoded).to.have.property('nbf', null);
Expand All @@ -243,7 +243,7 @@ describe('not before', function() {
// TODO an nbf of Infinity should fail validation
it('should set null "nbf" when given value Infinity', function (done) {
signWithNotBefore(undefined, {nbf: Infinity}, (err, token) => {
const decoded = jwt.decode(token);
const decoded = jwt.unsafeDecode(token);
testUtils.asyncCheck(done, () => {
expect(err).to.be.null;
expect(decoded).to.have.property('nbf', null);
Expand All @@ -254,7 +254,7 @@ describe('not before', function() {
// TODO an nbf of NaN should fail validation
it('should set null "nbf" when given value NaN', function (done) {
signWithNotBefore(undefined, {nbf: NaN}, (err, token) => {
const decoded = jwt.decode(token);
const decoded = jwt.unsafeDecode(token);
testUtils.asyncCheck(done, () => {
expect(err).to.be.null;
expect(decoded).to.have.property('nbf', null);
Expand Down Expand Up @@ -337,4 +337,4 @@ describe('not before', function() {
});
});
});
});
});
2 changes: 1 addition & 1 deletion test/decoding.tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ var expect = require('chai').expect;
describe('decoding', function() {

it('should not crash when decoding a null token', function () {
var decoded = jwt.decode("null");
var decoded = jwt.unsafeDecode("null");
expect(decoded).to.equal(null);
});

Expand Down
8 changes: 4 additions & 4 deletions test/header-kid.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ describe('keyid', function() {
it('should not add "kid" header when "keyid" option not provided', function(done) {
signWithKeyId(undefined, {}, (err, token) => {
testUtils.asyncCheck(done, () => {
const decoded = jwt.decode(token, {complete: true});
const decoded = jwt.unsafeDecode(token, {complete: true});
expect(err).to.be.null;
expect(decoded.header).to.not.have.property('kid');
});
Expand All @@ -67,7 +67,7 @@ describe('keyid', function() {
it('should add "kid" header when "keyid" option is provided and an object payload', function(done) {
signWithKeyId('foo', {}, (err, token) => {
testUtils.asyncCheck(done, () => {
const decoded = jwt.decode(token, {complete: true});
const decoded = jwt.unsafeDecode(token, {complete: true});
expect(err).to.be.null;
expect(decoded.header).to.have.property('kid', 'foo');
});
Expand All @@ -77,7 +77,7 @@ describe('keyid', function() {
it('should add "kid" header when "keyid" option is provided and a Buffer payload', function(done) {
signWithKeyId('foo', new Buffer('a Buffer payload'), (err, token) => {
testUtils.asyncCheck(done, () => {
const decoded = jwt.decode(token, {complete: true});
const decoded = jwt.unsafeDecode(token, {complete: true});
expect(err).to.be.null;
expect(decoded.header).to.have.property('kid', 'foo');
});
Expand All @@ -87,7 +87,7 @@ describe('keyid', function() {
it('should add "kid" header when "keyid" option is provided and a string payload', function(done) {
signWithKeyId('foo', 'a string payload', (err, token) => {
testUtils.asyncCheck(done, () => {
const decoded = jwt.decode(token, {complete: true});
const decoded = jwt.unsafeDecode(token, {complete: true});
expect(err).to.be.null;
expect(decoded.header).to.have.property('kid', 'foo');
});
Expand Down
6 changes: 3 additions & 3 deletions test/jwt.asymmetric_signing.tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ describe('Asymmetric Algorithms', function(){

describe('when decoding a invalid jwt token', function () {
it('should return null', function (done) {
var payload = jwt.decode('whatever.token');
var payload = jwt.unsafeDecode('whatever.token');
assert.isNull(payload);
done();
});
Expand All @@ -158,14 +158,14 @@ describe('Asymmetric Algorithms', function(){
it('should return the payload', function (done) {
var obj = { foo: 'bar' };
var token = jwt.sign(obj, priv, { algorithm: algorithm });
var payload = jwt.decode(token);
var payload = jwt.unsafeDecode(token);
assert.equal(payload.foo, obj.foo);
done();
});
it('should return the header and payload and signature if complete option is set', function (done) {
var obj = { foo: 'bar' };
var token = jwt.sign(obj, priv, { algorithm: algorithm });
var decoded = jwt.decode(token, { complete: true });
var decoded = jwt.unsafeDecode(token, { complete: true });
assert.equal(decoded.payload.foo, obj.foo);
assert.deepEqual(decoded.header, { typ: 'JWT', alg: algorithm });
assert.ok(typeof decoded.signature == 'string');
Expand Down
4 changes: 2 additions & 2 deletions test/set_headers.tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ describe('set header', function() {

it('should add the header', function () {
var token = jwt.sign({foo: 123}, '123', { header: { foo: 'bar' } });
var decoded = jwt.decode(token, {complete: true});
var decoded = jwt.unsafeDecode(token, {complete: true});
expect(decoded.header.foo).to.equal('bar');
});

it('should allow overriding header', function () {
var token = jwt.sign({foo: 123}, '123', { header: { alg: 'HS512' } });
var decoded = jwt.decode(token, {complete: true});
var decoded = jwt.unsafeDecode(token, {complete: true});
expect(decoded.header.alg).to.equal('HS512');
});

Expand Down

0 comments on commit d85caec

Please sign in to comment.