From aeab4a9eb0c11b987d9d20e217726688fbc3fd9b Mon Sep 17 00:00:00 2001 From: Steve Hetzel Date: Mon, 8 Jan 2024 14:37:05 -0700 Subject: [PATCH] fix: ignore requests for site icons --- src/webOAuthServer.ts | 5 +++ test/unit/webOauthServerTest.ts | 67 +++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) diff --git a/src/webOAuthServer.ts b/src/webOAuthServer.ts index f8ee59fad4..7695bb82ac 100644 --- a/src/webOAuthServer.ts +++ b/src/webOAuthServer.ts @@ -25,6 +25,9 @@ import { JwtOAuth2Config } from './org/authInfo'; Messages.importMessagesDirectory(__dirname); const messages = Messages.loadMessages('@salesforce/core', 'auth'); +// Server ignores requests for site icons +const iconPaths = ['/favicon.ico', '/apple-touch-icon-precomposed.png']; + /** * Handles the creation of a web server for web based login flows. * @@ -186,6 +189,8 @@ export class WebOAuthServer extends AsyncCreatable { this.webServer.reportSuccess(response); } else if (url.pathname === '/OauthError') { this.webServer.reportError(this.oauthError, response); + } else if (iconPaths.includes(url.pathname ?? '')) { + this.logger.debug(`Ignoring request for icon path: ${url.pathname}`); } else { this.webServer.sendError(404, 'Resource not found', response); const errName = 'invalidRequestUri'; diff --git a/test/unit/webOauthServerTest.ts b/test/unit/webOauthServerTest.ts index 4f2749e996..720c40942a 100644 --- a/test/unit/webOauthServerTest.ts +++ b/test/unit/webOauthServerTest.ts @@ -192,6 +192,73 @@ describe('WebOauthServer', () => { expect(reportErrorSpy.callCount).to.equal(1); expect(reportErrorSpy.args[0][0]).to.equal(authError); }); + + it('should ignore requests for favicon and continue', async () => { + const oauthServer = await WebOAuthServer.create({ oauthConfig: {} }); + const validateStateStub = stubMethod($$.SANDBOX, oauthServer, 'validateState').returns(true); + await oauthServer.start(); + + // @ts-expect-error because private member + const webServer = oauthServer.webServer; + const reportSuccessSpy = spyMethod($$.SANDBOX, webServer, 'reportSuccess'); + + const origOn = webServer.server.on; + let requestListener: http.RequestListener; + stubMethod($$.SANDBOX, webServer.server, 'on').callsFake((event, callback) => { + // eslint-disable-next-line @typescript-eslint/no-unsafe-return,@typescript-eslint/no-unsafe-argument + if (event !== 'request') return origOn.call(webServer.server, event, callback); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + requestListener = callback; + // eslint-disable-next-line @typescript-eslint/no-unsafe-call + callback( + { + method: 'GET', + url: 'http://localhost:1717/favicon.ico', + }, + { + setHeader: () => {}, + writeHead: () => {}, + end: () => {}, + } + ); + // eslint-disable-next-line @typescript-eslint/no-unsafe-call + callback( + { + method: 'GET', + url: `http://localhost:1717/OauthRedirect?code=${authCode}&state=972475373f51`, + query: { code: authCode }, + }, + { + setHeader: () => {}, + writeHead: () => {}, + end: () => {}, + } + ); + }); + + // stub the redirect to ensure proper redirect handling and the web server is closed. + redirectStub = stubMethod($$.SANDBOX, webServer, 'doRedirect').callsFake(async (status, url, response) => { + expect(status).to.equal(303); + expect(url).to.equal('/OauthSuccess'); + expect(response).to.be.ok; + // eslint-disable-next-line @typescript-eslint/await-thenable + await requestListener( + // @ts-expect-error + { method: 'GET', url: `http://localhost:1717${url}` }, + { + setHeader: () => {}, + writeHead: () => {}, + end: () => {}, + } + ); + }); + + const authInfo = await oauthServer.authorizeAndSave(); + expect(authInfo.getFields()).to.deep.equal(authFields); + expect(redirectStub.callCount).to.equal(1); + expect(validateStateStub.callCount).to.equal(1); + expect(reportSuccessSpy.callCount).to.equal(1); + }); }); it('should error if postback has error', async () => {