From ab08cbef610dce76249f7ff893d2b1089a15f07d Mon Sep 17 00:00:00 2001 From: Filip Skokan Date: Wed, 3 Apr 2019 20:45:17 +0200 Subject: [PATCH] fix: session required client properties control the iss & sid return --- lib/actions/end_session.js | 10 ++++---- lib/models/client.js | 5 +++- .../backchannel_logout.config.js | 8 +++++++ .../backchannel_logout.test.js | 24 +++++++++++++++++-- .../frontchannel_logout.config.js | 8 +++++++ .../frontchannel_logout.test.js | 11 ++++++++- 6 files changed, 58 insertions(+), 8 deletions(-) diff --git a/lib/actions/end_session.js b/lib/actions/end_session.js index 09ebbc5e8..74b0c11e0 100644 --- a/lib/actions/end_session.js +++ b/lib/actions/end_session.js @@ -138,10 +138,12 @@ module.exports = { if (client.frontchannelLogoutUri) { const target = url.parse(client.frontchannelLogoutUri, true); target.search = null; - Object.assign(target.query, { - sid, - iss: ctx.oidc.issuer, - }); + if (client.frontchannelLogoutSessionRequired) { + Object.assign(target.query, { + sid, + iss: ctx.oidc.issuer, + }); + } front.push(url.format(target)); } } diff --git a/lib/models/client.js b/lib/models/client.js index 62eee8ead..e75b61864 100644 --- a/lib/models/client.js +++ b/lib/models/client.js @@ -366,7 +366,10 @@ module.exports = function getClient(provider) { 'http://schemas.openid.net/event/backchannel-logout': {}, }); logoutToken.set('jti', nanoid()); - logoutToken.set('sid', sid); + + if (this.backchannelLogoutSessionRequired) { + logoutToken.set('sid', sid); + } return logoutToken.sign({ noExp: true }) .then(token => httpRequest.post(this.backchannelLogoutUri, provider.httpOptions({ diff --git a/test/backchannel_logout/backchannel_logout.config.js b/test/backchannel_logout/backchannel_logout.config.js index bacb2dd63..1c33bce0a 100644 --- a/test/backchannel_logout/backchannel_logout.config.js +++ b/test/backchannel_logout/backchannel_logout.config.js @@ -22,5 +22,13 @@ module.exports = { redirect_uris: ['https://second-client.example.com/cb'], backchannel_logout_uri: 'https://second-client.example.com/backchannel_logout', backchannel_logout_session_required: true, + }, { + client_id: 'no-sid', + client_secret: 'secret', + response_types: ['code id_token'], + grant_types: ['implicit', 'authorization_code', 'refresh_token'], + redirect_uris: ['https://second-client.example.com/cb'], + backchannel_logout_uri: 'https://no-sid.example.com/backchannel_logout', + // backchannel_logout_session_required: false, }], }; diff --git a/test/backchannel_logout/backchannel_logout.test.js b/test/backchannel_logout/backchannel_logout.test.js index 567ef9a8c..c537a5d40 100644 --- a/test/backchannel_logout/backchannel_logout.test.js +++ b/test/backchannel_logout/backchannel_logout.test.js @@ -24,15 +24,35 @@ describe('Back-Channel Logout 1.0', () => { .filteringRequestBody((body) => { expect(body).to.match(/^logout_token=(([\w-]+\.?){3})$/); const decoded = JSON.parse(base64url.decode(RegExp.$1.split('.')[1])); - expect(decoded).to.have.all.keys('sub', 'events', 'iat', 'aud', 'iss', 'jti'); + expect(decoded).to.have.all.keys('sub', 'events', 'iat', 'aud', 'iss', 'jti', 'sid'); expect(decoded).to.have.property('events').and.eql({ 'http://schemas.openid.net/event/backchannel-logout': {} }); expect(decoded).to.have.property('aud', 'client'); expect(decoded).to.have.property('sub', 'subject'); + expect(decoded).to.have.property('sid', 'foo'); + }) + .post('/backchannel_logout') + .reply(204); + + return client.backchannelLogout('subject', 'foo'); + }); + + it('omits sid when its not required', async function () { + const client = await this.provider.Client.find('no-sid'); + + nock('https://no-sid.example.com/') + .filteringRequestBody((body) => { + expect(body).to.match(/^logout_token=(([\w-]+\.?){3})$/); + const decoded = JSON.parse(base64url.decode(RegExp.$1.split('.')[1])); + expect(decoded).to.have.all.keys('sub', 'events', 'iat', 'aud', 'iss', 'jti'); + expect(decoded).to.have.property('events').and.eql({ 'http://schemas.openid.net/event/backchannel-logout': {} }); + expect(decoded).to.have.property('aud', 'no-sid'); + expect(decoded).to.have.property('sub', 'subject'); + expect(decoded).not.to.have.property('sid'); }) .post('/backchannel_logout') .reply(204); - return client.backchannelLogout('subject'); + return client.backchannelLogout('subject', 'foo'); }); }); diff --git a/test/frontchannel_logout/frontchannel_logout.config.js b/test/frontchannel_logout/frontchannel_logout.config.js index da4d4928f..8b3c78c99 100644 --- a/test/frontchannel_logout/frontchannel_logout.config.js +++ b/test/frontchannel_logout/frontchannel_logout.config.js @@ -24,5 +24,13 @@ module.exports = { redirect_uris: ['https://second-client.example.com/cb'], frontchannel_logout_uri: 'https://second-client.example.com/frontchannel_logout', frontchannel_logout_session_required: true, + }, { + client_id: 'no-nothing', + client_secret: 'secret', + response_types: ['code id_token'], + grant_types: ['implicit', 'authorization_code', 'refresh_token'], + redirect_uris: ['https://no-nothing.example.com/cb'], + frontchannel_logout_uri: 'https://no-nothing.example.com/frontchannel_logout', + // frontchannel_logout_session_required: false, }], }; diff --git a/test/frontchannel_logout/frontchannel_logout.test.js b/test/frontchannel_logout/frontchannel_logout.test.js index d5a0978ab..fad4cdbac 100644 --- a/test/frontchannel_logout/frontchannel_logout.test.js +++ b/test/frontchannel_logout/frontchannel_logout.test.js @@ -101,6 +101,7 @@ describe('Front-Channel Logout 1.0', () => { const client = await this.provider.Client.find('client'); const client2 = await this.provider.Client.find('second-client'); + const client3 = await this.provider.Client.find('no-nothing'); const FRAME = /