diff --git a/lib/jwt/verify.js b/lib/jwt/verify.js index 04cd5f7f11..4640ef35bd 100644 --- a/lib/jwt/verify.js +++ b/lib/jwt/verify.js @@ -36,6 +36,7 @@ const isStringOrArrayOfStrings = (value, label, required = false) => { } const isNotArrayOfStrings = val => !Array.isArray(val) || val.length === 0 || val.some(isNotString) +const normalizeTyp = (value) => value.toLowerCase().replace(/^application\//, '') const validateOptions = ({ algorithms, audience, clockTolerance, complete = false, crit, ignoreExp = false, @@ -254,7 +255,7 @@ module.exports = (token, key, options = {}) => { throw new JWTClaimInvalid('unexpected "aud" claim value', 'aud', 'check_failed') } - if (typ && decoded.header.typ !== typ) { + if (typ && normalizeTyp(decoded.header.typ) !== normalizeTyp(typ)) { throw new JWTClaimInvalid('unexpected "typ" JWT header value', 'typ', 'check_failed') } diff --git a/test/jwt/verify.test.js b/test/jwt/verify.test.js index 3d53742f75..4a2a15d648 100644 --- a/test/jwt/verify.test.js +++ b/test/jwt/verify.test.js @@ -199,8 +199,26 @@ test('option.typ validation fails', t => { }) test('option.typ validation success', t => { - const token = JWT.sign({}, key, { header: { typ: 'foo' } }) - JWT.verify(token, key, { typ: 'foo' }) + { + const token = JWT.sign({}, key, { header: { typ: 'foo' } }) + JWT.verify(token, key, { typ: 'foo' }) + } + { + const token = JWT.sign({}, key, { header: { typ: 'application/foo' } }) + JWT.verify(token, key, { typ: 'foo' }) + } + { + const token = JWT.sign({}, key, { header: { typ: 'foo' } }) + JWT.verify(token, key, { typ: 'application/foo' }) + } + { + const token = JWT.sign({}, key, { header: { typ: 'foO' } }) + JWT.verify(token, key, { typ: 'application/foo' }) + } + { + const token = JWT.sign({}, key, { header: { typ: 'application/foo' } }) + JWT.verify(token, key, { typ: 'fOo' }) + } t.pass() })