Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

introduce pre-/post-auth request hooks for HttpServer #36690

Merged
merged 21 commits into from
May 29, 2019
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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: Request, sessionStorage: SessionStorage<T>, t: AuthToolkit) => Promise<AuthResult>;
export declare type AuthenticationHandler<T> = (request: Readonly<Request>, sessionStorage: SessionStorage<T>, 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: (credentials: any) => 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>(credentials: any) =&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?: {`<p/>` statusCode?: number;`<p/>` }) =&gt; AuthResult</code> | Authentication is unsuccessful, fail the request with specified error. |

Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@

```typescript
http: {
registerOnPreAuth: HttpServiceSetup['registerOnPreAuth'];
registerAuth: HttpServiceSetup['registerAuth'];
registerOnRequest: HttpServiceSetup['registerOnRequest'];
registerOnPostAuth: HttpServiceSetup['registerOnPostAuth'];
Copy link
Contributor Author

@mshustov mshustov May 27, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@eliperelman what do you think if we allocate basePath functionality under basePath namespace in httpSetup? If you agree on this interface, I can implement for server side as a part of #35816

basePath: {
  get (key) {}
  set (key, value) {}
  prepend(url) {}
  remove (url) {}
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this makes sense. I like it.

getBasePathFor: HttpServiceSetup['getBasePathFor'];
setBasePathFor: HttpServiceSetup['setBasePathFor'];
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,5 @@ export interface CoreSetup
| Property | Type | Description |
| --- | --- | --- |
| [elasticsearch](./kibana-plugin-server.coresetup.elasticsearch.md) | <code>{`<p/>` adminClient$: Observable&lt;ClusterClient&gt;;`<p/>` dataClient$: Observable&lt;ClusterClient&gt;;`<p/>` }</code> | |
| [http](./kibana-plugin-server.coresetup.http.md) | <code>{`<p/>` registerAuth: HttpServiceSetup['registerAuth'];`<p/>` registerOnRequest: HttpServiceSetup['registerOnRequest'];`<p/>` getBasePathFor: HttpServiceSetup['getBasePathFor'];`<p/>` setBasePathFor: HttpServiceSetup['setBasePathFor'];`<p/>` }</code> | |
| [http](./kibana-plugin-server.coresetup.http.md) | <code>{`<p/>` registerOnPreAuth: HttpServiceSetup['registerOnPreAuth'];`<p/>` registerAuth: HttpServiceSetup['registerAuth'];`<p/>` registerOnPostAuth: HttpServiceSetup['registerOnPostAuth'];`<p/>` getBasePathFor: HttpServiceSetup['getBasePathFor'];`<p/>` setBasePathFor: HttpServiceSetup['setBasePathFor'];`<p/>` }</code> | |

Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export declare class KibanaRequest<Params = unknown, Query = unknown, Body = unk
| [params](./kibana-plugin-server.kibanarequest.params.md) | | <code>Params</code> | |
| [path](./kibana-plugin-server.kibanarequest.path.md) | | <code>string</code> | |
| [query](./kibana-plugin-server.kibanarequest.query.md) | | <code>Query</code> | |
| [url](./kibana-plugin-server.kibanarequest.url.md) | | <code>Url</code> | |

## Methods

Expand Down
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) &gt; [kibana-plugin-server](./kibana-plugin-server.md) &gt; [KibanaRequest](./kibana-plugin-server.kibanarequest.md) &gt; [url](./kibana-plugin-server.kibanarequest.url.md)

## KibanaRequest.url property

<b>Signature:</b>

```typescript
readonly url: Url;
```
6 changes: 4 additions & 2 deletions docs/development/core/server/kibana-plugin-server.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ The plugin integrates with the core system via lifecycle events: `setup`<!-- -->
| [Logger](./kibana-plugin-server.logger.md) | Logger exposes all the necessary methods to log any type of information and this is the interface used by the logging consumers including plugins. |
| [LoggerFactory](./kibana-plugin-server.loggerfactory.md) | The single purpose of <code>LoggerFactory</code> interface is to define a way to retrieve a context-based logger instance. |
| [LogMeta](./kibana-plugin-server.logmeta.md) | Contextual metadata |
| [OnRequestToolkit](./kibana-plugin-server.onrequesttoolkit.md) | A tool set defining an outcome of OnRequest interceptor for incoming request. |
| [OnPostAuthToolkit](./kibana-plugin-server.onpostauthtoolkit.md) | A tool set defining an outcome of OnPostAuth interceptor for incoming request. |
| [OnPreAuthToolkit](./kibana-plugin-server.onpreauthtoolkit.md) | A tool set defining an outcome of OnPreAuth interceptor for incoming request. |
| [Plugin](./kibana-plugin-server.plugin.md) | The interface that should be returned by a <code>PluginInitializer</code>. |
| [PluginInitializerContext](./kibana-plugin-server.plugininitializercontext.md) | Context that's available to plugins during initialization stage. |
| [PluginsServiceSetup](./kibana-plugin-server.pluginsservicesetup.md) | |
Expand All @@ -49,7 +50,8 @@ The plugin integrates with the core system via lifecycle events: `setup`<!-- -->
| [ElasticsearchClientConfig](./kibana-plugin-server.elasticsearchclientconfig.md) | |
| [Headers](./kibana-plugin-server.headers.md) | |
| [HttpServiceSetup](./kibana-plugin-server.httpservicesetup.md) | |
| [OnRequestHandler](./kibana-plugin-server.onrequesthandler.md) | |
| [OnPostAuthHandler](./kibana-plugin-server.onpostauthhandler.md) | |
| [OnPreAuthHandler](./kibana-plugin-server.onpreauthhandler.md) | |
| [PluginInitializer](./kibana-plugin-server.plugininitializer.md) | The <code>plugin</code> export at the root of a plugin's <code>server</code> directory should conform to this interface. |
| [PluginName](./kibana-plugin-server.pluginname.md) | Dedicated type for plugin name/id that is supposed to make Map/Set/Arrays that use it as a key or value more obvious. |

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

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

## OnPostAuthHandler type


<b>Signature:</b>

```typescript
export declare type OnPostAuthHandler<Params = any, Query = any, Body = any> = (request: KibanaRequest<Params, Query, Body>, t: OnPostAuthToolkit) => OnPostAuthResult | Promise<OnPostAuthResult>;
```
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) &gt; [kibana-plugin-server](./kibana-plugin-server.md) &gt; [OnPostAuthToolkit](./kibana-plugin-server.onpostauthtoolkit.md)

## OnPostAuthToolkit interface

A tool set defining an outcome of OnPostAuth interceptor for incoming request.

<b>Signature:</b>

```typescript
export interface OnPostAuthToolkit
```

## Properties

| Property | Type | Description |
| --- | --- | --- |
| [next](./kibana-plugin-server.onpostauthtoolkit.next.md) | <code>() =&gt; OnPostAuthResult</code> | To pass request to the next handler |
| [redirected](./kibana-plugin-server.onpostauthtoolkit.redirected.md) | <code>(url: string) =&gt; OnPostAuthResult</code> | To interrupt request handling and redirect to a configured url |
| [rejected](./kibana-plugin-server.onpostauthtoolkit.rejected.md) | <code>(error: Error, options?: {`<p/>` statusCode?: number;`<p/>` }) =&gt; OnPostAuthResult</code> | Fail the request with specified error. |

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

[Home](./index) &gt; [kibana-plugin-server](./kibana-plugin-server.md) &gt; [OnPostAuthToolkit](./kibana-plugin-server.onpostauthtoolkit.md) &gt; [next](./kibana-plugin-server.onpostauthtoolkit.next.md)

## OnPostAuthToolkit.next property

To pass request to the next handler

<b>Signature:</b>

```typescript
next: () => OnPostAuthResult;
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index) &gt; [kibana-plugin-server](./kibana-plugin-server.md) &gt; [OnPostAuthToolkit](./kibana-plugin-server.onpostauthtoolkit.md) &gt; [redirected](./kibana-plugin-server.onpostauthtoolkit.redirected.md)

## OnPostAuthToolkit.redirected property

To interrupt request handling and redirect to a configured url

<b>Signature:</b>

```typescript
redirected: (url: string) => OnPostAuthResult;
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index) &gt; [kibana-plugin-server](./kibana-plugin-server.md) &gt; [OnPostAuthToolkit](./kibana-plugin-server.onpostauthtoolkit.md) &gt; [rejected](./kibana-plugin-server.onpostauthtoolkit.rejected.md)

## OnPostAuthToolkit.rejected property

Fail the request with specified error.

<b>Signature:</b>

```typescript
rejected: (error: Error, options?: {
statusCode?: number;
}) => OnPostAuthResult;
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

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

## OnPreAuthHandler type


<b>Signature:</b>

```typescript
export declare type OnPreAuthHandler<Params = any, Query = any, Body = any> = (request: KibanaRequest<Params, Query, Body>, t: OnPreAuthToolkit) => OnPreAuthResult | Promise<OnPreAuthResult>;
```
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) &gt; [kibana-plugin-server](./kibana-plugin-server.md) &gt; [OnPreAuthToolkit](./kibana-plugin-server.onpreauthtoolkit.md)

## OnPreAuthToolkit interface

A tool set defining an outcome of OnPreAuth interceptor for incoming request.

<b>Signature:</b>

```typescript
export interface OnPreAuthToolkit
```

## Properties

| Property | Type | Description |
| --- | --- | --- |
| [next](./kibana-plugin-server.onpreauthtoolkit.next.md) | <code>() =&gt; OnPreAuthResult</code> | To pass request to the next handler |
| [redirected](./kibana-plugin-server.onpreauthtoolkit.redirected.md) | <code>(url: string, options?: {`<p/>` forward: boolean;`<p/>` }) =&gt; OnPreAuthResult</code> | To interrupt request handling and redirect to a configured url. If "options.forwarded" = true, request will be forwarded to another url right on the server. |
| [rejected](./kibana-plugin-server.onpreauthtoolkit.rejected.md) | <code>(error: Error, options?: {`<p/>` statusCode?: number;`<p/>` }) =&gt; OnPreAuthResult</code> | Fail the request with specified error. |

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

[Home](./index) &gt; [kibana-plugin-server](./kibana-plugin-server.md) &gt; [OnRequestToolkit](./kibana-plugin-server.onrequesttoolkit.md) &gt; [next](./kibana-plugin-server.onrequesttoolkit.next.md)
[Home](./index) &gt; [kibana-plugin-server](./kibana-plugin-server.md) &gt; [OnPreAuthToolkit](./kibana-plugin-server.onpreauthtoolkit.md) &gt; [next](./kibana-plugin-server.onpreauthtoolkit.next.md)

## OnRequestToolkit.next property
## OnPreAuthToolkit.next property

To pass request to the next handler

<b>Signature:</b>

```typescript
next: () => OnRequestResult;
next: () => OnPreAuthResult;
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index) &gt; [kibana-plugin-server](./kibana-plugin-server.md) &gt; [OnPreAuthToolkit](./kibana-plugin-server.onpreauthtoolkit.md) &gt; [redirected](./kibana-plugin-server.onpreauthtoolkit.redirected.md)

## OnPreAuthToolkit.redirected property

To interrupt request handling and redirect to a configured url. If "options.forwarded" = true, request will be forwarded to another url right on the server.

<b>Signature:</b>

```typescript
redirected: (url: string, options?: {
forward: boolean;
}) => OnPreAuthResult;
```
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index) &gt; [kibana-plugin-server](./kibana-plugin-server.md) &gt; [OnRequestToolkit](./kibana-plugin-server.onrequesttoolkit.md) &gt; [rejected](./kibana-plugin-server.onrequesttoolkit.rejected.md)
[Home](./index) &gt; [kibana-plugin-server](./kibana-plugin-server.md) &gt; [OnPreAuthToolkit](./kibana-plugin-server.onpreauthtoolkit.md) &gt; [rejected](./kibana-plugin-server.onpreauthtoolkit.rejected.md)

## OnRequestToolkit.rejected property
## OnPreAuthToolkit.rejected property

Fail the request with specified error.

Expand All @@ -11,5 +11,5 @@ Fail the request with specified error.
```typescript
rejected: (error: Error, options?: {
statusCode?: number;
}) => OnRequestResult;
}) => OnPreAuthResult;
```

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

51 changes: 51 additions & 0 deletions src/core/server/http/auth_state_storage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { Request } from 'hapi';
import { KibanaRequest } 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;

export class AuthStateStorage {
private readonly storage = new WeakMap<ReturnType<typeof toKey>, unknown>();
constructor(private readonly canBeAuthenticated: () => boolean) {}
public set = (request: KibanaRequest | Request, state: unknown) => {
this.storage.set(toKey(request), state);
};
public get = (request: KibanaRequest | Request) => {
const key = toKey(request);
const state = this.storage.get(key);
const status: AuthStatus = this.storage.has(key)
? AuthStatus.authenticated
: this.canBeAuthenticated()
? AuthStatus.unauthenticated
: AuthStatus.unknown;

return { status, state };
};
public isAuthenticated = (request: KibanaRequest | Request) => {
return this.get(request).status === AuthStatus.authenticated;
};
}
Loading