diff --git a/docs/basic-config.asciidoc b/docs/basic-config.asciidoc index 38ed7c1d8..04e95ca9e 100644 --- a/docs/basic-config.asciidoc +++ b/docs/basic-config.asciidoc @@ -67,6 +67,13 @@ auth: { apiKey: 'base64EncodedKey' } ---- +Bearer authentication, useful for https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-create-service-token.html[service account tokens]. Be aware that it does not handle automatic token refresh: +[source,js] +---- +auth: { + bearer: 'token' +} +---- |`maxRetries` @@ -248,4 +255,4 @@ const client = new Client({ |`boolean`, `'proto'`, `'constructor'` - By the default the client will protect you against prototype poisoning attacks. Read https://web.archive.org/web/20200319091159/https://hueniverse.com/square-brackets-are-the-enemy-ff5b9fd8a3e8?gi=184a27ee2a08[this article] to learn more. If needed you can disable prototype poisoning protection entirely or one of the two checks. Read the `secure-json-parse` https://github.com/fastify/secure-json-parse[documentation] to learn more. + _Default:_ `false` -|=== \ No newline at end of file +|=== diff --git a/docs/connecting.asciidoc b/docs/connecting.asciidoc index 4854a096a..d24abe594 100644 --- a/docs/connecting.asciidoc +++ b/docs/connecting.asciidoc @@ -93,6 +93,26 @@ const client = new Client({ }) ---- +[discrete] +[[auth-bearer]] +==== Bearer authentication + +You can provide your credentials by passing the `bearer` token +parameter via the `auth` option. +Useful for https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-create-service-token.html[service account tokens]. +Be aware that it does not handle automatic token refresh. + +[source,js] +---- +const { Client } = require('@elastic/elasticsearch') +const client = new Client({ + node: 'https://localhost:9200', + auth: { + bearer: 'token' + } +}) +---- + [discrete] [[auth-basic]] diff --git a/index.d.ts b/index.d.ts index cdc56d657..0ff290303 100644 --- a/index.d.ts +++ b/index.d.ts @@ -43,7 +43,8 @@ import { CloudConnectionPool, ResurrectEvent, BasicAuth, - ApiKeyAuth + ApiKeyAuth, + BearerAuth } from './lib/pool'; import Serializer from './lib/Serializer'; import Helpers from './lib/Helpers'; @@ -106,7 +107,7 @@ interface ClientOptions { opaqueIdPrefix?: string; generateRequestId?: generateRequestIdFn; name?: string | symbol; - auth?: BasicAuth | ApiKeyAuth; + auth?: BasicAuth | ApiKeyAuth | BearerAuth; context?: Context; proxy?: string | URL; enableMetaHeader?: boolean; diff --git a/lib/Connection.js b/lib/Connection.js index 20e08f708..6eda7c539 100644 --- a/lib/Connection.js +++ b/lib/Connection.js @@ -331,6 +331,8 @@ function prepareHeaders (headers = {}, auth) { } else { headers.authorization = `ApiKey ${auth.apiKey}` } + } else if (auth.bearer) { + headers.authorization = `Bearer ${auth.bearer}` } else if (auth.username && auth.password) { headers.authorization = 'Basic ' + Buffer.from(`${auth.username}:${auth.password}`).toString('base64') } diff --git a/lib/pool/index.d.ts b/lib/pool/index.d.ts index 246f88d2b..c1ebbdad6 100644 --- a/lib/pool/index.d.ts +++ b/lib/pool/index.d.ts @@ -61,6 +61,10 @@ interface BasicAuth { password: string; } +interface BearerAuth { + bearer: string +} + interface resurrectOptions { now?: number; requestId: string; @@ -204,6 +208,7 @@ export { getConnectionOptions, ApiKeyAuth, BasicAuth, + BearerAuth, internals, resurrectOptions, ResurrectEvent, diff --git a/test/unit/client.test.js b/test/unit/client.test.js index 9c2c551ba..95ae7cc12 100644 --- a/test/unit/client.test.js +++ b/test/unit/client.test.js @@ -1421,3 +1421,30 @@ test('Disable prototype poisoning protection', t => { t.error(err) }) }) + +test('Bearer auth', t => { + t.plan(3) + + function handler (req, res) { + t.match(req.headers, { + authorization: 'Bearer Zm9vOmJhcg==' + }) + res.setHeader('Content-Type', 'application/json;utf=8') + res.end(JSON.stringify({ hello: 'world' })) + } + + buildServer(handler, ({ port }, server) => { + const client = new Client({ + node: `http://localhost:${port}`, + auth: { + bearer: 'Zm9vOmJhcg==' + } + }) + + client.info((err, { body }) => { + t.error(err) + t.same(body, { hello: 'world' }) + server.stop() + }) + }) +})