Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

atlassian-jwt

Package Overview
Dependencies
Maintainers
5
Versions
13
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

atlassian-jwt - npm Package Compare versions

Comparing version 1.0.2 to 1.0.3

30

dist/lib/jwt.d.ts

@@ -37,13 +37,13 @@ import { Request as ExpressRequest } from 'express';

};
export declare const version = "1.0.3";
/**
* version
*/
export declare const version = "0.1.0";
/**
* Decode jwt
* Decodes JWT string to object.
* The encoding algorithm must be HS256, HS384, or HS512.
*
* @param {Object} token
* @param {String} key
* @param {Boolean} noVerify
* @return {Object} payload
* @param token JWT to decode
* @param key Key used to decode
* @param noVerify optional, set to true to skip the result verification
*
* @return Decoded JWT object
*
* @api public

@@ -53,8 +53,10 @@ */

/**
* Encode jwt
* Encodes JWT object to string.
*
* @param {Object} payload
* @param {String} key
* @param {String} algorithm
* @return {String} token
* @param payload Payload object to encode
* @param key Key used to encode
* @param algorithm Optional, must be HS256, HS384, or HS512; default is HS256
*
* @return Encoded JWT string
*
* @api public

@@ -61,0 +63,0 @@ */

"use strict";
/*
* Based off jwt-simple, adds query string hash verification
* Based off jwt-simple:
* https://github.com/hokaccha/node-jwt-simple
*
* Add Atlassian query string hash verification:
* https://developer.atlassian.com/cloud/jira/platform/understanding-jwt/
*
* JSON Web Token encode and decode module for node.js

@@ -10,2 +14,5 @@ *

*/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
var __importStar = (this && this.__importStar) || function (mod) {

@@ -18,13 +25,8 @@ if (mod && mod.__esModule) return mod;

};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
/**
* module dependencies
*/
var crypto_1 = require("crypto");
var _ = __importStar(require("lodash"));
var lodash_1 = __importDefault(require("lodash"));
var jsuri_1 = __importDefault(require("jsuri"));
var url = __importStar(require("url"));
// https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/
var Algorithm;

@@ -48,2 +50,10 @@ (function (Algorithm) {

}
/**
* Supported algorithm mapping.
*/
var algorithmMap = {
HS256: 'sha256',
HS384: 'sha384',
HS512: 'sha512'
};
function fromExpressRequest(eReq) {

@@ -82,31 +92,23 @@ // req.originalUrl represents the full URL and req.path represents the URL from the last router

/**
* support algorithm mapping
*/
var algorithmMap = {
HS256: 'sha256',
HS384: 'sha384',
HS512: 'sha512'
};
/**
* The separator between sections of a canonical query.
*/
var CANONICAL_QUERY_SEPARATOR = '&';
exports.version = '1.0.3';
/**
* version
*/
exports.version = '0.1.0';
/**
* Decode jwt
* Decodes JWT string to object.
* The encoding algorithm must be HS256, HS384, or HS512.
*
* @param {Object} token
* @param {String} key
* @param {Boolean} noVerify
* @return {Object} payload
* @param token JWT to decode
* @param key Key used to decode
* @param noVerify optional, set to true to skip the result verification
*
* @return Decoded JWT object
*
* @api public
*/
exports.decode = function jwt_decode(token, key, noVerify) {
// check seguments
// Check seguments
var segments = token.split('.');
if (segments.length !== 3) {
throw new Error('Not enough or too many segments');
throw new Error('Not enough or too many JWT token segments; should be 3');
}

@@ -117,23 +119,11 @@ // All segment should be base64

var signatureSeg = segments[2];
// base64 decode and parse JSON
// Base64 decode and parse JSON
var header = JSON.parse(base64urlDecode(headerSeg));
var payload = JSON.parse(base64urlDecode(payloadSeg));
// normalize 'aud' claim, the spec allows both String and Array
if (payload.aud && !_.isArray(payload.aud)) {
// Normalize 'aud' claim, the spec allows both String and Array
if (payload.aud && !lodash_1.default.isArray(payload.aud)) {
payload.aud = [payload.aud];
}
if (!noVerify) {
var alg = getAlgorithmFromString(header.alg);
if (!alg) {
throw new Error('Algorithm "' + header.alg + '" is not supported');
}
var signingMethod = algorithmMap[alg];
if (!signingMethod) {
throw new Error('Algorithm "' + header.alg + '" is not supported');
}
// verify signature. `sign` will return base64 string.
var signingInput = [headerSeg, payloadSeg].join('.');
if (signatureSeg !== sign(signingInput, key, signingMethod)) {
throw new Error('Signature verification failed for input: ' + signingInput + ' with method ' + signingMethod);
}
verifySignature(headerSeg, payloadSeg, signatureSeg, key, header.alg);
}

@@ -143,26 +133,17 @@ return payload;

/**
* Encode jwt
* Encodes JWT object to string.
*
* @param {Object} payload
* @param {String} key
* @param {String} algorithm
* @return {String} token
* @param payload Payload object to encode
* @param key Key used to encode
* @param algorithm Optional, must be HS256, HS384, or HS512; default is HS256
*
* @return Encoded JWT string
*
* @api public
*/
exports.encode = function jwt_encode(payload, key, algorithm) {
// Check key
if (!key) {
throw new Error('Require key');
}
// Check algorithm, default is HS256
if (!algorithm) {
algorithm = Algorithm.HS256;
}
var signingMethod = algorithmMap[algorithm];
if (!signingMethod) {
throw new Error('Algorithm "' + algorithm + '" is not supported');
}
// header, typ is fixed value.
var header = { typ: 'JWT', alg: algorithm };
// create segments, all segment should be base64 string
var _a = validateAlgorithm(key, algorithm), signingAlgorithm = _a[0], signingMethod = _a[1];
// typ is fixed value
var header = { typ: 'JWT', alg: signingAlgorithm };
// Create segments, all segment should be base64 string
var segments = [];

@@ -189,4 +170,29 @@ segments.push(base64urlEncode(JSON.stringify(header)));

/**
* private util functions
* Private util functions.
*/
function validateAlgorithm(key, algorithm) {
// Check key
if (!key) {
throw new Error('Require key');
}
// Check algorithm, default is HS256
var signingAlgorithm = algorithm || 'HS256';
var alg = getAlgorithmFromString(signingAlgorithm);
if (!alg) {
throw new Error('Algorithm "' + algorithm + '" is not supported');
}
var signingMethod = algorithmMap[alg];
if (!signingMethod) {
throw new Error('Algorithm "' + algorithm + '" is not supported');
}
return [signingAlgorithm, signingMethod];
}
function verifySignature(headerSeg, payloadSeg, signatureSeg, key, algorithm) {
var _a = validateAlgorithm(key, algorithm), signingMethod = _a[1];
// Verify signature
var signingInput = [headerSeg, payloadSeg].join('.');
if (signatureSeg !== sign(signingInput, key, signingMethod)) {
throw new Error('Signature verification failed for input: ' + signingInput + ' with method ' + signingMethod);
}
}
function sign(input, key, method) {

@@ -226,7 +232,7 @@ var base64str = crypto_1.createHmac(method, key).update(input).digest('base64');

path = path.replace(new RegExp(CANONICAL_QUERY_SEPARATOR, 'g'), encodeRfc3986(CANONICAL_QUERY_SEPARATOR));
// prefix with /
// Prefix with /
if (path[0] !== '/') {
path = '/' + path;
}
// remove trailing /
// Remove trailing /
if (path.length > 1 && path[path.length - 1] === '/') {

@@ -238,13 +244,14 @@ path = path.substring(0, path.length - 1);

function canonicalizeQueryString(req, checkBodyForParams) {
var queryParams = req.query, method = req.method.toUpperCase();
var queryParams = req.query;
var method = req.method.toUpperCase();
// Apache HTTP client (or something) sometimes likes to take the query string and put it into the request body
// if the method is PUT or POST
if (checkBodyForParams && _.isEmpty(queryParams) && (method === 'POST' || method === 'PUT')) {
if (checkBodyForParams && lodash_1.default.isEmpty(queryParams) && (method === 'POST' || method === 'PUT')) {
queryParams = req.body;
}
var sortedQueryString = new Array(), query = _.extend({}, queryParams);
if (!_.isEmpty(query)) {
// remove the 'jwt' query string param
var sortedQueryString = new Array(), query = lodash_1.default.extend({}, queryParams);
if (!lodash_1.default.isEmpty(query)) {
// Remove the 'jwt' query string param
delete query.jwt;
_.each(_.keys(query).sort(), function (key) {
lodash_1.default.each(lodash_1.default.keys(query).sort(), function (key) {
// The __proto__ field can sometimes sneak in depending on what node version is being used.

@@ -255,5 +262,6 @@ // Get rid of it or the qsh calculation will be wrong.

}
var param = query[key], paramValue = '';
var param = query[key];
var paramValue = '';
if (Array.isArray(param)) {
paramValue = _.map(param.sort(), encodeRfc3986).join(',');
paramValue = lodash_1.default.map(param.sort(), encodeRfc3986).join(',');
}

@@ -260,0 +268,0 @@ else {

{
"name": "atlassian-jwt",
"description": "JWT (JSON Web Token) implementation with custom Atlassian QSH claim verification",
"version": "1.0.2",
"author": "Seb Ruiz <sruiz@atlassian.com>",
"version": "1.0.3",
"author": "Atlassian",
"contributors": [
"Robert Massaioli <rmassaioli@atlassian.com>",
"Jake Furler <jfurler@atlassian.com>",
"Ngoc Dao <ndao@atlassian.com>",
"Ralph Whitbeck <rwhitbeck@atlassian.com>",
"Parambir Singh",
"RichardS",
"Seb Ruiz <sruiz@atlassian.com>"
],
"homepage": "https://bitbucket.org/atlassian/atlassian-jwt-js",
"repository": {

@@ -10,19 +20,22 @@ "type": "git",

},
"publishConfig": {
"registry": "https://registry.npmjs.org"
},
"dependencies": {
"jsuri": "^1.3.1",
"lodash": "^4.12.0"
"lodash": "^4.17.11"
},
"devDependencies": {
"@types/express": "^4.16.0",
"@types/express": "^4.17.0",
"@types/jsuri": "^1.3.30",
"@types/lodash": "^4.14.116",
"@types/mocha": "^5.2.5",
"@types/lodash": "^4.14.134",
"@types/mocha": "^5.2.7",
"@types/node": "^10.7.1",
"@types/qs": "^6.5.1",
"mocha": "^5.2.0",
"moment": "^2.14.1",
"qs": "^6.2.1",
"ts-node": "^7.0.1",
"tslint": "^5.11.0",
"typescript": "^3.0.1"
"@types/qs": "^6.5.3",
"mocha": "^6.1.4",
"moment": "^2.24.0",
"qs": "^6.7.0",
"ts-node": "^8.3.0",
"tslint": "^5.17.0",
"typescript": "^3.5.2"
},

@@ -29,0 +42,0 @@ "scripts": {

# atlassian-jwt
![build-status](https://bitbucket-badges.atlassian.io/badge/atlassian/atlassian-jwt-js.svg)
[![TypeScript](https://badges.frapsoft.com/typescript/code/typescript.svg?v=101)](https://github.com/ellerbrock/typescript-badges/)
[JWT (JSON Web Token)](http://self-issued.info/docs/draft-jones-json-web-token.html) encoding & decoding
library for node.js. Built on [jwt-simple](https://github.com/hokaccha/node-jwt-simple) and adds support
[JWT (JSON Web Token)](http://self-issued.info/docs/draft-jones-json-web-token.html) encoding & decoding
library for node.js. Built on [jwt-simple](https://github.com/hokaccha/node-jwt-simple), it adds support
for Atlassian's custom QSH (query string hash) claim.
For more information on using JWT tokens with Atlassian add-ons, please read:
For more information on using JWT tokens with Atlassian apps, please read:
[Understanding JWT](https://developer.atlassian.com/cloud/jira/platform/understanding-jwt/).

@@ -15,3 +14,5 @@

$ npm install atlassian-jwt
```sh
npm install atlassian-jwt
```

@@ -33,5 +34,5 @@ ## Usage

"iss": 'issuer-val',
"iat": now.unix(), // the time the token is generated
"exp": now.add(3, 'minutes').unix(), // token expiry time (recommend 3 minutes after issuing)
"qsh": jwt.createQueryStringHash(req) // [Query String Hash](https://developer.atlassian.com/cloud/jira/platform/understanding-jwt/#a-name-qsh-a-creating-a-query-string-hash)
"iat": now.unix(), // The time the token is generated
"exp": now.add(3, 'minutes').unix(), // Token expiry time (recommend 3 minutes after issuing)
"qsh": jwt.createQueryStringHash(req) // [Query String Hash](https://developer.atlassian.com/cloud/jira/platform/understanding-jwt/#a-name-qsh-a-creating-a-query-string-hash)
};

@@ -47,16 +48,9 @@

```javascript
/*
* jwt.decode(token, secret, noVerify, algorithm)
*
* Decodes the JWT token and verifies the signature using the secret and algorithm. Algorithm defaults to HS256.
*/
var decoded = jwt.decode(token, secret);
```typescript
const decoded = jwt.decode(token, secret);
console.log(decoded); //=> { foo: 'bar' }
/*
* Decode without verifing the signature of the token.
* Tokens should never be used without verifying the signature as otherwise payload trust cannot be established.
*/
var decoded = jwt.decode(token, null, true);
// Decode without verifing the signature of the token.
// Don't do this unless that's your intention.
const decoded = jwt.decode(token, null, true);
console.log(decoded); //=> { foo: 'bar' }

@@ -67,12 +61,17 @@ ```

- `jwt.createQueryStringHash(req, checkBodyForParams, baseUrl)`
Create a QSH using the algorithm defined by [the algorithm](https://developer.atlassian.com/static/connect/docs/latest/concepts/understanding-jwt.html#qsh) .
- `jwt.createCanonicalRequest(req, checkBodyForParams, baseUrl)`
Creates a canonical request which is used to calculate the QSH for the JWT token. Prefer using `#createQueryStringHash()` directly.
- `jwt.fromExpressRequest(expressRequest: ExpressRequest)`
Converts an Express.js Request into a `Request` object that can be used with other methods in this library.
- `jwt.fromMethodAndUrl(method: string, url: string)`
This takes in a method and url, both as plain strings, and turns them into a `Request` object that can be used with other methods in this library.
- `jwt.fromMethodAndPathAndBody`
This takes in a method, a url, and some form params from a request body and turns them into a `Request` object that can be used with other methods in this library.
- `jwt.createQueryStringHash(req, checkBodyForParams, baseUrl)`
Creates a QSH using the algorithm defined by
[the algorithm](https://developer.atlassian.com/static/connect/docs/latest/concepts/understanding-jwt.html#qsh).
- `jwt.createCanonicalRequest(req, checkBodyForParams, baseUrl)`
Creates a canonical request which is used to calculate the QSH for the JWT token.
Prefer using `#createQueryStringHash()` directly.
- `jwt.fromExpressRequest(expressRequest: ExpressRequest)`
Converts an Express.js request into a `Request` object
that can be used with other methods in this library.
- `jwt.fromMethodAndUrl(method, url)`
Takes in a method and URL, both as plain strings,
and turns them into a `Request` object that can be used with other methods in this library.
- `jwt.fromMethodAndPathAndBody(method, url, body)`
Takes in a method, a URL, and some form params from a request body
and turns them into a `Request` object that can be used with other methods in this library.

@@ -83,7 +82,23 @@ ### Algorithms

The supported algorithms for encoding and decoding are `HS256`, `HS384`, `HS512` and `RS256`.
The supported algorithms for encoding and decoding are `HS256`, `HS384`, and `HS512`.
See [Critical vulnerabilities in JSON Web Token libraries](https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/).
If you use TypeScript:
```typescript
// Encode using HS256 (default)
jwt.encode(payload, secret);
// Encode using HS512
jwt.encode(payload, secret, jwt.Algorithm.HS512);
```
If you use JavaScript:
```javascript
// encode using HS512
jwt.encode(payload, secret, 'HS512')
// Encode using HS256 (default)
jwt.encode(payload, secret);
// Encode using HS512
jwt.encode(payload, secret, 'HS512');
```

@@ -113,11 +128,17 @@

Update `version` in package.json and lib/jwt.ts.
To publish this library:
npm run tsc
npm publish
```sh
npm run tsc
npm publish
```
This has been combined into a single command with:
npm run build-and-publish
```sh
npm run build-and-publish
```
Only the built typescript files will be published with this library.
Only the built TypeScript files will be published with this library.

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc