From 1da97392876b0675904d9a24217b7c574bd8b37b Mon Sep 17 00:00:00 2001 From: Derek Ho Date: Mon, 12 Feb 2024 19:19:02 -0500 Subject: [PATCH] Add keep alive test Signed-off-by: Derek Ho --- server/auth/types/authentication_type.test.ts | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/server/auth/types/authentication_type.test.ts b/server/auth/types/authentication_type.test.ts index d3f6026bb..53b65dac6 100644 --- a/server/auth/types/authentication_type.test.ts +++ b/server/auth/types/authentication_type.test.ts @@ -16,8 +16,20 @@ import { SecurityPluginConfigType } from '../..'; import { AuthenticationType } from './authentication_type'; import { httpServerMock } from '../../../../../src/core/server/mocks'; +import { + SessionStorageFactory, + SessionStorage, + OpenSearchDashboardsRequest, +} from '../../../../../src/core/server'; +import { SecuritySessionCookie } from '../../session/security_cookie'; + +const mockedNow = 0; +Date.now = jest.fn(() => mockedNow); class DummyAuthType extends AuthenticationType { + authNotRequired(request: OpenSearchDashboardsRequest): boolean { + return false; + } buildAuthHeaderFromCookie() {} getAdditionalAuthHeader() {} handleUnauthedRequest() {} @@ -35,6 +47,43 @@ class DummyAuthType extends AuthenticationType { } } +// Implementation of SessionStorage using browser's sessionStorage +class BrowserSessionStorage implements SessionStorage { + private readonly storageKey: string; + + constructor(storageKey: string) { + this.storageKey = storageKey; + } + + async get(): Promise { + const storedValue = sessionStorage.getItem(this.storageKey); + return storedValue ? JSON.parse(storedValue) : null; + } + + set(sessionValue: T): void { + const serializedValue = JSON.stringify(sessionValue); + sessionStorage.setItem(this.storageKey, serializedValue); + } + + clear(): void { + sessionStorage.removeItem(this.storageKey); + } +} + +// Implementation of SessionStorageFactory using the browser's sessionStorage +class BrowserSessionStorageFactory implements SessionStorageFactory { + private readonly storageKey: string; + + constructor(storageKey: string) { + this.storageKey = storageKey; + } + + // This method returns a new instance of the browser's SessionStorage for each request + asScoped(request: OpenSearchDashboardsRequest): SessionStorage { + return new BrowserSessionStorage(this.storageKey); + } +} + describe('test tenant header', () => { const config = { multitenancy: { @@ -106,4 +155,45 @@ describe('test tenant header', () => { const result = await dummyAuthType.authHandler(request, response, toolkit); expect(result.requestHeaders.securitytenant).toEqual('dummy_tenant'); }); + + it(`keepalive should not shorten the cookie expiry`, async () => { + const keepAliveConfig = { + multitenancy: { + enabled: true, + }, + auth: { + unauthenticated_routes: [] as string[], + }, + session: { + keepalive: true, + ttl: 1000, + }, + } as SecurityPluginConfigType; + const keepAliveDummyAuth = new DummyAuthType( + keepAliveConfig, + new BrowserSessionStorageFactory('security_cookie'), + router, + esClient, + coreSetup, + logger + ); + const testCookie: SecuritySessionCookie = { + credentials: { + authHeaderValueExtra: true, + }, + expiryTime: 2000, + }; + // Set cookie + sessionStorage.setItem('security_cookie', JSON.stringify(testCookie)); + const request = httpServerMock.createOpenSearchDashboardsRequest({ + path: '/internal/v1', + }); + const response = jest.fn(); + const toolkit = { + authenticated: jest.fn((value) => value), + }; + const _ = await keepAliveDummyAuth.authHandler(request, response, toolkit); + const cookieAfterRequest = sessionStorage.getItem('security_cookie'); + expect(JSON.parse(cookieAfterRequest!).expiryTime).toBe(2000); + }); });