Comparing version 3.2.0 to 3.3.0
@@ -5,2 +5,14 @@ # Changelog | ||
## [3.3.0](https://github.com/panva/jose/compare/v3.2.0...v3.3.0) (2020-12-06) | ||
### Features | ||
* support recognizing proprietary `crit` header parameters ([5163116](https://github.com/panva/jose/commit/5163116ca1c091871ed0c601c9fbc1dbe94599cd)), closes [#123](https://github.com/panva/jose/issues/123) | ||
### Bug Fixes | ||
* reject JWTs with b64: false ([691b44a](https://github.com/panva/jose/commit/691b44ad4717c82a06539facfedff48fa0e9c6a9)) | ||
## [3.2.0](https://github.com/panva/jose/compare/v3.1.3...v3.2.0) (2020-12-02) | ||
@@ -7,0 +19,0 @@ |
@@ -14,3 +14,3 @@ import { JOSEAlgNotAllowed, JOSENotSupported, JWEInvalid } from '../../util/errors.js'; | ||
const generateCek = cekFactory(random); | ||
const checkCrit = validateCrit.bind(undefined, JWEInvalid, new Map()); | ||
const checkExtensions = validateCrit.bind(undefined, JWEInvalid, new Map()); | ||
const checkAlgOption = validateAlgorithms.bind(undefined, 'keyManagementAlgorithms'); | ||
@@ -62,3 +62,3 @@ const checkEncOption = validateAlgorithms.bind(undefined, 'contentEncryptionAlgorithms'); | ||
}; | ||
checkCrit(parsedProt, joseHeader); | ||
checkExtensions(options === null || options === void 0 ? void 0 : options.crit, parsedProt, joseHeader); | ||
if (joseHeader.zip !== undefined) { | ||
@@ -65,0 +65,0 @@ if (!parsedProt || !parsedProt.zip) { |
@@ -12,3 +12,3 @@ import ivFactory from '../../lib/iv.js'; | ||
const generateIv = ivFactory(random); | ||
const checkCrit = validateCrit.bind(undefined, JWEInvalid, new Map()); | ||
const checkExtensions = validateCrit.bind(undefined, JWEInvalid, new Map()); | ||
export default class FlattenedEncrypt { | ||
@@ -76,3 +76,3 @@ constructor(plaintext) { | ||
}; | ||
checkCrit(this._protectedHeader, joseHeader); | ||
checkExtensions(options === null || options === void 0 ? void 0 : options.crit, this._protectedHeader, joseHeader); | ||
if (joseHeader.zip !== undefined) { | ||
@@ -79,0 +79,0 @@ if (!this._protectedHeader || !this._protectedHeader.zip) { |
@@ -10,4 +10,4 @@ import FlattenedSign from '../flattened/sign.js'; | ||
} | ||
async sign(key) { | ||
const jws = await this._flattened.sign(key); | ||
async sign(key, options) { | ||
const jws = await this._flattened.sign(key, options); | ||
if (jws.payload === undefined) { | ||
@@ -14,0 +14,0 @@ throw new TypeError('use the flattened module for creating JWS with b64: false'); |
@@ -27,3 +27,3 @@ import isDisjoint from '../../lib/is_disjoint.js'; | ||
} | ||
async sign(key) { | ||
async sign(key, options) { | ||
if (!this._protectedHeader && !this._unprotectedHeader) { | ||
@@ -39,3 +39,3 @@ throw new JWSInvalid('either setProtectedHeader or setUnprotectedHeader must be called before #sign()'); | ||
}; | ||
const extensions = checkExtensions(this._protectedHeader, joseHeader); | ||
const extensions = checkExtensions(options === null || options === void 0 ? void 0 : options.crit, this._protectedHeader, joseHeader); | ||
let b64 = true; | ||
@@ -42,0 +42,0 @@ if (extensions.has('b64')) { |
@@ -43,3 +43,3 @@ import { JOSEAlgNotAllowed, JWSInvalid, JWSSignatureVerificationFailed } from '../../util/errors.js'; | ||
}; | ||
const extensions = checkExtensions(parsedProt, joseHeader); | ||
const extensions = checkExtensions(options === null || options === void 0 ? void 0 : options.crit, parsedProt, joseHeader); | ||
let b64 = true; | ||
@@ -46,0 +46,0 @@ if (extensions.has('b64')) { |
@@ -10,3 +10,3 @@ import CompactSign from '../jws/compact/sign.js'; | ||
} | ||
async sign(key) { | ||
async sign(key, options) { | ||
var _a; | ||
@@ -18,4 +18,4 @@ const sig = new CompactSign(encoder.encode(JSON.stringify(this._payload))); | ||
} | ||
return sig.sign(key); | ||
return sig.sign(key, options); | ||
} | ||
} |
import verify from '../jws/compact/verify.js'; | ||
import jwtPayload from '../lib/jwt_claims_set.js'; | ||
import { JWTInvalid } from '../util/errors.js'; | ||
export default async function jwtVerify(jwt, key, options) { | ||
var _a; | ||
const verified = await verify(jwt, key, options); | ||
if (((_a = verified.protectedHeader.crit) === null || _a === void 0 ? void 0 : _a.includes('b64')) && verified.protectedHeader.b64 === false) { | ||
throw new JWTInvalid('JWTs MUST NOT use unencoded payload'); | ||
} | ||
const payload = jwtPayload(verified.protectedHeader, verified.payload, options); | ||
return { payload, protectedHeader: verified.protectedHeader }; | ||
} |
import { JOSENotSupported } from '../util/errors.js'; | ||
function validateCrit(Err, supported, protectedHeader, joseHeader) { | ||
function validateCrit(Err, recognizedDefault, recognizedOption, protectedHeader, joseHeader) { | ||
if (joseHeader.crit !== undefined && protectedHeader.crit === undefined) { | ||
@@ -14,5 +14,12 @@ throw new Err('"crit" (Critical) Header Parameter MUST be integrity protected'); | ||
} | ||
let recognized; | ||
if (recognizedOption !== undefined) { | ||
recognized = new Map([...Object.entries(recognizedOption), ...recognizedDefault.entries()]); | ||
} | ||
else { | ||
recognized = recognizedDefault; | ||
} | ||
for (const parameter of protectedHeader.crit) { | ||
if (!supported.has(parameter)) { | ||
throw new JOSENotSupported(`Extension Header Parameter "${parameter}" is not supported by this implementation`); | ||
if (!recognized.has(parameter)) { | ||
throw new JOSENotSupported(`Extension Header Parameter "${parameter}" is not recognized`); | ||
} | ||
@@ -22,3 +29,3 @@ if (joseHeader[parameter] === undefined) { | ||
} | ||
else if (supported.get(parameter) && protectedHeader[parameter] === undefined) { | ||
else if (recognized.get(parameter) && protectedHeader[parameter] === undefined) { | ||
throw new Err(`Extension Header Parameter "${parameter}" MUST be integrity protected`); | ||
@@ -25,0 +32,0 @@ } |
@@ -16,3 +16,3 @@ "use strict"; | ||
const generateCek = cek_js_1.default(random_js_1.default); | ||
const checkCrit = validate_crit_js_1.default.bind(undefined, errors_js_1.JWEInvalid, new Map()); | ||
const checkExtensions = validate_crit_js_1.default.bind(undefined, errors_js_1.JWEInvalid, new Map()); | ||
const checkAlgOption = validate_algorithms_js_1.default.bind(undefined, 'keyManagementAlgorithms'); | ||
@@ -64,3 +64,3 @@ const checkEncOption = validate_algorithms_js_1.default.bind(undefined, 'contentEncryptionAlgorithms'); | ||
}; | ||
checkCrit(parsedProt, joseHeader); | ||
checkExtensions(options === null || options === void 0 ? void 0 : options.crit, parsedProt, joseHeader); | ||
if (joseHeader.zip !== undefined) { | ||
@@ -67,0 +67,0 @@ if (!parsedProt || !parsedProt.zip) { |
@@ -14,3 +14,3 @@ "use strict"; | ||
const generateIv = iv_js_1.default(random_js_1.default); | ||
const checkCrit = validate_crit_js_1.default.bind(undefined, errors_js_1.JWEInvalid, new Map()); | ||
const checkExtensions = validate_crit_js_1.default.bind(undefined, errors_js_1.JWEInvalid, new Map()); | ||
class FlattenedEncrypt { | ||
@@ -78,3 +78,3 @@ constructor(plaintext) { | ||
}; | ||
checkCrit(this._protectedHeader, joseHeader); | ||
checkExtensions(options === null || options === void 0 ? void 0 : options.crit, this._protectedHeader, joseHeader); | ||
if (joseHeader.zip !== undefined) { | ||
@@ -81,0 +81,0 @@ if (!this._protectedHeader || !this._protectedHeader.zip) { |
@@ -12,4 +12,4 @@ "use strict"; | ||
} | ||
async sign(key) { | ||
const jws = await this._flattened.sign(key); | ||
async sign(key, options) { | ||
const jws = await this._flattened.sign(key, options); | ||
if (jws.payload === undefined) { | ||
@@ -16,0 +16,0 @@ throw new TypeError('use the flattened module for creating JWS with b64: false'); |
@@ -29,3 +29,3 @@ "use strict"; | ||
} | ||
async sign(key) { | ||
async sign(key, options) { | ||
if (!this._protectedHeader && !this._unprotectedHeader) { | ||
@@ -41,3 +41,3 @@ throw new errors_js_1.JWSInvalid('either setProtectedHeader or setUnprotectedHeader must be called before #sign()'); | ||
}; | ||
const extensions = checkExtensions(this._protectedHeader, joseHeader); | ||
const extensions = checkExtensions(options === null || options === void 0 ? void 0 : options.crit, this._protectedHeader, joseHeader); | ||
let b64 = true; | ||
@@ -44,0 +44,0 @@ if (extensions.has('b64')) { |
@@ -45,3 +45,3 @@ "use strict"; | ||
}; | ||
const extensions = checkExtensions(parsedProt, joseHeader); | ||
const extensions = checkExtensions(options === null || options === void 0 ? void 0 : options.crit, parsedProt, joseHeader); | ||
let b64 = true; | ||
@@ -48,0 +48,0 @@ if (extensions.has('b64')) { |
@@ -12,3 +12,3 @@ "use strict"; | ||
} | ||
async sign(key) { | ||
async sign(key, options) { | ||
var _a; | ||
@@ -20,5 +20,5 @@ const sig = new sign_js_1.default(buffer_utils_js_1.encoder.encode(JSON.stringify(this._payload))); | ||
} | ||
return sig.sign(key); | ||
return sig.sign(key, options); | ||
} | ||
} | ||
exports.default = SignJWT; |
@@ -5,4 +5,9 @@ "use strict"; | ||
const jwt_claims_set_js_1 = require("../lib/jwt_claims_set.js"); | ||
const errors_js_1 = require("../util/errors.js"); | ||
async function jwtVerify(jwt, key, options) { | ||
var _a; | ||
const verified = await verify_js_1.default(jwt, key, options); | ||
if (((_a = verified.protectedHeader.crit) === null || _a === void 0 ? void 0 : _a.includes('b64')) && verified.protectedHeader.b64 === false) { | ||
throw new errors_js_1.JWTInvalid('JWTs MUST NOT use unencoded payload'); | ||
} | ||
const payload = jwt_claims_set_js_1.default(verified.protectedHeader, verified.payload, options); | ||
@@ -9,0 +14,0 @@ return { payload, protectedHeader: verified.protectedHeader }; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const errors_js_1 = require("../util/errors.js"); | ||
function validateCrit(Err, supported, protectedHeader, joseHeader) { | ||
function validateCrit(Err, recognizedDefault, recognizedOption, protectedHeader, joseHeader) { | ||
if (joseHeader.crit !== undefined && protectedHeader.crit === undefined) { | ||
@@ -16,5 +16,12 @@ throw new Err('"crit" (Critical) Header Parameter MUST be integrity protected'); | ||
} | ||
let recognized; | ||
if (recognizedOption !== undefined) { | ||
recognized = new Map([...Object.entries(recognizedOption), ...recognizedDefault.entries()]); | ||
} | ||
else { | ||
recognized = recognizedDefault; | ||
} | ||
for (const parameter of protectedHeader.crit) { | ||
if (!supported.has(parameter)) { | ||
throw new errors_js_1.JOSENotSupported(`Extension Header Parameter "${parameter}" is not supported by this implementation`); | ||
if (!recognized.has(parameter)) { | ||
throw new errors_js_1.JOSENotSupported(`Extension Header Parameter "${parameter}" is not recognized`); | ||
} | ||
@@ -24,3 +31,3 @@ if (joseHeader[parameter] === undefined) { | ||
} | ||
else if (supported.get(parameter) && protectedHeader[parameter] === undefined) { | ||
else if (recognized.get(parameter) && protectedHeader[parameter] === undefined) { | ||
throw new Err(`Extension Header Parameter "${parameter}" MUST be integrity protected`); | ||
@@ -27,0 +34,0 @@ } |
@@ -14,3 +14,3 @@ import { JOSEAlgNotAllowed, JOSENotSupported, JWEInvalid } from '../../util/errors.js'; | ||
const generateCek = cekFactory(random); | ||
const checkCrit = validateCrit.bind(undefined, JWEInvalid, new Map()); | ||
const checkExtensions = validateCrit.bind(undefined, JWEInvalid, new Map()); | ||
const checkAlgOption = validateAlgorithms.bind(undefined, 'keyManagementAlgorithms'); | ||
@@ -62,3 +62,3 @@ const checkEncOption = validateAlgorithms.bind(undefined, 'contentEncryptionAlgorithms'); | ||
}; | ||
checkCrit(parsedProt, joseHeader); | ||
checkExtensions(options === null || options === void 0 ? void 0 : options.crit, parsedProt, joseHeader); | ||
if (joseHeader.zip !== undefined) { | ||
@@ -65,0 +65,0 @@ if (!parsedProt || !parsedProt.zip) { |
@@ -12,3 +12,3 @@ import ivFactory from '../../lib/iv.js'; | ||
const generateIv = ivFactory(random); | ||
const checkCrit = validateCrit.bind(undefined, JWEInvalid, new Map()); | ||
const checkExtensions = validateCrit.bind(undefined, JWEInvalid, new Map()); | ||
export default class FlattenedEncrypt { | ||
@@ -76,3 +76,3 @@ constructor(plaintext) { | ||
}; | ||
checkCrit(this._protectedHeader, joseHeader); | ||
checkExtensions(options === null || options === void 0 ? void 0 : options.crit, this._protectedHeader, joseHeader); | ||
if (joseHeader.zip !== undefined) { | ||
@@ -79,0 +79,0 @@ if (!this._protectedHeader || !this._protectedHeader.zip) { |
@@ -10,4 +10,4 @@ import FlattenedSign from '../flattened/sign.js'; | ||
} | ||
async sign(key) { | ||
const jws = await this._flattened.sign(key); | ||
async sign(key, options) { | ||
const jws = await this._flattened.sign(key, options); | ||
if (jws.payload === undefined) { | ||
@@ -14,0 +14,0 @@ throw new TypeError('use the flattened module for creating JWS with b64: false'); |
@@ -27,3 +27,3 @@ import isDisjoint from '../../lib/is_disjoint.js'; | ||
} | ||
async sign(key) { | ||
async sign(key, options) { | ||
if (!this._protectedHeader && !this._unprotectedHeader) { | ||
@@ -39,3 +39,3 @@ throw new JWSInvalid('either setProtectedHeader or setUnprotectedHeader must be called before #sign()'); | ||
}; | ||
const extensions = checkExtensions(this._protectedHeader, joseHeader); | ||
const extensions = checkExtensions(options === null || options === void 0 ? void 0 : options.crit, this._protectedHeader, joseHeader); | ||
let b64 = true; | ||
@@ -42,0 +42,0 @@ if (extensions.has('b64')) { |
@@ -43,3 +43,3 @@ import { JOSEAlgNotAllowed, JWSInvalid, JWSSignatureVerificationFailed } from '../../util/errors.js'; | ||
}; | ||
const extensions = checkExtensions(parsedProt, joseHeader); | ||
const extensions = checkExtensions(options === null || options === void 0 ? void 0 : options.crit, parsedProt, joseHeader); | ||
let b64 = true; | ||
@@ -46,0 +46,0 @@ if (extensions.has('b64')) { |
@@ -10,3 +10,3 @@ import CompactSign from '../jws/compact/sign.js'; | ||
} | ||
async sign(key) { | ||
async sign(key, options) { | ||
var _a; | ||
@@ -18,4 +18,4 @@ const sig = new CompactSign(encoder.encode(JSON.stringify(this._payload))); | ||
} | ||
return sig.sign(key); | ||
return sig.sign(key, options); | ||
} | ||
} |
import verify from '../jws/compact/verify.js'; | ||
import jwtPayload from '../lib/jwt_claims_set.js'; | ||
import { JWTInvalid } from '../util/errors.js'; | ||
export default async function jwtVerify(jwt, key, options) { | ||
var _a; | ||
const verified = await verify(jwt, key, options); | ||
if (((_a = verified.protectedHeader.crit) === null || _a === void 0 ? void 0 : _a.includes('b64')) && verified.protectedHeader.b64 === false) { | ||
throw new JWTInvalid('JWTs MUST NOT use unencoded payload'); | ||
} | ||
const payload = jwtPayload(verified.protectedHeader, verified.payload, options); | ||
return { payload, protectedHeader: verified.protectedHeader }; | ||
} |
import { JOSENotSupported } from '../util/errors.js'; | ||
function validateCrit(Err, supported, protectedHeader, joseHeader) { | ||
function validateCrit(Err, recognizedDefault, recognizedOption, protectedHeader, joseHeader) { | ||
if (joseHeader.crit !== undefined && protectedHeader.crit === undefined) { | ||
@@ -14,5 +14,12 @@ throw new Err('"crit" (Critical) Header Parameter MUST be integrity protected'); | ||
} | ||
let recognized; | ||
if (recognizedOption !== undefined) { | ||
recognized = new Map([...Object.entries(recognizedOption), ...recognizedDefault.entries()]); | ||
} | ||
else { | ||
recognized = recognizedDefault; | ||
} | ||
for (const parameter of protectedHeader.crit) { | ||
if (!supported.has(parameter)) { | ||
throw new JOSENotSupported(`Extension Header Parameter "${parameter}" is not supported by this implementation`); | ||
if (!recognized.has(parameter)) { | ||
throw new JOSENotSupported(`Extension Header Parameter "${parameter}" is not recognized`); | ||
} | ||
@@ -22,3 +29,3 @@ if (joseHeader[parameter] === undefined) { | ||
} | ||
else if (supported.get(parameter) && protectedHeader[parameter] === undefined) { | ||
else if (recognized.get(parameter) && protectedHeader[parameter] === undefined) { | ||
throw new Err(`Extension Header Parameter "${parameter}" MUST be integrity protected`); | ||
@@ -25,0 +32,0 @@ } |
@@ -16,3 +16,3 @@ "use strict"; | ||
const generateCek = cek_js_1.default(random_js_1.default); | ||
const checkCrit = validate_crit_js_1.default.bind(undefined, errors_js_1.JWEInvalid, new Map()); | ||
const checkExtensions = validate_crit_js_1.default.bind(undefined, errors_js_1.JWEInvalid, new Map()); | ||
const checkAlgOption = validate_algorithms_js_1.default.bind(undefined, 'keyManagementAlgorithms'); | ||
@@ -64,3 +64,3 @@ const checkEncOption = validate_algorithms_js_1.default.bind(undefined, 'contentEncryptionAlgorithms'); | ||
}; | ||
checkCrit(parsedProt, joseHeader); | ||
checkExtensions(options?.crit, parsedProt, joseHeader); | ||
if (joseHeader.zip !== undefined) { | ||
@@ -67,0 +67,0 @@ if (!parsedProt || !parsedProt.zip) { |
@@ -14,3 +14,3 @@ "use strict"; | ||
const generateIv = iv_js_1.default(random_js_1.default); | ||
const checkCrit = validate_crit_js_1.default.bind(undefined, errors_js_1.JWEInvalid, new Map()); | ||
const checkExtensions = validate_crit_js_1.default.bind(undefined, errors_js_1.JWEInvalid, new Map()); | ||
class FlattenedEncrypt { | ||
@@ -78,3 +78,3 @@ constructor(plaintext) { | ||
}; | ||
checkCrit(this._protectedHeader, joseHeader); | ||
checkExtensions(options?.crit, this._protectedHeader, joseHeader); | ||
if (joseHeader.zip !== undefined) { | ||
@@ -81,0 +81,0 @@ if (!this._protectedHeader || !this._protectedHeader.zip) { |
@@ -12,4 +12,4 @@ "use strict"; | ||
} | ||
async sign(key) { | ||
const jws = await this._flattened.sign(key); | ||
async sign(key, options) { | ||
const jws = await this._flattened.sign(key, options); | ||
if (jws.payload === undefined) { | ||
@@ -16,0 +16,0 @@ throw new TypeError('use the flattened module for creating JWS with b64: false'); |
@@ -29,3 +29,3 @@ "use strict"; | ||
} | ||
async sign(key) { | ||
async sign(key, options) { | ||
if (!this._protectedHeader && !this._unprotectedHeader) { | ||
@@ -41,3 +41,3 @@ throw new errors_js_1.JWSInvalid('either setProtectedHeader or setUnprotectedHeader must be called before #sign()'); | ||
}; | ||
const extensions = checkExtensions(this._protectedHeader, joseHeader); | ||
const extensions = checkExtensions(options?.crit, this._protectedHeader, joseHeader); | ||
let b64 = true; | ||
@@ -44,0 +44,0 @@ if (extensions.has('b64')) { |
@@ -45,3 +45,3 @@ "use strict"; | ||
}; | ||
const extensions = checkExtensions(parsedProt, joseHeader); | ||
const extensions = checkExtensions(options?.crit, parsedProt, joseHeader); | ||
let b64 = true; | ||
@@ -48,0 +48,0 @@ if (extensions.has('b64')) { |
@@ -12,3 +12,3 @@ "use strict"; | ||
} | ||
async sign(key) { | ||
async sign(key, options) { | ||
const sig = new sign_js_1.default(buffer_utils_js_1.encoder.encode(JSON.stringify(this._payload))); | ||
@@ -19,5 +19,5 @@ sig.setProtectedHeader(this._protectedHeader); | ||
} | ||
return sig.sign(key); | ||
return sig.sign(key, options); | ||
} | ||
} | ||
exports.default = SignJWT; |
@@ -5,4 +5,8 @@ "use strict"; | ||
const jwt_claims_set_js_1 = require("../lib/jwt_claims_set.js"); | ||
const errors_js_1 = require("../util/errors.js"); | ||
async function jwtVerify(jwt, key, options) { | ||
const verified = await verify_js_1.default(jwt, key, options); | ||
if (verified.protectedHeader.crit?.includes('b64') && verified.protectedHeader.b64 === false) { | ||
throw new errors_js_1.JWTInvalid('JWTs MUST NOT use unencoded payload'); | ||
} | ||
const payload = jwt_claims_set_js_1.default(verified.protectedHeader, verified.payload, options); | ||
@@ -9,0 +13,0 @@ return { payload, protectedHeader: verified.protectedHeader }; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const errors_js_1 = require("../util/errors.js"); | ||
function validateCrit(Err, supported, protectedHeader, joseHeader) { | ||
function validateCrit(Err, recognizedDefault, recognizedOption, protectedHeader, joseHeader) { | ||
if (joseHeader.crit !== undefined && protectedHeader.crit === undefined) { | ||
@@ -16,5 +16,12 @@ throw new Err('"crit" (Critical) Header Parameter MUST be integrity protected'); | ||
} | ||
let recognized; | ||
if (recognizedOption !== undefined) { | ||
recognized = new Map([...Object.entries(recognizedOption), ...recognizedDefault.entries()]); | ||
} | ||
else { | ||
recognized = recognizedDefault; | ||
} | ||
for (const parameter of protectedHeader.crit) { | ||
if (!supported.has(parameter)) { | ||
throw new errors_js_1.JOSENotSupported(`Extension Header Parameter "${parameter}" is not supported by this implementation`); | ||
if (!recognized.has(parameter)) { | ||
throw new errors_js_1.JOSENotSupported(`Extension Header Parameter "${parameter}" is not recognized`); | ||
} | ||
@@ -24,3 +31,3 @@ if (joseHeader[parameter] === undefined) { | ||
} | ||
else if (supported.get(parameter) && protectedHeader[parameter] === undefined) { | ||
else if (recognized.get(parameter) && protectedHeader[parameter] === undefined) { | ||
throw new Err(`Extension Header Parameter "${parameter}" MUST be integrity protected`); | ||
@@ -27,0 +34,0 @@ } |
@@ -14,3 +14,3 @@ import { JOSEAlgNotAllowed, JOSENotSupported, JWEInvalid } from '../../util/errors.js'; | ||
const generateCek = cekFactory(random); | ||
const checkCrit = validateCrit.bind(undefined, JWEInvalid, new Map()); | ||
const checkExtensions = validateCrit.bind(undefined, JWEInvalid, new Map()); | ||
const checkAlgOption = validateAlgorithms.bind(undefined, 'keyManagementAlgorithms'); | ||
@@ -62,3 +62,3 @@ const checkEncOption = validateAlgorithms.bind(undefined, 'contentEncryptionAlgorithms'); | ||
}; | ||
checkCrit(parsedProt, joseHeader); | ||
checkExtensions(options?.crit, parsedProt, joseHeader); | ||
if (joseHeader.zip !== undefined) { | ||
@@ -65,0 +65,0 @@ if (!parsedProt || !parsedProt.zip) { |
@@ -12,3 +12,3 @@ import ivFactory from '../../lib/iv.js'; | ||
const generateIv = ivFactory(random); | ||
const checkCrit = validateCrit.bind(undefined, JWEInvalid, new Map()); | ||
const checkExtensions = validateCrit.bind(undefined, JWEInvalid, new Map()); | ||
export default class FlattenedEncrypt { | ||
@@ -76,3 +76,3 @@ constructor(plaintext) { | ||
}; | ||
checkCrit(this._protectedHeader, joseHeader); | ||
checkExtensions(options?.crit, this._protectedHeader, joseHeader); | ||
if (joseHeader.zip !== undefined) { | ||
@@ -79,0 +79,0 @@ if (!this._protectedHeader || !this._protectedHeader.zip) { |
@@ -10,4 +10,4 @@ import FlattenedSign from '../flattened/sign.js'; | ||
} | ||
async sign(key) { | ||
const jws = await this._flattened.sign(key); | ||
async sign(key, options) { | ||
const jws = await this._flattened.sign(key, options); | ||
if (jws.payload === undefined) { | ||
@@ -14,0 +14,0 @@ throw new TypeError('use the flattened module for creating JWS with b64: false'); |
@@ -27,3 +27,3 @@ import isDisjoint from '../../lib/is_disjoint.js'; | ||
} | ||
async sign(key) { | ||
async sign(key, options) { | ||
if (!this._protectedHeader && !this._unprotectedHeader) { | ||
@@ -39,3 +39,3 @@ throw new JWSInvalid('either setProtectedHeader or setUnprotectedHeader must be called before #sign()'); | ||
}; | ||
const extensions = checkExtensions(this._protectedHeader, joseHeader); | ||
const extensions = checkExtensions(options?.crit, this._protectedHeader, joseHeader); | ||
let b64 = true; | ||
@@ -42,0 +42,0 @@ if (extensions.has('b64')) { |
@@ -43,3 +43,3 @@ import { JOSEAlgNotAllowed, JWSInvalid, JWSSignatureVerificationFailed } from '../../util/errors.js'; | ||
}; | ||
const extensions = checkExtensions(parsedProt, joseHeader); | ||
const extensions = checkExtensions(options?.crit, parsedProt, joseHeader); | ||
let b64 = true; | ||
@@ -46,0 +46,0 @@ if (extensions.has('b64')) { |
@@ -10,3 +10,3 @@ import CompactSign from '../jws/compact/sign.js'; | ||
} | ||
async sign(key) { | ||
async sign(key, options) { | ||
const sig = new CompactSign(encoder.encode(JSON.stringify(this._payload))); | ||
@@ -17,4 +17,4 @@ sig.setProtectedHeader(this._protectedHeader); | ||
} | ||
return sig.sign(key); | ||
return sig.sign(key, options); | ||
} | ||
} |
import verify from '../jws/compact/verify.js'; | ||
import jwtPayload from '../lib/jwt_claims_set.js'; | ||
import { JWTInvalid } from '../util/errors.js'; | ||
export default async function jwtVerify(jwt, key, options) { | ||
const verified = await verify(jwt, key, options); | ||
if (verified.protectedHeader.crit?.includes('b64') && verified.protectedHeader.b64 === false) { | ||
throw new JWTInvalid('JWTs MUST NOT use unencoded payload'); | ||
} | ||
const payload = jwtPayload(verified.protectedHeader, verified.payload, options); | ||
return { payload, protectedHeader: verified.protectedHeader }; | ||
} |
import { JOSENotSupported } from '../util/errors.js'; | ||
function validateCrit(Err, supported, protectedHeader, joseHeader) { | ||
function validateCrit(Err, recognizedDefault, recognizedOption, protectedHeader, joseHeader) { | ||
if (joseHeader.crit !== undefined && protectedHeader.crit === undefined) { | ||
@@ -14,5 +14,12 @@ throw new Err('"crit" (Critical) Header Parameter MUST be integrity protected'); | ||
} | ||
let recognized; | ||
if (recognizedOption !== undefined) { | ||
recognized = new Map([...Object.entries(recognizedOption), ...recognizedDefault.entries()]); | ||
} | ||
else { | ||
recognized = recognizedDefault; | ||
} | ||
for (const parameter of protectedHeader.crit) { | ||
if (!supported.has(parameter)) { | ||
throw new JOSENotSupported(`Extension Header Parameter "${parameter}" is not supported by this implementation`); | ||
if (!recognized.has(parameter)) { | ||
throw new JOSENotSupported(`Extension Header Parameter "${parameter}" is not recognized`); | ||
} | ||
@@ -22,3 +29,3 @@ if (joseHeader[parameter] === undefined) { | ||
} | ||
else if (supported.get(parameter) && protectedHeader[parameter] === undefined) { | ||
else if (recognized.get(parameter) && protectedHeader[parameter] === undefined) { | ||
throw new Err(`Extension Header Parameter "${parameter}" MUST be integrity protected`); | ||
@@ -25,0 +32,0 @@ } |
@@ -1,2 +0,2 @@ | ||
import type { JWSHeaderParameters, KeyLike } from '../../types.d'; | ||
import type { JWSHeaderParameters, KeyLike, SignOptions } from '../../types.d'; | ||
/** | ||
@@ -55,5 +55,6 @@ * The CompactSign class is a utility for creating Compact JWS strings. | ||
* @param key Private Key or Secret to sign the JWS with. | ||
* @param options JWS Sign options. | ||
*/ | ||
sign(key: KeyLike): Promise<string>; | ||
sign(key: KeyLike, options?: SignOptions): Promise<string>; | ||
} | ||
export type { JWSHeaderParameters, KeyLike }; |
@@ -1,2 +0,2 @@ | ||
import type { KeyLike, FlattenedJWS, JWSHeaderParameters } from '../../types.d'; | ||
import type { KeyLike, FlattenedJWS, JWSHeaderParameters, SignOptions } from '../../types.d'; | ||
/** | ||
@@ -62,5 +62,6 @@ * The FlattenedSign class is a utility for creating Flattened JWS objects. | ||
* @param key Private Key or Secret to sign the JWS with. | ||
* @param options JWS Sign options. | ||
*/ | ||
sign(key: KeyLike): Promise<FlattenedJWS>; | ||
sign(key: KeyLike, options?: SignOptions): Promise<FlattenedJWS>; | ||
} | ||
export type { KeyLike, FlattenedJWS, JWSHeaderParameters }; |
@@ -1,2 +0,2 @@ | ||
import type { JWSHeaderParameters, JWTPayload, KeyLike } from '../types.d'; | ||
import type { JWSHeaderParameters, JWTPayload, KeyLike, SignOptions } from '../types.d'; | ||
import ProduceJWT from '../lib/jwt_producer.js'; | ||
@@ -55,5 +55,6 @@ /** | ||
* @param key Private Key or Secret to sign the JWT with. | ||
* @param options JWT Sign options. | ||
*/ | ||
sign(key: KeyLike): Promise<string>; | ||
sign(key: KeyLike, options?: SignOptions): Promise<string>; | ||
} | ||
export type { JWSHeaderParameters, JWTPayload, KeyLike }; |
@@ -317,5 +317,34 @@ /* eslint-disable @typescript-eslint/naming-convention */ | ||
/** | ||
* Shared Interface with a "crit" property for all sign and verify operations. | ||
*/ | ||
export interface CritOption { | ||
/** | ||
* An object with keys representing recognized "crit" (Critical) Header Parameter | ||
* names. The value for those is either `true` or `false`. `true` when the | ||
* Header Parameter MUST be integrity protected, `false` when it's irrelevant. | ||
* | ||
* This makes the "Extension Header Parameter "${parameter}" is not recognized" | ||
* error go away. | ||
* | ||
* Use this when a given JWS/JWT/JWE profile requires the use of proprietary | ||
* non-registered "crit" (Critical) Header Parameters. This will only make sure | ||
* the Header Parameter is syntactically correct when provided and that it is | ||
* optionally integrity protected. It will not process the Header Parameter in | ||
* any way or reject if the operation if it is missing. You MUST still | ||
* verify the Header Parameter was present and process it according to the | ||
* profile's validation steps after the operation succeeds. | ||
* | ||
* The JWS extension Header Parameter `b64` is always recognized and processed | ||
* properly. No other registered Header Parameters that need this kind of | ||
* default built-in treatment are currently available. | ||
*/ | ||
crit?: { | ||
[propName: string]: boolean | ||
} | ||
} | ||
/** | ||
* JWE Decryption options. | ||
*/ | ||
export interface DecryptOptions { | ||
export interface DecryptOptions extends CritOption { | ||
/** | ||
@@ -341,3 +370,3 @@ * A list of accepted JWE "alg" (Algorithm) Header Parameter values. | ||
*/ | ||
export interface EncryptOptions { | ||
export interface EncryptOptions extends CritOption { | ||
/** | ||
@@ -395,3 +424,3 @@ * In a browser runtime you have to provide an implementation for Deflate Raw | ||
*/ | ||
export interface VerifyOptions { | ||
export interface VerifyOptions extends CritOption { | ||
/** | ||
@@ -404,2 +433,7 @@ * A list of accepted JWS "alg" (Algorithm) Header Parameter values. | ||
/** | ||
* JWS Signing options. | ||
*/ | ||
export interface SignOptions extends CritOption {} | ||
/** | ||
* Recognized JWT Claims Set members, any other members | ||
@@ -406,0 +440,0 @@ * may also be present. |
{ | ||
"name": "jose", | ||
"version": "3.2.0", | ||
"version": "3.3.0", | ||
"description": "JSON Web Almost Everything - JWA, JWS, JWE, JWK, JWT, JWKS with no dependencies", | ||
@@ -309,12 +309,2 @@ "keywords": [ | ||
}, | ||
"husky": { | ||
"hooks": { | ||
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS" | ||
} | ||
}, | ||
"commitlint": { | ||
"extends": [ | ||
"@commitlint/config-conventional" | ||
] | ||
}, | ||
"devDependencies": { | ||
@@ -321,0 +311,0 @@ "@types/node": "^14.14.9", |
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
643447
397
15095