diff --git a/docs/README.md b/docs/README.md index c00321d62f..9df856e3c3 100644 --- a/docs/README.md +++ b/docs/README.md @@ -775,7 +775,7 @@ that will be used to sign with is either provided as part of the 'options.algori the payload - `jti`: `` JWT ID, "jti" claim value, if provided it will replace "jti" found in the payload - - `kid`: `` When true it pushes the key's "kid" to the JWT Header. **Default:** 'true' + - `kid`: `` When true it pushes the key's "kid" to the JWT Header. **Default:** 'true' for asymmetric keys, 'false' for symmetric keys. - `nonce`: `` ID Token Nonce, "nonce" claim value, if provided it will replace "nonce" found in the payload. See [OpenID Connect Core 1.0][connect-core] for details. - `notBefore`: `` JWT Not Before, "nbf" claim value, specified as string which is added to diff --git a/lib/jwt/sign.js b/lib/jwt/sign.js index 9e9f312ec0..bb44f63587 100644 --- a/lib/jwt/sign.js +++ b/lib/jwt/sign.js @@ -77,9 +77,19 @@ module.exports = (payload, key, options = {}) => { key = getKey(key) + let includeKid + + if (typeof options.kid === 'boolean') { + includeKid = kid + } else if (key.secret) { + includeKid = false + } else { + includeKid = true + } + return JWS.sign(payload, key, { ...header, alg: algorithm || header.alg, - kid: kid ? key.kid : header.kid + kid: includeKid ? key.kid : header.kid }) } diff --git a/test/jwt/sign.test.js b/test/jwt/sign.test.js index 5128354ea5..202d85a7d5 100644 --- a/test/jwt/sign.test.js +++ b/test/jwt/sign.test.js @@ -80,14 +80,35 @@ test('payload is used', t => { test('options.header is used', t => { const { header: { alg, kid, ...header } } = JWT.decode(JWT.sign({}, key, { header: { typ: 'JWT' } }), { complete: true }) - t.is(kid, key.kid) t.is(alg, 'HS256') t.deepEqual(header, { typ: 'JWT' }) }) -test('options.kid', t => { - const { header: { kid } } = JWT.decode(JWT.sign({}, key, { kid: false }), { complete: true }) +test('options.kid for symmetric keys', t => { + let kid + + ;({ header: { kid } } = JWT.decode(JWT.sign({}, key), { complete: true })) + t.is(kid, undefined) + + ;({ header: { kid } } = JWT.decode(JWT.sign({}, key, { kid: false }), { complete: true })) + t.is(kid, undefined) + + ;({ header: { kid } } = JWT.decode(JWT.sign({}, key, { kid: true }), { complete: true })) + t.is(kid, key.kid) +}) + +test('options.kid for asymmetric keys', t => { + const key = JWK.generateSync('EC') + let kid + + ;({ header: { kid } } = JWT.decode(JWT.sign({}, key), { complete: true })) + t.is(kid, key.kid) + + ;({ header: { kid } } = JWT.decode(JWT.sign({}, key, { kid: false }), { complete: true })) t.is(kid, undefined) + + ;({ header: { kid } } = JWT.decode(JWT.sign({}, key, { kid: true }), { complete: true })) + t.is(kid, key.kid) }) test('options.subject', t => {