Skip to content

Commit

Permalink
Fix basePath (tenant) issue
Browse files Browse the repository at this point in the history
  • Loading branch information
jportner committed Nov 25, 2019
1 parent 8b6d1fd commit 2649e5a
Show file tree
Hide file tree
Showing 7 changed files with 24 additions and 21 deletions.
1 change: 1 addition & 0 deletions x-pack/legacy/plugins/security/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ export const security = (kibana) => new kibana.Plugin({
return {
secureCookies: securityPlugin.__legacyCompat.config.secureCookies,
session: {
tenant: server.newPlatform.setup.core.http.basePath.serverBasePath,
idleTimeout: securityPlugin.__legacyCompat.config.session.idleTimeout,
lifespan: securityPlugin.__legacyCompat.config.session.lifespan,
},
Expand Down
7 changes: 4 additions & 3 deletions x-pack/plugins/security/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,16 @@ export class SecurityPlugin implements Plugin<SecurityPluginSetup, SecurityPlugi
private sessionTimeout!: SessionTimeout;

public setup(core: CoreSetup) {
const { http, notifications } = core;
const { http, notifications, injectedMetadata } = core;
const { basePath, anonymousPaths } = http;
anonymousPaths.register('/login');
anonymousPaths.register('/logout');
anonymousPaths.register('/logged_out');

const sessionExpired = new SessionExpired(basePath);
const tenant = `${injectedMetadata.getInjectedVar('session.tenant', '')}`;
const sessionExpired = new SessionExpired(basePath, tenant);
http.intercept(new UnauthorizedResponseHttpInterceptor(sessionExpired, anonymousPaths));
this.sessionTimeout = new SessionTimeout(notifications, sessionExpired, http);
this.sessionTimeout = new SessionTimeout(notifications, sessionExpired, http, tenant);
http.intercept(new SessionTimeoutHttpInterceptor(this.sessionTimeout, anonymousPaths));

return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,12 @@ describe('Session Expiration', () => {

describe('logout', () => {
const mockCurrentUrl = (url: string) => window.history.pushState({}, '', url);
const tenant = '';

it('redirects user to "/logout" when there is no basePath', async () => {
const { basePath } = coreMock.createSetup().http;
mockCurrentUrl('/foo/bar?baz=quz#quuz');
const sessionExpired = new SessionExpired(basePath);
const sessionExpired = new SessionExpired(basePath, tenant);
const newUrlPromise = new Promise<string>(resolve => {
jest.spyOn(window.location, 'assign').mockImplementation(url => {
resolve(url);
Expand All @@ -47,7 +48,7 @@ describe('Session Expiration', () => {
it('adds a provider parameter when an auth provider is saved in sessionStorage', async () => {
const { basePath } = coreMock.createSetup().http;
mockCurrentUrl('/foo/bar?baz=quz#quuz');
const sessionExpired = new SessionExpired(basePath);
const sessionExpired = new SessionExpired(basePath, tenant);
const newUrlPromise = new Promise<string>(resolve => {
jest.spyOn(window.location, 'assign').mockImplementation(url => {
resolve(url);
Expand All @@ -68,7 +69,7 @@ describe('Session Expiration', () => {
it('redirects user to "/${basePath}/logout" and removes basePath from next parameter when there is a basePath', async () => {
const { basePath } = coreMock.createSetup({ basePath: '/foo' }).http;
mockCurrentUrl('/foo/bar?baz=quz#quuz');
const sessionExpired = new SessionExpired(basePath);
const sessionExpired = new SessionExpired(basePath, tenant);
const newUrlPromise = new Promise<string>(resolve => {
jest.spyOn(window.location, 'assign').mockImplementation(url => {
resolve(url);
Expand Down
4 changes: 2 additions & 2 deletions x-pack/plugins/security/public/session/session_expired.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ export interface ISessionExpired {
}

export class SessionExpired {
constructor(private basePath: HttpSetup['basePath']) {}
constructor(private basePath: HttpSetup['basePath'], private tenant: string) {}

logout() {
const next = this.basePath.remove(
`${window.location.pathname}${window.location.search}${window.location.hash}`
);
const key = this.basePath.prepend('/session_provider');
const key = `${this.tenant}/session_provider`;
const providerName = sessionStorage.getItem(key);
const provider = providerName ? `&provider=${encodeURIComponent(providerName)}` : '';
window.location.assign(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,8 @@ describe('Session Timeout', () => {
http = setup.http;
notifications.toasts.add.mockReturnValue(toast as any);
sessionExpired = createSessionExpiredMock();
sessionTimeout = new SessionTimeout(notifications, sessionExpired, http);
const tenant = '';
sessionTimeout = new SessionTimeout(notifications, sessionExpired, http, tenant);

// default mocked response for checking session info
http.fetch.mockResolvedValue(defaultSessionInfo);
Expand Down
14 changes: 6 additions & 8 deletions x-pack/plugins/security/public/session/session_timeout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { NotificationsSetup, Toast, HttpSetup, ToastInput, IBasePath } from 'src/core/public';
import { NotificationsSetup, Toast, HttpSetup, ToastInput } from 'src/core/public';
import { BroadcastChannel } from 'broadcast-channel';
import { createToast as createIdleTimeoutToast } from './session_idle_timeout_warning';
import { createToast as createLifespanToast } from './session_lifespan_warning';
Expand Down Expand Up @@ -42,7 +42,6 @@ export interface ISessionTimeout {
}

export class SessionTimeout {
private basePath: IBasePath;
private channel?: BroadcastChannel<SessionInfo>;
private sessionInfo?: SessionInfo;
private fetchTimer?: number;
Expand All @@ -53,10 +52,9 @@ export class SessionTimeout {
constructor(
private notifications: NotificationsSetup,
private sessionExpired: ISessionExpired,
private http: HttpSetup
) {
this.basePath = http.basePath;
}
private http: HttpSetup,
private tenant: string
) {}

start() {
if (this.http.anonymousPaths.isAnonymous(window.location.pathname)) {
Expand All @@ -65,7 +63,7 @@ export class SessionTimeout {

// subscribe to a broadcast channel for session timeout messages
// this allows us to synchronize the UX across tabs and avoid repetitive API calls
const name = this.basePath.prepend('/session_timeout');
const name = `${this.tenant}/session_timeout`;
this.channel = new BroadcastChannel(name, { webWorkerSupport: false });
this.channel.onmessage = this.handleSessionInfoAndResetTimers;

Expand Down Expand Up @@ -129,7 +127,7 @@ export class SessionTimeout {
private handleSessionInfoAndResetTimers = (sessionInfo: SessionInfo) => {
this.sessionInfo = sessionInfo;
// save the provider name in session storage, we will need it when we log out
const key = this.basePath.prepend('/session_provider');
const key = `${this.tenant}/session_provider`;
sessionStorage.setItem(key, sessionInfo.provider);

const { timeout, isLifespanTimeout } = this.getTimeout();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,15 @@ const setupHttp = (basePath: string) => {
});
return http;
};
const tenant = '';

afterEach(() => {
fetchMock.restore();
});

it(`logs out 401 responses`, async () => {
const http = setupHttp('/foo');
const sessionExpired = new SessionExpired(http.basePath);
const sessionExpired = new SessionExpired(http.basePath, tenant);
const logoutPromise = new Promise(resolve => {
jest.spyOn(sessionExpired, 'logout').mockImplementation(() => resolve());
});
Expand All @@ -58,7 +59,7 @@ it(`ignores anonymous paths`, async () => {
const http = setupHttp('/foo');
const { anonymousPaths } = http;
anonymousPaths.register('/bar');
const sessionExpired = new SessionExpired(http.basePath);
const sessionExpired = new SessionExpired(http.basePath, tenant);
const interceptor = new UnauthorizedResponseHttpInterceptor(sessionExpired, anonymousPaths);
http.intercept(interceptor);
fetchMock.mock('*', 401);
Expand All @@ -69,7 +70,7 @@ it(`ignores anonymous paths`, async () => {

it(`ignores errors which don't have a response, for example network connectivity issues`, async () => {
const http = setupHttp('/foo');
const sessionExpired = new SessionExpired(http.basePath);
const sessionExpired = new SessionExpired(http.basePath, tenant);
const interceptor = new UnauthorizedResponseHttpInterceptor(sessionExpired, http.anonymousPaths);
http.intercept(interceptor);
fetchMock.mock('*', new Promise((resolve, reject) => reject(new Error('Network is down'))));
Expand All @@ -80,7 +81,7 @@ it(`ignores errors which don't have a response, for example network connectivity

it(`ignores requests which omit credentials`, async () => {
const http = setupHttp('/foo');
const sessionExpired = new SessionExpired(http.basePath);
const sessionExpired = new SessionExpired(http.basePath, tenant);
const interceptor = new UnauthorizedResponseHttpInterceptor(sessionExpired, http.anonymousPaths);
http.intercept(interceptor);
fetchMock.mock('*', 401);
Expand Down

0 comments on commit 2649e5a

Please sign in to comment.