diff --git a/src/handlers/auth-callback-request.js b/src/handlers/auth-callback-request.js index 8c64d07..0f7b501 100644 --- a/src/handlers/auth-callback-request.js +++ b/src/handlers/auth-callback-request.js @@ -55,7 +55,6 @@ class AuthCallbackRequest { } let requestUri = AuthCallbackRequest.fullUriFor(req) - let issuer = AuthCallbackRequest.extractIssuer(req) let options = { @@ -63,9 +62,9 @@ class AuthCallbackRequest { requestUri, oidcManager, serverUri, + returnToUrl: req.session.returnToUrl, response: res, - session: req.session, - returnToUrl: req.session.returnToUrl + session: req.session } let request = new AuthCallbackRequest(options) @@ -158,6 +157,7 @@ class AuthCallbackRequest { this.debug(' Resuming workflow, redirecting to ' + this.returnToUrl) delete this.session.returnToUrl + return this.response.redirect(302, this.returnToUrl) } } diff --git a/src/handlers/select-provider-request.js b/src/handlers/select-provider-request.js index 2b4e0b7..3f81c8a 100644 --- a/src/handlers/select-provider-request.js +++ b/src/handlers/select-provider-request.js @@ -12,6 +12,8 @@ class SelectProviderRequest { * @param [options.oidcManager] {OidcManager} * @param [options.response] {HttpResponse} * @param [options.serverUri] {string} + * @param [options.returnToUrl] {string} Url of the original resource + * a client was trying to access before being redirected to select provider */ constructor (options) { this.webId = options.webId @@ -19,6 +21,7 @@ class SelectProviderRequest { this.response = options.response this.session = options.session this.serverUri = options.serverUri + this.returnToUrl = options.returnToUrl } /** @@ -58,8 +61,9 @@ class SelectProviderRequest { * @return {SelectProviderRequest} */ static fromParams (req, res) { - let body = req.body || {} - let webId = SelectProviderRequest.normalizeUri(body.webid) + const body = req.body || {} + const query = req.query || {} + const webId = SelectProviderRequest.normalizeUri(body.webid) let oidcManager, serverUri if (req.app && req.app.locals) { @@ -72,6 +76,7 @@ class SelectProviderRequest { webId, oidcManager, serverUri, + returnToUrl: query.returnToUrl, response: res, session: req.session } @@ -124,6 +129,7 @@ class SelectProviderRequest { static handlePost (request) { return Promise.resolve() .then(() => request.validate()) + .then(() => request.saveReturnToUrl()) .then(() => request.selectProvider()) .catch(err => request.error(err)) } @@ -163,6 +169,15 @@ class SelectProviderRequest { .then(providerAuthUrl => this.response.redirect(providerAuthUrl)) } + /** + * Saves `returnToUrl` param for later use in AuthCallbackRequest handler, + * to redirect the client to the original resource they were trying to access + * before entering the authn workflow. + */ + saveReturnToUrl () { + this.session.returnToUrl = this.returnToUrl + } + /** * @throws {Error} * diff --git a/test/unit/auth-callback-request.js b/test/unit/auth-callback-request.js index 1859763..399960b 100644 --- a/test/unit/auth-callback-request.js +++ b/test/unit/auth-callback-request.js @@ -77,7 +77,8 @@ describe('AuthCallbackRequest', () => { let oidcManager = {} let host = { serverUri: 'https://example.com' } - let session = { returnToUrl: 'https://example.com/resource' } + let returnToUrl = 'https://example.com/resource#hash' + let session = { returnToUrl } let req = { session, @@ -96,7 +97,7 @@ describe('AuthCallbackRequest', () => { expect(request.oidcManager).to.equal(oidcManager) expect(request.response).to.equal(res) expect(request.session).to.equal(session) - expect(request.returnToUrl).to.equal(session.returnToUrl) + expect(request.returnToUrl).to.equal(returnToUrl) }) }) diff --git a/test/unit/select-provider-request.js b/test/unit/select-provider-request.js index f273151..6206c01 100644 --- a/test/unit/select-provider-request.js +++ b/test/unit/select-provider-request.js @@ -79,6 +79,9 @@ describe('SelectProviderRequest', () => { let res = HttpMocks.createResponse() let serverUri = 'https://example.com' + // 'https%3A%2F%2Foriginal.com%2Fpath%23hash' + const returnToUrl = encodeURIComponent('https://original.com/path#hash') + it('should initialize a SelectProviderRequest instance', () => { let aliceWebId = 'https://alice.example.com' let oidcManager = {} @@ -86,6 +89,7 @@ describe('SelectProviderRequest', () => { let req = { session, body: { webid: aliceWebId }, + query: { returnToUrl }, app: { locals: { oidc: oidcManager, host: { serverUri } } } } @@ -95,6 +99,7 @@ describe('SelectProviderRequest', () => { expect(request.oidcManager).to.equal(oidcManager) expect(request.session).to.equal(session) expect(request.serverUri).to.equal(serverUri) + expect(request.returnToUrl).to.equal(returnToUrl) }) it('should attempt to normalize an invalid webid uri', () => { @@ -126,6 +131,19 @@ describe('SelectProviderRequest', () => { }) }) + describe('saveReturnToUrl()', () => { + it('should save the returnToUrl in session', () => { + let response = HttpMocks.createResponse() + let session = {} + let returnToUrl = encodeURIComponent('https://example.com/path#hash') + let request = new SelectProviderRequest({ response, session, returnToUrl }) + + request.saveReturnToUrl() + + expect(request.session.returnToUrl).to.equal(returnToUrl) + }) + }) + describe('selectProvider()', () => { it('should fetch the provider uri and redirect user to its /authorize endpoint', () => { let webId = 'https://example.com/#me' @@ -178,11 +196,13 @@ describe('SelectProviderRequest', () => { request.validate = sinon.stub().resolves() request.selectProvider = sinon.stub().resolves() + request.saveReturnToUrl = sinon.stub() return SelectProviderRequest.handlePost(request) .then(() => { expect(request.validate).to.have.been.called() expect(request.selectProvider).to.have.been.called() + expect(request.saveReturnToUrl).to.have.been.called() }) })