New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@arcblock/jwt

Package Overview
Dependencies
Maintainers
4
Versions
286
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@arcblock/jwt - npm Package Compare versions

Comparing version 1.16.16 to 1.16.17

83

lib/index.d.ts

@@ -1,16 +0,67 @@

// Generate by [js2dts@0.3.3](https://github.com/whxaxes/js2dts#readme)
declare const _Lib: _Lib.T102;
declare namespace _Lib {
export interface T101 {
tolerance?: number;
enforceTimestamp?: boolean;
signerKey?: string;
}
export interface T102 {
sign: (signer: string, sk: string, payload?: any, doSign?: boolean, version?: string) => string;
verify: (token: string, signerPk: string, T100?: _Lib.T101) => boolean;
decode: (token: string, payloadOnly?: boolean) => any;
}
}
export = _Lib;
import { BytesType } from '@ocap/util';
export declare type JwtBody = {
iss?: string;
iat?: string;
nbf?: string;
exp?: string;
version?: string;
[key: string]: any;
};
export declare type JwtHeader = {
alg: string;
type: 'JWT';
};
export declare type JwtToken = {
header: JwtHeader;
body: JwtBody;
signature: string;
};
export declare type JwtVerifyOptions = Partial<{
tolerance: number;
enforceTimestamp: boolean;
signerKey: string;
}>;
/**
*
*
* @param {string} signer - address string
* @param {string} sk - hex encoded secret key
* @param {*} [payload={}] - data to be included before signing
* @param {boolean} [doSign=true] - do we need to sign the payload or just return the content to be signed
* @param {string} [version='1.0.0']
* @return {*} {string} - hex encoded signature
*/
export declare function sign(signer: string, sk: string, payload?: {}, doSign?: boolean, version?: string): string;
/**
*
*
* @param {string} token - jwt string
* @param {boolean} [payloadOnly=true]
* @return {*} {{
* header: any;
* body: any;
* signature: string;
* }}
*/
export declare function decode(token: string, payloadOnly?: boolean): JwtToken;
/**
*
*
* @param {string} token - the jwt token
* @param {string} signerPk - signer public key
* @param {{
* tolerance: number; - number of seconds to tolerant expire
* enforceTimestamp: boolean; - whether should be verify timestamps?
* signerKey: string; - which field should be used to pick the signer
* }} [{
* tolerance,
* enforceTimestamp,
* signerKey,
* }={
* tolerance: 5,
* enforceTimestamp: true,
* signerKey: 'iss',
* }]
* @return {*} {boolean}
*/
export declare function verify(token: string, signerPk: BytesType, options?: JwtVerifyOptions): boolean;

357

lib/index.js

@@ -1,206 +0,195 @@

const semver = require('semver');
const stringify = require('json-stable-stringify');
const Mcrypto = require('@ocap/mcrypto');
const { toHex, toBase64, fromBase64 } = require('@ocap/util');
const { toDid, toStrictHex, toTypeInfo, isValid, isFromPublicKey } = require('@arcblock/did');
// eslint-disable-next-line
const debug = require('debug')(require('../package.json').name);
const { types, getSigner } = Mcrypto;
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.verify = exports.decode = exports.sign = void 0;
/* eslint-disable @typescript-eslint/ban-ts-comment */
const json_stable_stringify_1 = __importDefault(require("json-stable-stringify"));
const semver_1 = __importDefault(require("semver"));
const util_1 = require("@ocap/util");
const did_1 = require("@arcblock/did");
const mcrypto_1 = require("@ocap/mcrypto");
const debug_1 = __importDefault(require("debug"));
const debug = (0, debug_1.default)('@arcblock/jwt');
// we start hashing before signing after 1.1
const JWT_VERSION_REQUIRE_HASH_BEFORE_SIGN = '1.1.0';
// since ios requires a fixed length of input to sign, we use sha3 here before sign
const hasher = Mcrypto.Hasher.SHA3.hash256;
const hasher = mcrypto_1.Hasher.SHA3.hash256;
/**
* Generate and sign a jwt token
*
* @public
* @static
*
* @param {string} signer - address string
* @param {string} sk - hex encoded secret key
* @param {object} [payload={}] - data to be included before signing
* @param {*} [payload={}] - data to be included before signing
* @param {boolean} [doSign=true] - do we need to sign the payload or just return the content to be signed
* @returns {string} hex encoded signature
* @param {string} [version='1.0.0']
* @return {*} {string} - hex encoded signature
*/
const sign = (signer, sk, payload = {}, doSign = true, version = '1.0.0') => {
if (isValid(signer) === false) {
throw new Error('Cannot do sign with invalid signer');
}
const type = toTypeInfo(signer);
const headers = {
[types.KeyType.SECP256K1]: {
alg: 'ES256K',
type: 'JWT',
},
[types.KeyType.ED25519]: {
alg: 'Ed25519',
type: 'JWT',
},
[types.KeyType.ETHEREUM]: {
alg: 'Ethereum',
type: 'JWT',
},
};
// make header
const header = headers[type.pk];
const headerB64 = toBase64(stringify(header));
// make body
const now = Math.floor(Date.now() / 1000);
let body = {
iss: toDid(signer),
iat: String(now),
nbf: String(now),
exp: String(now + 5 * 60),
version,
...(payload || {}),
};
// remove empty keys
body = Object.keys(body)
.filter((x) => {
if (typeof body[x] === 'undefined' || body[x] == null || body[x] === '') {
return false;
}
return true;
function sign(signer, sk, payload = {}, doSign = true, version = '1.0.0') {
if ((0, did_1.isValid)(signer) === false) {
throw new Error('Cannot do sign with invalid signer');
}
const type = (0, did_1.toTypeInfo)(signer);
const headers = {
[mcrypto_1.types.KeyType.SECP256K1]: {
alg: 'ES256K',
type: 'JWT',
},
[mcrypto_1.types.KeyType.ED25519]: {
alg: 'Ed25519',
type: 'JWT',
},
[mcrypto_1.types.KeyType.ETHEREUM]: {
alg: 'Ethereum',
type: 'JWT',
},
};
// make header
const header = headers[type.pk];
const headerB64 = (0, util_1.toBase64)((0, json_stable_stringify_1.default)(header));
// make body
const now = Math.floor(Date.now() / 1000);
let body = Object.assign({ iss: (0, did_1.toDid)(signer), iat: String(now), nbf: String(now), exp: String(now + 5 * 60), version }, (payload || {}));
// remove empty keys
body = Object.keys(body)
.filter((x) => {
if (typeof body[x] === 'undefined' || body[x] == null || body[x] === '') {
return false;
}
return true;
})
.reduce((acc, x) => {
acc[x] = body[x];
return acc;
.reduce((acc, x) => {
acc[x] = body[x];
return acc;
}, {});
const bodyB64 = toBase64(stringify(body));
debug('sign.body', body);
// istanbul ignore if
if (!doSign) {
return `${headerB64}.${bodyB64}`;
}
// make signature
const msgHex = toHex(`${headerB64}.${bodyB64}`);
const msgHash = semver.gte(semver.coerce(version).version, JWT_VERSION_REQUIRE_HASH_BEFORE_SIGN)
? hasher(msgHex)
: msgHex;
const sigHex = getSigner(type.pk).sign(msgHash, sk);
const sigB64 = toBase64(sigHex);
return [headerB64, bodyB64, sigB64].join('.');
};
const bodyB64 = (0, util_1.toBase64)((0, json_stable_stringify_1.default)(body));
debug('sign.body', body);
// istanbul ignore if
if (!doSign) {
return `${headerB64}.${bodyB64}`;
}
// @ts-ignore make signature
const msgHex = (0, util_1.toHex)(`${headerB64}.${bodyB64}`);
const msgHash = semver_1.default.gte(semver_1.default.coerce(version).version, JWT_VERSION_REQUIRE_HASH_BEFORE_SIGN)
? hasher(msgHex)
: msgHex;
const sigHex = (0, mcrypto_1.getSigner)(type.pk).sign(msgHash, sk);
const sigB64 = (0, util_1.toBase64)(sigHex);
return [headerB64, bodyB64, sigB64].join('.');
}
exports.sign = sign;
/**
* Decode info from jwt token
*
* @public
* @static
*
* @param {string} token - jwt string
* @param {boolean} [payloadOnly=false]
* @returns {object}
* @param {boolean} [payloadOnly=true]
* @return {*} {{
* header: any;
* body: any;
* signature: string;
* }}
*/
const decode = (token, payloadOnly = true) => {
const [headerB64, bodyB64, sigB64] = token.split('.');
const header = JSON.parse(fromBase64(headerB64));
const body = JSON.parse(fromBase64(bodyB64));
const sig = Buffer.from(fromBase64(sigB64)).toString('hex');
if (payloadOnly) {
return body;
}
return { header, body, signature: `0x${toStrictHex(sig)}` };
};
function decode(token, payloadOnly = true) {
const [headerB64, bodyB64, sigB64] = token.split('.');
const header = JSON.parse((0, util_1.fromBase64)(headerB64).toString());
const body = JSON.parse((0, util_1.fromBase64)(bodyB64).toString());
const sig = Buffer.from((0, util_1.fromBase64)(sigB64)).toString('hex');
if (payloadOnly) {
return body;
}
return { header, body, signature: `0x${(0, did_1.toStrictHex)(sig)}` };
}
exports.decode = decode;
/**
* Verify a jwt token signed with signerPk and signerDid
*
* @public
* @static
* @param {string} token - the jwt token
*
* @param {string} token - the jwt token
* @param {string} signerPk - signer public key
* @param {object} options - options to customize the verify
* @param {number} [options.tolerance=5] - number of seconds to tolerant expire
* @param {boolean} [options.enforceTimestamp=true] - whether should be verify timestamps?
* @param {string} [options.signerKey='iss'] - which field should be used to pick the signer
* @returns {boolean}
* @param {{
* tolerance: number; - number of seconds to tolerant expire
* enforceTimestamp: boolean; - whether should be verify timestamps?
* signerKey: string; - which field should be used to pick the signer
* }} [{
* tolerance,
* enforceTimestamp,
* signerKey,
* }={
* tolerance: 5,
* enforceTimestamp: true,
* signerKey: 'iss',
* }]
* @return {*} {boolean}
*/
const verify = (token, signerPk, { tolerance = 5, enforceTimestamp = true, signerKey = 'iss' } = {}) => {
try {
const [headerB64, bodyB64] = token.split('.');
const { header, body, signature } = decode(token, false);
if (!signature) {
debug('verify.error.emptySig');
return false;
function verify(token, signerPk, options) {
const { tolerance, enforceTimestamp, signerKey } = Object.assign({
tolerance: 5,
enforceTimestamp: true,
signerKey: 'iss',
}, options);
try {
const [headerB64, bodyB64] = token.split('.');
const { header, body, signature } = decode(token, false);
if (!signature) {
debug('verify.error.emptySig');
return false;
}
if (!header.alg) {
debug('verify.error.emptyAlg');
return false;
}
const signerDid = body[signerKey];
if (!signerDid) {
debug('verify.error.emptySignerDid');
return false;
}
if ((0, did_1.isFromPublicKey)(signerDid, signerPk) === false) {
debug('verify.error.signerDidAndPkNotMatch');
return false;
}
if (enforceTimestamp) {
const now = Math.ceil(Date.now() / 1000);
const exp = Number(body.exp) || 0;
const iat = Number(body.iat) || 0;
const nbf = Number(body.nbf) || 0;
debug('verify.enforceTimestamp', { now, exp, iat, nbf });
if (exp && exp + tolerance < now) {
debug('verify.error.expired');
return false;
}
if (iat && iat > now && iat - now > tolerance) {
debug('verify.error.issuedAt');
return false;
}
if (nbf && nbf > now && nbf - now > tolerance) {
debug('verify.error.notBefore');
return false;
}
}
const signers = {
secp256k1: (0, mcrypto_1.getSigner)(mcrypto_1.types.KeyType.SECP256K1),
es256k: (0, mcrypto_1.getSigner)(mcrypto_1.types.KeyType.SECP256K1),
ed25519: (0, mcrypto_1.getSigner)(mcrypto_1.types.KeyType.ED25519),
ethereum: (0, mcrypto_1.getSigner)(mcrypto_1.types.KeyType.ETHEREUM),
};
const alg = header.alg.toLowerCase();
if (signers[alg]) {
// @ts-ignore
const msgHex = (0, util_1.toHex)(`${headerB64}.${bodyB64}`);
// If we are using v1.1 protocol, the message should be hashed before verify
const version = body.version && semver_1.default.coerce(body.version) ? semver_1.default.coerce(body.version).version : '';
if (version && version === JWT_VERSION_REQUIRE_HASH_BEFORE_SIGN) {
return signers[alg].verify(hasher(msgHex), signature, signerPk);
}
return signers[alg].verify(msgHex, signature, signerPk);
}
debug('verify.error.crypto');
return false;
}
if (!header.alg) {
debug('verify.error.emptyAlg');
return false;
}
const signerDid = body[signerKey];
if (!signerDid) {
debug('verify.error.emptySignerDid');
return false;
}
if (isFromPublicKey(signerDid, signerPk) === false) {
debug('verify.error.signerDidAndPkNotMatch');
return false;
}
if (enforceTimestamp) {
const now = Math.ceil(Date.now() / 1000);
const exp = Number(body.exp) || 0;
const iat = Number(body.iat) || 0;
const nbf = Number(body.nbf) || 0;
debug('verify.enforceTimestamp', { now, exp, iat, nbf });
if (exp && exp + tolerance < now) {
debug('verify.error.expired');
catch (err) {
debug('verify.error.exception');
debug(err);
return false;
}
if (iat && iat > now && iat - now > tolerance) {
debug('verify.error.issuedAt');
return false;
}
if (nbf && nbf > now && nbf - now > tolerance) {
debug('verify.error.notBefore');
return false;
}
}
const signers = {
secp256k1: getSigner(types.KeyType.SECP256K1),
es256k: getSigner(types.KeyType.SECP256K1),
ed25519: getSigner(types.KeyType.ED25519),
ethereum: getSigner(types.KeyType.ETHEREUM),
};
const alg = header.alg.toLowerCase();
if (signers[alg]) {
const msgHex = toHex(`${headerB64}.${bodyB64}`);
// If we are using v1.1 protocol, the message should be hashed before verify
const version = body.version && semver.coerce(body.version) ? semver.coerce(body.version).version : '';
if (version && version === JWT_VERSION_REQUIRE_HASH_BEFORE_SIGN) {
return signers[alg].verify(hasher(msgHex), signature, signerPk);
}
return signers[alg].verify(msgHex, signature, signerPk);
}
debug('verify.error.crypto');
return false;
} catch (err) {
debug('verify.error.exception');
debug(err);
return false;
}
};
module.exports = {
sign,
verify,
decode,
};
}
exports.verify = verify;
{
"name": "@arcblock/jwt",
"description": "JSON Web Token variant for arcblock DID solutions",
"version": "1.16.16",
"version": "1.16.17",
"author": {

@@ -21,5 +21,5 @@ "name": "wangshijun",

"dependencies": {
"@arcblock/did": "1.16.16",
"@ocap/mcrypto": "1.16.16",
"@ocap/util": "1.16.16",
"@arcblock/did": "1.16.17",
"@ocap/mcrypto": "1.16.17",
"@ocap/util": "1.16.17",
"debug": "^4.3.3",

@@ -30,3 +30,12 @@ "json-stable-stringify": "^1.0.1",

"devDependencies": {
"jest": "^27.3.1"
"@arcblock/eslint-config-ts": "0.2.2",
"@types/jest": "^27.5.1",
"@types/json-stable-stringify": "^1.0.34",
"@types/node": "^17.0.33",
"@types/semver": "^7.3.9",
"eslint": "^8.17.0",
"jest": "^27.3.1",
"ts-jest": "^28.0.0",
"tslib": "^2.4.0",
"typescript": "^4.6.4"
},

@@ -41,3 +50,4 @@ "homepage": "https://github.com/ArcBlock/asset-chain/tree/master/did/jwt",

"license": "Apache-2.0",
"main": "./lib/index.js",
"main": "lib/index.js",
"typings": "lib/index.d.ts",
"files": [

@@ -51,8 +61,12 @@ "lib"

"scripts": {
"lint": "eslint lib tests",
"lint:fix": "eslint --fix lib tests",
"lint": "eslint src tests",
"lint:fix": "eslint src tests --fix",
"test": "jest --forceExit --detectOpenHandles",
"coverage": "yarn test -- --coverage"
"coverage": "yarn test -- --coverage",
"clean": "rm -fr lib",
"prebuild": "npm run clean",
"build:watch": "npm run build -- -w",
"build": "tsc"
},
"gitHead": "051f9620995cf24407374cc4811b0fa6ed6dc7ca"
"gitHead": "489ce5e03bce27ddcd535390228b11ab56e7a2e3"
}
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