diff --git a/lib/client.js b/lib/client.js index 6aaaa696..bd909b80 100644 --- a/lib/client.js +++ b/lib/client.js @@ -609,7 +609,7 @@ module.exports = (issuer, aadIssValidation = false) => class Client extends Base * @api private */ async decryptJARM(response) { - if (!this.authorization_encrypted_response_alg && !this.authorization_encrypted_response_enc) { + if (!this.authorization_encrypted_response_alg) { return response; } @@ -648,7 +648,7 @@ module.exports = (issuer, aadIssValidation = false) => class Client extends Base * @name decryptJWE * @api private */ - async decryptJWE(jwe, expectedAlg, expectedEnc) { + async decryptJWE(jwe, expectedAlg, expectedEnc = 'A128CBC-HS256') { const header = JSON.parse(base64url.decode(jwe.split('.')[0])); if (header.alg !== expectedAlg) { @@ -1046,8 +1046,7 @@ module.exports = (issuer, aadIssValidation = false) => class Client extends Base assertIssuerConfiguration(this.issuer, 'userinfo_endpoint'); const jwt = !!(this.userinfo_signed_response_alg - || this.userinfo_encrypted_response_alg - || this.userinfo_encrypted_response_enc); + || this.userinfo_encrypted_response_alg); if (jwt) { options.headers = { Accept: 'application/jwt' }; @@ -1429,7 +1428,7 @@ module.exports = (issuer, aadIssValidation = false) => class Client extends Base sign: this.request_object_signing_alg, encrypt: { alg: this.request_object_encryption_alg, - enc: this.request_object_encryption_enc, + enc: this.request_object_encryption_enc || 'A128CBC-HS256', }, }, { sign: 'none', diff --git a/test/client/client_instance.test.js b/test/client/client_instance.test.js index 06b8892f..1950ab1e 100644 --- a/test/client/client_instance.test.js +++ b/test/client/client_instance.test.js @@ -3096,7 +3096,6 @@ describe('Client', () => { const client = new issuer.Client({ client_id: 'identifier', id_token_encrypted_response_alg: 'RSA-OAEP', - id_token_encrypted_response_enc: 'A128CBC-HS256', }); const header = base64url.encode(JSON.stringify({ @@ -3109,7 +3108,7 @@ describe('Client', () => { }); }); - it('verifies the id token is using the right enc', async () => { + it('verifies the id token is using the right enc (explicit)', async () => { const issuer = new Issuer(); const client = new issuer.Client({ client_id: 'identifier', @@ -3126,6 +3125,23 @@ describe('Client', () => { expect(err).to.have.property('message', 'unexpected JWE enc received, expected A128CBC-HS256, got: A128GCM'); }); }); + + it('verifies the id token is using the right enc (defaulted to)', async () => { + const issuer = new Issuer(); + const client = new issuer.Client({ + client_id: 'identifier', + id_token_encrypted_response_alg: 'RSA-OAEP', + }); + + const header = base64url.encode(JSON.stringify({ + alg: 'RSA-OAEP', + enc: 'A128GCM', + })); + + return client.decryptIdToken(`${header}....`).then(fail, (err) => { + expect(err).to.have.property('message', 'unexpected JWE enc received, expected A128CBC-HS256, got: A128GCM'); + }); + }); }); /* eslint-disable max-len */ @@ -3168,7 +3184,6 @@ describe('Client', () => { client_id: '4e87dde4-ddd3-4c21-aef9-2f2f6bab43ca', client_secret: 'GfsT479VMy5ZZZPquadPbN3wKzaFGYo1CTkb0IFFzDNODLEAuC2GUV3QsTye3xNQ', id_token_encrypted_response_alg: 'ECDH-ES', - id_token_encrypted_response_enc: 'A128CBC-HS256', id_token_signed_response_alg: 'HS256', }, this.keystore.toJWKS(true)); @@ -3202,7 +3217,6 @@ describe('Client', () => { client_id: '4e87dde4-ddd3-4c21-aef9-2f2f6bab43ca', client_secret: 'GfsT479VMy5ZZZPquadPbN3wKzaFGYo1CTkb0IFFzDNODLEAuC2GUV3QsTye3xNQ', id_token_encrypted_response_alg: 'ECDH-ES', - id_token_encrypted_response_enc: 'A128CBC-HS256', id_token_signed_response_alg: 'HS256', }, this.keystore.toJWKS(true)); @@ -3228,7 +3242,6 @@ describe('Client', () => { const client = new issuer.Client({ client_id: 'f21d5d1d-1c3f-4905-8ff1-5f553a2090b1', userinfo_encrypted_response_alg: 'ECDH-ES', - userinfo_encrypted_response_enc: 'A128CBC-HS256', }, this.keystore.toJWKS(true)); return client.userinfo('accesstoken').then((userinfo) => { @@ -3256,7 +3269,6 @@ describe('Client', () => { const client = new issuer.Client({ client_id: 'f21d5d1d-1c3f-4905-8ff1-5f553a2090b1', userinfo_encrypted_response_alg: 'ECDH-ES', - userinfo_encrypted_response_enc: 'A128CBC-HS256', }, this.keystore.toJWKS(true)); return client.userinfo('accesstoken').then(fail, (err) => { @@ -3281,7 +3293,6 @@ describe('Client', () => { const client = new issuer.Client({ client_id: 'f21d5d1d-1c3f-4905-8ff1-5f553a2090b1', userinfo_encrypted_response_alg: 'ECDH-ES', - userinfo_encrypted_response_enc: 'A128CBC-HS256', }, this.keystore.toJWKS(true)); return client.userinfo('accesstoken').then(fail, (err) => { @@ -3298,7 +3309,6 @@ describe('Client', () => { client_id: '0d9413a4-61c1-4b2b-8d84-a82464c1556c', client_secret: 'l73jho9z9mL0GAomiQwbw08ARqro2tJ4E4qhJ+PZhNQoU6G6D23UDF91L9VR7iJ4', id_token_encrypted_response_alg: 'A128GCMKW', - id_token_encrypted_response_enc: 'A128CBC-HS256', id_token_signed_response_alg: 'HS256', }); @@ -3505,7 +3515,7 @@ describe('Client', () => { }); }); - it('encrypts for issuer using issuer\'s public key', function () { + it('encrypts for issuer using issuer\'s public key (explicit enc)', function () { const client = new this.issuer.Client({ client_id: 'identifier', request_object_encryption_alg: 'RSA1_5', request_object_encryption_enc: 'A128CBC-HS256' }); return client.requestObject({ state: 'foobar' }) @@ -3515,6 +3525,16 @@ describe('Client', () => { }); }); + it('encrypts for issuer using issuer\'s public key (default enc)', function () { + const client = new this.issuer.Client({ client_id: 'identifier', request_object_encryption_alg: 'RSA1_5' }); + + return client.requestObject({ state: 'foobar' }) + .then((encrypted) => { + const parts = encrypted.split('.'); + expect(JSON.parse(base64url.decode(parts[0]))).to.contain({ alg: 'RSA1_5', enc: 'A128CBC-HS256', cty: 'JWT' }).and.have.property('kid'); + }); + }); + it('encrypts for issuer using pre-shared client_secret (A\\d{3}GCMKW)', function () { const client = new this.issuer.Client({ client_id: 'identifier', @@ -3544,6 +3564,20 @@ describe('Client', () => { }); }); + it('encrypts for issuer using pre-shared client_secret (dir + defaulted to A128CBC-HS256)', function () { + const client = new this.issuer.Client({ + client_id: 'identifier', + client_secret: 'GfsT479VMy5ZZZPquadPbN3wKzaFGYo1CTkb0IFFzDNODLEAuC2GUV3QsTye3xNQ', + request_object_encryption_alg: 'dir', + }); + + return client.requestObject({ state: 'foobar' }) + .then((encrypted) => { + const parts = encrypted.split('.'); + expect(JSON.parse(base64url.decode(parts[0]))).to.contain({ alg: 'dir', enc: 'A128CBC-HS256', cty: 'JWT' }).and.not.have.property('kid'); + }); + }); + if (!('electron' in process.versions)) { it('encrypts for issuer using pre-shared client_secret (PBES2)', function () { const client = new this.issuer.Client({