@arcblock/did
Advanced tools
Comparing version 0.29.0 to 0.29.1
@@ -36,12 +36,4 @@ // Generate by [js2dts@0.3.3](https://github.com/whxaxes/js2dts#readme) | ||
isValid: (did: string) => boolean; | ||
jwtSign: (did: string, sk: string, payload?: any) => string; | ||
jwtVerify: ( | ||
token: string, | ||
pk: string, | ||
tolerance?: number, | ||
verifyTimestamp?: boolean | ||
) => boolean; | ||
jwtDecode: (token: string, payloadOnly?: boolean) => any; | ||
} | ||
} | ||
export = _Lib; |
173
lib/index.js
@@ -9,8 +9,7 @@ /** | ||
const upperFirst = require('lodash/upperFirst'); | ||
const stringify = require('json-stable-stringify'); | ||
const Mcrypto = require('@arcblock/mcrypto'); | ||
const multibase = require('multibase'); | ||
const base64 = require('base64-url'); | ||
const { toHex, numberToHex, stripHexPrefix } = require('@arcblock/forge-util'); | ||
const { numberToHex, stripHexPrefix } = require('@arcblock/forge-util'); | ||
const { DID_PREFIX, toBits, toBytes, toStrictHex } = require('./util'); | ||
// eslint-disable-next-line | ||
@@ -219,167 +218,2 @@ const debug = require('debug')(require('../package.json').name); | ||
/** | ||
* Generate and sign a jwt token | ||
* | ||
* @public | ||
* @static | ||
* @param {string} did - address string | ||
* @param {string} sk - hex encoded secret key | ||
* @param {object} [payload={}] - data to be included before signing | ||
* @returns {string} hex encoded signature | ||
*/ | ||
const jwtSign = (did, sk, payload = {}) => { | ||
if (isValid(did) === false) { | ||
throw new Error('Cannot do jwtSign with invalid did'); | ||
} | ||
const type = toTypeInfo(did); | ||
const headers = { | ||
[types.KeyType.SECP256K1]: { | ||
alg: 'ES256K', | ||
type: 'JWT', | ||
}, | ||
[types.KeyType.ED25519]: { | ||
alg: 'Ed25519', | ||
type: 'JWT', | ||
}, | ||
}; | ||
// make header | ||
const header = headers[type.pk]; | ||
const headerB64 = base64.escape(base64.encode(stringify(header))); | ||
// make body | ||
const now = Math.floor(Date.now() / 1000); | ||
let body = Object.assign( | ||
{ | ||
iss: did.indexOf(DID_PREFIX) === 0 ? did : `${DID_PREFIX}${did}`, | ||
iat: now, | ||
nbf: now, | ||
exp: now + 5 * 60, | ||
}, | ||
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; | ||
}, {}); | ||
const bodyB64 = base64.escape(base64.encode(stringify(body))); | ||
// make signature | ||
const msgHex = toHex(`${headerB64}.${bodyB64}`); | ||
const sigHex = getSigner(type.pk).sign(msgHex, sk); | ||
const sigB64 = base64.escape(Buffer.from(stripHexPrefix(sigHex), 'hex').toString('base64')); | ||
return [headerB64, bodyB64, sigB64].join('.'); | ||
}; | ||
/** | ||
* Decode info from jwt token | ||
* | ||
* @public | ||
* @static | ||
* @param {string} token - jwt string | ||
* @param {boolean} [payloadOnly=false] | ||
* @returns {object} | ||
*/ | ||
const jwtDecode = (token, payloadOnly = true) => { | ||
const [headerB64, bodyB64, sigB64] = token.split('.'); | ||
const header = JSON.parse(base64.decode(base64.unescape(headerB64))); | ||
const body = JSON.parse(base64.decode(base64.unescape(bodyB64))); | ||
const sig = Buffer.from(base64.unescape(sigB64), 'base64').toString('hex'); | ||
if (payloadOnly) { | ||
return body; | ||
} | ||
return { header, body, signature: `0x${toStrictHex(sig)}` }; | ||
}; | ||
/** | ||
* Verify a jwt token signed with pk and certain issuer | ||
* | ||
* @public | ||
* @static | ||
* @param {string} token - the jwt token | ||
* @param {string} pk - hex encoded public key | ||
* @param {number} [tolerance=5] - number of seconds to tolerant expire | ||
* @param {boolean} [verifyTimestamp=true] - whether should be verify timestamps? | ||
* @returns {boolean} | ||
*/ | ||
const jwtVerify = (token, pk, tolerance = 5, verifyTimestamp = true) => { | ||
try { | ||
const [headerB64, bodyB64] = token.split('.'); | ||
const { header, body, signature } = jwtDecode(token, false); | ||
if (!signature) { | ||
debug('jwtVerify.error.emptySig'); | ||
return false; | ||
} | ||
if (!header.alg) { | ||
debug('jwtVerify.error.emptyAlg'); | ||
return false; | ||
} | ||
const did = body.iss; | ||
if (!did) { | ||
debug('jwtVerify.error.emptyDid'); | ||
return false; | ||
} | ||
if (isFromPublicKey(did, pk) === false) { | ||
debug('jwtVerify.error.did_pk_mismatch'); | ||
return false; | ||
} | ||
if (verifyTimestamp) { | ||
const now = Math.ceil(Date.now() / 1000) + tolerance; | ||
const exp = Number(body.exp) || 0; | ||
const iat = Number(body.iat) || 0; | ||
const nbf = Number(body.nbf) || 0; | ||
debug('jwtVerify.verifyTimestamp', { now, exp, iat, nbf }); | ||
if (exp && exp < now) { | ||
debug('jwtVerify.error.expired'); | ||
return false; | ||
} | ||
if (iat && iat > now) { | ||
debug('jwtVerify.error.issuedAt'); | ||
return false; | ||
} | ||
if (nbf && nbf > now) { | ||
debug('jwtVerify.error.notBefore'); | ||
return false; | ||
} | ||
} | ||
const signers = { | ||
secp256k1: getSigner(types.KeyType.SECP256K1), | ||
es256k: getSigner(types.KeyType.SECP256K1), | ||
ed25519: getSigner(types.KeyType.ED25519), | ||
}; | ||
const alg = header.alg.toLowerCase(); | ||
if (signers[alg]) { | ||
const msgHex = toHex(`${headerB64}.${bodyB64}`); | ||
return signers[alg].verify(msgHex, signature, pk); | ||
} | ||
debug('jwtVerify.error.crypto'); | ||
return false; | ||
} catch (err) { | ||
debug('jwtVerify.error.exception'); | ||
if (process.env.NODE_ENV !== 'test') { | ||
// eslint-disable-next-line | ||
console.error('jwtVerify.error', err); | ||
} | ||
return false; | ||
} | ||
}; | ||
/** | ||
* Convert did to address: remove `did:abt:` prefix if exists | ||
@@ -421,5 +255,2 @@ * | ||
isValid, | ||
jwtSign, | ||
jwtVerify, | ||
jwtDecode, | ||
}; |
{ | ||
"name": "@arcblock/did", | ||
"version": "0.29.0", | ||
"version": "0.29.1", | ||
"description": "Javascript lib to work with ArcBlock DID", | ||
@@ -50,9 +50,7 @@ "keywords": [ | ||
"@arcblock/mcrypto": "^0.29.0", | ||
"base64-url": "^2.2.0", | ||
"debug": "^4.1.1", | ||
"json-stable-stringify": "^1.0.1", | ||
"lodash": "^4.17.11", | ||
"multibase": "^0.6.0" | ||
}, | ||
"gitHead": "6e922db0d834db071d8208d56cbf46175192e301" | ||
"gitHead": "b4c1adec7c48c0b5ed07fb7d5548ccf5030dc3bd" | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
5
1
12416
313
- Removedbase64-url@^2.2.0
- Removedjson-stable-stringify@^1.0.1
- Removedbase64-url@2.3.3(transitive)
- Removedcall-bind@1.0.7(transitive)
- Removeddefine-data-property@1.1.4(transitive)
- Removedes-define-property@1.0.0(transitive)
- Removedes-errors@1.3.0(transitive)
- Removedfunction-bind@1.1.2(transitive)
- Removedget-intrinsic@1.2.4(transitive)
- Removedgopd@1.0.1(transitive)
- Removedhas-property-descriptors@1.0.2(transitive)
- Removedhas-proto@1.0.3(transitive)
- Removedhas-symbols@1.0.3(transitive)
- Removedhasown@2.0.2(transitive)
- Removedisarray@2.0.5(transitive)
- Removedjson-stable-stringify@1.1.1(transitive)
- Removedjsonify@0.0.1(transitive)
- Removedobject-keys@1.1.1(transitive)
- Removedset-function-length@1.2.2(transitive)