Skip to content

Commit

Permalink
Session storage refactoring (#37992)
Browse files Browse the repository at this point in the history
* Kibana request keep a reference to raw request. used to bind hapi-cookie

* CookieSessionStorage should work with KibanaRequest

as soon as registerAuth refactored to restrict access to hapi Request, CookieSessionStorage won't work with hapi request directly

* change registerAuth public api

* adopt auth lifecycle tests

* move lifecycle auth tests from integration to unit and adopt to new api.

* mark toRawRequest as internal to prevent exposure

* generate docs

* reword test cases

* mark Request internals in tsdoc
  • Loading branch information
mshustov authored Jun 7, 2019
1 parent 2165583 commit f753474
Show file tree
Hide file tree
Showing 26 changed files with 379 additions and 251 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@
<b>Signature:</b>

```typescript
export declare type AuthenticationHandler<T> = (request: Readonly<Request>, sessionStorage: SessionStorage<T>, t: AuthToolkit) => AuthResult | Promise<AuthResult>;
export declare type AuthenticationHandler = (request: Readonly<Request>, t: AuthToolkit) => AuthResult | Promise<AuthResult>;
```
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ Authentication is successful with given credentials, allow request to pass throu
<b>Signature:</b>

```typescript
authenticated: (state: object) => AuthResult;
authenticated: (state?: object) => AuthResult;
```
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export interface AuthToolkit

| Property | Type | Description |
| --- | --- | --- |
| [authenticated](./kibana-plugin-server.authtoolkit.authenticated.md) | <code>(state: object) =&gt; AuthResult</code> | Authentication is successful with given credentials, allow request to pass through |
| [authenticated](./kibana-plugin-server.authtoolkit.authenticated.md) | <code>(state?: object) =&gt; AuthResult</code> | Authentication is successful with given credentials, allow request to pass through |
| [redirected](./kibana-plugin-server.authtoolkit.redirected.md) | <code>(url: string) =&gt; AuthResult</code> | Authentication requires to interrupt request handling and redirect to a configured url |
| [rejected](./kibana-plugin-server.authtoolkit.rejected.md) | <code>(error: Error, options?: {</code><br/><code> statusCode?: number;</code><br/><code> }) =&gt; AuthResult</code> | Authentication is unsuccessful, fail the request with specified error. |

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,5 @@ export declare class KibanaRequest<Params = unknown, Query = unknown, Body = unk

| Method | Modifiers | Description |
| --- | --- | --- |
| [from(req, routeSchemas)](./kibana-plugin-server.kibanarequest.from.md) | <code>static</code> | Factory for creating requests. Validates the request before creating an instance of a KibanaRequest. |
| [getFilteredHeaders(headersToKeep)](./kibana-plugin-server.kibanarequest.getfilteredheaders.md) | | |
| [unstable\_getIncomingMessage()](./kibana-plugin-server.kibanarequest.unstable_getincomingmessage.md) | | |

This file was deleted.

2 changes: 2 additions & 0 deletions docs/development/core/server/kibana-plugin-server.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ The plugin integrates with the core system via lifecycle events: `setup`<!-- -->
| [PluginsServiceSetup](./kibana-plugin-server.pluginsservicesetup.md) | |
| [PluginsServiceStart](./kibana-plugin-server.pluginsservicestart.md) | |
| [RouteConfigOptions](./kibana-plugin-server.routeconfigoptions.md) | Route specific configuration. |
| [SessionStorage](./kibana-plugin-server.sessionstorage.md) | Provides an interface to store and retrieve data across requests. |
| [SessionStorageFactory](./kibana-plugin-server.sessionstoragefactory.md) | SessionStorage factory to bind one to an incoming request |

## Type Aliases

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-server](./kibana-plugin-server.md) &gt; [SessionStorage](./kibana-plugin-server.sessionstorage.md) &gt; [clear](./kibana-plugin-server.sessionstorage.clear.md)

## SessionStorage.clear() method

Clears current session.

<b>Signature:</b>

```typescript
clear(): void;
```
<b>Returns:</b>

`void`

Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-server](./kibana-plugin-server.md) &gt; [SessionStorage](./kibana-plugin-server.sessionstorage.md) &gt; [get](./kibana-plugin-server.sessionstorage.get.md)

## SessionStorage.get() method

Retrieves session value from the session storage.

<b>Signature:</b>

```typescript
get(): Promise<T | null>;
```
<b>Returns:</b>

`Promise<T | null>`

Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-server](./kibana-plugin-server.md) &gt; [SessionStorage](./kibana-plugin-server.sessionstorage.md)

## SessionStorage interface

Provides an interface to store and retrieve data across requests.

<b>Signature:</b>

```typescript
export interface SessionStorage<T>
```

## Methods

| Method | Description |
| --- | --- |
| [clear()](./kibana-plugin-server.sessionstorage.clear.md) | Clears current session. |
| [get()](./kibana-plugin-server.sessionstorage.get.md) | Retrieves session value from the session storage. |
| [set(sessionValue)](./kibana-plugin-server.sessionstorage.set.md) | Puts current session value into the session storage. |

Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-server](./kibana-plugin-server.md) &gt; [SessionStorage](./kibana-plugin-server.sessionstorage.md) &gt; [set](./kibana-plugin-server.sessionstorage.set.md)

## SessionStorage.set() method

Puts current session value into the session storage.

<b>Signature:</b>

```typescript
set(sessionValue: T): void;
```

## Parameters

| Parameter | Type | Description |
| --- | --- | --- |
| sessionValue | <code>T</code> | value to put |

<b>Returns:</b>

`void`

Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-server](./kibana-plugin-server.md) &gt; [SessionStorageFactory](./kibana-plugin-server.sessionstoragefactory.md) &gt; [asScoped](./kibana-plugin-server.sessionstoragefactory.asscoped.md)

## SessionStorageFactory.asScoped property

<b>Signature:</b>

```typescript
asScoped: (request: Readonly<Request> | KibanaRequest) => SessionStorage<T>;
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-server](./kibana-plugin-server.md) &gt; [SessionStorageFactory](./kibana-plugin-server.sessionstoragefactory.md)

## SessionStorageFactory interface

SessionStorage factory to bind one to an incoming request

<b>Signature:</b>

```typescript
export interface SessionStorageFactory<T>
```

## Properties

| Property | Type | Description |
| --- | --- | --- |
| [asScoped](./kibana-plugin-server.sessionstoragefactory.asscoped.md) | <code>(request: Readonly&lt;Request&gt; &#124; KibanaRequest) =&gt; SessionStorage&lt;T&gt;</code> | |

12 changes: 6 additions & 6 deletions src/core/server/http/auth_state_storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,25 +17,25 @@
* under the License.
*/
import { Request } from 'hapi';
import { KibanaRequest } from './router';
import { KibanaRequest, toRawRequest } from './router';

export enum AuthStatus {
authenticated = 'authenticated',
unauthenticated = 'unauthenticated',
unknown = 'unknown',
}

const toKey = (request: KibanaRequest | Request) =>
request instanceof KibanaRequest ? request.unstable_getIncomingMessage() : request.raw.req;
const getIncomingMessage = (request: KibanaRequest | Request) =>
request instanceof KibanaRequest ? toRawRequest(request).raw.req : request.raw.req;

export class AuthStateStorage {
private readonly storage = new WeakMap<ReturnType<typeof toKey>, unknown>();
private readonly storage = new WeakMap<ReturnType<typeof getIncomingMessage>, unknown>();
constructor(private readonly canBeAuthenticated: () => boolean) {}
public set = (request: KibanaRequest | Request, state: unknown) => {
this.storage.set(toKey(request), state);
this.storage.set(getIncomingMessage(request), state);
};
public get = (request: KibanaRequest | Request) => {
const key = toKey(request);
const key = getIncomingMessage(request);
const state = this.storage.get(key);
const status: AuthStatus = this.storage.has(key)
? AuthStatus.authenticated
Expand Down
11 changes: 7 additions & 4 deletions src/core/server/http/cookie_session_storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

import { Request, Server } from 'hapi';
import hapiAuthCookie from 'hapi-auth-cookie';

import { KibanaRequest, toRawRequest } from './router';
import { SessionStorageFactory, SessionStorage } from './session_storage';

export interface SessionStorageCookieOptions<T> {
Expand All @@ -29,10 +31,10 @@ export interface SessionStorageCookieOptions<T> {
}

class ScopedCookieSessionStorage<T extends Record<string, any>> implements SessionStorage<T> {
constructor(private readonly server: Server, private readonly request: Request) {}
constructor(private readonly server: Server, private readonly request: Readonly<Request>) {}
public async get(): Promise<T | null> {
try {
return await this.server.auth.test('security-cookie', this.request);
return await this.server.auth.test('security-cookie', this.request as Request);
} catch (error) {
return null;
}
Expand Down Expand Up @@ -71,8 +73,9 @@ export async function createCookieSessionStorageFactory<T>(
});

return {
asScoped(request: Request) {
return new ScopedCookieSessionStorage<T>(server, request);
asScoped(request: Readonly<Request> | KibanaRequest) {
const req = request instanceof KibanaRequest ? toRawRequest(request) : request;
return new ScopedCookieSessionStorage<T>(server, req);
},
};
}
Loading

0 comments on commit f753474

Please sign in to comment.