diff --git a/nuget.config b/nuget.config
new file mode 100644
index 0000000..3f0e003
--- /dev/null
+++ b/nuget.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Elastic.Transport/Components/Connection/HttpConnection.cs b/src/Elastic.Transport/Components/Connection/HttpConnection.cs
index b7f48b7..05bb440 100644
--- a/src/Elastic.Transport/Components/Connection/HttpConnection.cs
+++ b/src/Elastic.Transport/Components/Connection/HttpConnection.cs
@@ -286,53 +286,31 @@ protected virtual void SetAuthenticationIfNeeded(HttpRequestMessage requestMessa
return;
}
- // Api Key authentication takes precedence
- var apiKeySet = SetApiKeyAuthenticationIfNeeded(requestMessage, requestData);
-
- if (!apiKeySet)
- SetBasicAuthenticationIfNeeded(requestMessage, requestData);
+ SetConfiguredAuthenticationHeaderIfNeeded(requestMessage, requestData);
}
- private static bool SetApiKeyAuthenticationIfNeeded(HttpRequestMessage requestMessage, RequestData requestData)
- {
- // ApiKey auth credentials take the following precedence (highest -> lowest):
- // 1 - Specified on the request (highest precedence)
- // 2 - Specified at the global IConnectionSettings level
-
-
- string apiKey = null;
- if (requestData.ApiKeyAuthenticationCredentials != null)
- apiKey = requestData.ApiKeyAuthenticationCredentials.Base64EncodedApiKey.CreateString();
-
- if (string.IsNullOrWhiteSpace(apiKey))
- return false;
-
- requestMessage.Headers.Authorization = new AuthenticationHeaderValue("ApiKey", apiKey);
- return true;
-
- }
-
- private static void SetBasicAuthenticationIfNeeded(HttpRequestMessage requestMessage, RequestData requestData)
+ private static void SetConfiguredAuthenticationHeaderIfNeeded(HttpRequestMessage requestMessage, RequestData requestData)
{
// Basic auth credentials take the following precedence (highest -> lowest):
- // 1 - Specified on the request (highest precedence)
- // 2 - Specified at the global IConnectionSettings level
- // 3 - Specified with the URI (lowest precedence)
+ // 1 - Specified with the URI (highest precedence)
+ // 2 - Specified on the request
+ // 3 - Specified at the global IConnectionSettings level (lowest precedence)
- string userInfo = null;
+ string value = null;
+ string key = null;
if (!requestData.Uri.UserInfo.IsNullOrEmpty())
- userInfo = Uri.UnescapeDataString(requestData.Uri.UserInfo);
- else if (requestData.BasicAuthorizationCredentials != null)
{
- userInfo =
- $"{requestData.BasicAuthorizationCredentials.Username}:{requestData.BasicAuthorizationCredentials.Password.CreateString()}";
+ value = BasicAuthentication.GetBase64String(Uri.UnescapeDataString(requestData.Uri.UserInfo));
+ key = BasicAuthentication.Base64Header;
}
-
- if (!userInfo.IsNullOrEmpty())
+ else if (requestData.AuthenticationHeader != null && requestData.AuthenticationHeader.TryGetHeader(out var v))
{
- var credentials = Convert.ToBase64String(Encoding.UTF8.GetBytes(userInfo!));
- requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Basic", credentials);
+ value = v;
+ key = requestData.AuthenticationHeader.Header;
}
+
+ if (value.IsNullOrEmpty()) return;
+ requestMessage.Headers.Authorization = new AuthenticationHeaderValue(key, value);
}
private static HttpRequestMessage CreateRequestMessage(RequestData requestData)
diff --git a/src/Elastic.Transport/Components/Connection/HttpWebRequestConnection.cs b/src/Elastic.Transport/Components/Connection/HttpWebRequestConnection.cs
index 6817e30..a11bbbf 100644
--- a/src/Elastic.Transport/Components/Connection/HttpWebRequestConnection.cs
+++ b/src/Elastic.Transport/Components/Connection/HttpWebRequestConnection.cs
@@ -311,11 +311,14 @@ protected virtual void SetProxyIfNeeded(HttpWebRequest request, RequestData requ
/// Hook for subclasses to set authentication on
protected virtual void SetAuthenticationIfNeeded(RequestData requestData, HttpWebRequest request)
{
- // Api Key authentication takes precedence
- var apiKeySet = SetApiKeyAuthenticationIfNeeded(request, requestData);
-
- if (!apiKeySet)
- SetBasicAuthenticationIfNeeded(request, requestData);
+ //If user manually specifies an Authorization Header give it preference
+ if (requestData.Headers.HasKeys() && requestData.Headers.AllKeys.Contains("Authorization"))
+ {
+ var header = requestData.Headers["Authorization"];
+ request.Headers["Authorization"] = header;
+ return;
+ }
+ SetBasicAuthenticationIfNeeded(request, requestData);
}
private static void SetBasicAuthenticationIfNeeded(HttpWebRequest request, RequestData requestData)
@@ -325,37 +328,28 @@ private static void SetBasicAuthenticationIfNeeded(HttpWebRequest request, Reque
// 2 - Specified at the global IConnectionSettings level
// 3 - Specified with the URI (lowest precedence)
- string userInfo = null;
- if (!string.IsNullOrEmpty(requestData.Uri.UserInfo))
- userInfo = Uri.UnescapeDataString(requestData.Uri.UserInfo);
- else if (requestData.BasicAuthorizationCredentials != null)
- {
- userInfo =
- $"{requestData.BasicAuthorizationCredentials.Username}:{requestData.BasicAuthorizationCredentials.Password.CreateString()}";
- }
-
- if (string.IsNullOrWhiteSpace(userInfo))
- return;
-
- request.Headers["Authorization"] = $"Basic {Convert.ToBase64String(Encoding.UTF8.GetBytes(userInfo))}";
- }
- private static bool SetApiKeyAuthenticationIfNeeded(HttpWebRequest request, RequestData requestData)
- {
- // ApiKey auth credentials take the following precedence (highest -> lowest):
- // 1 - Specified on the request (highest precedence)
- // 2 - Specified at the global IConnectionSettings level
-
- string apiKey = null;
- if (requestData.ApiKeyAuthenticationCredentials != null)
- apiKey = requestData.ApiKeyAuthenticationCredentials.Base64EncodedApiKey.CreateString();
+ // Basic auth credentials take the following precedence (highest -> lowest):
+ // 1 - Specified with the URI (highest precedence)
+ // 2 - Specified on the request
+ // 3 - Specified at the global IConnectionSettings level (lowest precedence)
- if (string.IsNullOrWhiteSpace(apiKey))
- return false;
+ string value = null;
+ string key = null;
+ if (!requestData.Uri.UserInfo.IsNullOrEmpty())
+ {
+ value = BasicAuthentication.GetBase64String(Uri.UnescapeDataString(requestData.Uri.UserInfo));
+ key = BasicAuthentication.Base64Header;
+ }
+ else if (requestData.AuthenticationHeader != null && requestData.AuthenticationHeader.TryGetHeader(out var v))
+ {
+ value = v;
+ key = requestData.AuthenticationHeader.Header;
+ }
- request.Headers["Authorization"] = $"ApiKey {apiKey}";
- return true;
+ if (value.IsNullOrEmpty()) return;
+ request.Headers["Authorization"] = $"{key} {value}";
}
///
diff --git a/src/Elastic.Transport/Components/ConnectionPool/CloudConnectionPool.cs b/src/Elastic.Transport/Components/ConnectionPool/CloudConnectionPool.cs
index 4c0797c..85c5e9a 100644
--- a/src/Elastic.Transport/Components/ConnectionPool/CloudConnectionPool.cs
+++ b/src/Elastic.Transport/Components/ConnectionPool/CloudConnectionPool.cs
@@ -37,32 +37,8 @@ public class CloudConnectionPool : SingleNodeConnectionPool
///
///
/// Optionally inject an instance of used to set
- public CloudConnectionPool(string cloudId, BasicAuthenticationCredentials credentials, IDateTimeProvider dateTimeProvider = null) : this(ParseCloudId(cloudId), dateTimeProvider) =>
- BasicCredentials = credentials;
-
- ///
- /// An implementation that can be seeded with a cloud id
- /// and will signal the right defaults for the client to use for Elastic Cloud to .
- ///
- /// Read more about Elastic Cloud Id here
- /// https://www.elastic.co/guide/en/cloud/current/ec-cloud-id.html
- ///
- ///
- /// The Cloud Id, this is available on your cluster's dashboard and is a string in the form of cluster_name:base_64_encoded_string
- /// Base64 encoded string contains the following tokens in order separated by $:
- /// * Host Name (mandatory)
- /// * Elasticsearch UUID (mandatory)
- /// * Kibana UUID
- /// * APM UUID
- ///
- /// We then use these tokens to create the URI to your Elastic Cloud cluster!
- ///
- /// Read more here: https://www.elastic.co/guide/en/cloud/current/ec-cloud-id.html
- ///
- ///
- /// Optionally inject an instance of used to set
- public CloudConnectionPool(string cloudId, ApiKeyAuthenticationCredentials credentials, IDateTimeProvider dateTimeProvider = null) : this(ParseCloudId(cloudId), dateTimeProvider) =>
- ApiKeyCredentials = credentials;
+ public CloudConnectionPool(string cloudId, IAuthenticationHeader credentials, IDateTimeProvider dateTimeProvider = null) : this(ParseCloudId(cloudId), dateTimeProvider) =>
+ AuthenticationHeader = credentials;
private CloudConnectionPool(ParsedCloudId parsedCloudId, IDateTimeProvider dateTimeProvider = null) : base(parsedCloudId.Uri, dateTimeProvider) =>
ClusterName = parsedCloudId.Name;
@@ -71,11 +47,8 @@ private CloudConnectionPool(ParsedCloudId parsedCloudId, IDateTimeProvider dateT
// ReSharper disable once UnusedAutoPropertyAccessor.Local
private string ClusterName { get; }
- /// Read-only access to the basic authentication credentials that were passed in
- public BasicAuthenticationCredentials BasicCredentials { get; }
-
- /// Read-only access to the api key authentication credentials that were passed in
- public ApiKeyAuthenticationCredentials ApiKeyCredentials { get; }
+ ///
+ public IAuthenticationHeader AuthenticationHeader { get; }
private readonly struct ParsedCloudId
{
@@ -121,10 +94,6 @@ private static ParsedCloudId ParseCloudId(string cloudId)
}
/// Allows subclasses to hook into the parents dispose
- protected override void DisposeManagedResources()
- {
- ApiKeyCredentials?.Dispose();
- BasicCredentials?.Dispose();
- }
+ protected override void DisposeManagedResources() => AuthenticationHeader?.Dispose();
}
}
diff --git a/src/Elastic.Transport/Components/Pipeline/RequestData.cs b/src/Elastic.Transport/Components/Pipeline/RequestData.cs
index 8e295ba..fa512e7 100644
--- a/src/Elastic.Transport/Components/Pipeline/RequestData.cs
+++ b/src/Elastic.Transport/Components/Pipeline/RequestData.cs
@@ -94,8 +94,7 @@ IMemoryStreamFactory memoryStreamFactory
ProxyUsername = global.ProxyUsername;
ProxyPassword = global.ProxyPassword;
DisableAutomaticProxyDetection = global.DisableAutomaticProxyDetection;
- BasicAuthorizationCredentials = local?.BasicAuthenticationCredentials ?? global.BasicAuthenticationCredentials;
- ApiKeyAuthenticationCredentials = local?.ApiKeyAuthenticationCredentials ?? global.ApiKeyAuthenticationCredentials;
+ AuthenticationHeader = local?.AuthenticationHeader ?? global.AuthenticationHeader;
AllowedStatusCodes = local?.AllowedStatusCodes ?? EmptyReadOnly.Collection;
ClientCertificates = local?.ClientCertificates ?? global.ClientCertificates;
UserAgent = global.UserAgent;
@@ -109,9 +108,7 @@ IMemoryStreamFactory memoryStreamFactory
public string Accept { get; }
public IReadOnlyCollection AllowedStatusCodes { get; }
- public ApiKeyAuthenticationCredentials ApiKeyAuthenticationCredentials { get; }
-
- public BasicAuthenticationCredentials BasicAuthorizationCredentials { get; }
+ public IAuthenticationHeader AuthenticationHeader { get; }
public X509CertificateCollection ClientCertificates { get; }
public ITransportConfigurationValues ConnectionSettings { get; }
diff --git a/src/Elastic.Transport/Components/Pipeline/RequestPipeline.cs b/src/Elastic.Transport/Components/Pipeline/RequestPipeline.cs
index af54ca0..a8dd478 100644
--- a/src/Elastic.Transport/Components/Pipeline/RequestPipeline.cs
+++ b/src/Elastic.Transport/Components/Pipeline/RequestPipeline.cs
@@ -62,8 +62,7 @@ IRequestParameters requestParameters
{
PingTimeout = PingTimeout,
RequestTimeout = PingTimeout,
- BasicAuthenticationCredentials = _settings.BasicAuthenticationCredentials,
- ApiKeyAuthenticationCredentials = _settings.ApiKeyAuthenticationCredentials,
+ AuthenticationHeader = _settings.AuthenticationHeader,
EnableHttpPipelining = RequestConfiguration?.EnableHttpPipelining ?? _settings.HttpPipeliningEnabled,
ForceNode = RequestConfiguration?.ForceNode
};
diff --git a/src/Elastic.Transport/Configuration/ITransportConfigurationValues.cs b/src/Elastic.Transport/Configuration/ITransportConfigurationValues.cs
index c69be32..330854c 100644
--- a/src/Elastic.Transport/Configuration/ITransportConfigurationValues.cs
+++ b/src/Elastic.Transport/Configuration/ITransportConfigurationValues.cs
@@ -19,21 +19,8 @@ namespace Elastic.Transport
///
public interface ITransportConfigurationValues : IDisposable
{
- ///
- /// Basic access authorization credentials to specify with all requests.
- ///
- ///
- /// Cannot be used in conjuction with
- ///
- BasicAuthenticationCredentials BasicAuthenticationCredentials { get; }
-
- ///
- /// Api Key authorization credentials to specify with all requests.
- ///
- ///
- /// Cannot be used in conjuction with
- ///
- ApiKeyAuthenticationCredentials ApiKeyAuthenticationCredentials { get; }
+ ///
+ IAuthenticationHeader AuthenticationHeader { get; }
/// Provides a semaphoreslim to transport implementations that need to limit access to a resource
SemaphoreSlim BootstrapLock { get; }
diff --git a/src/Elastic.Transport/Configuration/RequestConfiguration.cs b/src/Elastic.Transport/Configuration/RequestConfiguration.cs
index 2ca19cc..341eeb3 100644
--- a/src/Elastic.Transport/Configuration/RequestConfiguration.cs
+++ b/src/Elastic.Transport/Configuration/RequestConfiguration.cs
@@ -27,22 +27,9 @@ public interface IRequestConfiguration
IReadOnlyCollection AllowedStatusCodes { get; set; }
///
- /// Basic access authorization credentials to specify with this request.
- /// Overrides any credentials that are set at the global IConnectionSettings level.
+ /// Provide an authentication header override for this request
///
- ///
- /// Cannot be used in conjunction with
- ///
- BasicAuthenticationCredentials BasicAuthenticationCredentials { get; set; }
-
- ///
- /// An API-key authorization credentials to specify with this request.
- /// Overrides any credentials that are set at the global IConnectionSettings level.
- ///
- ///
- /// Cannot be used in conjunction with
- ///
- ApiKeyAuthenticationCredentials ApiKeyAuthenticationCredentials { get; set; }
+ IAuthenticationHeader AuthenticationHeader { get; set; }
///
/// Use the following client certificates to authenticate this single request
@@ -140,9 +127,7 @@ public class RequestConfiguration : IRequestConfiguration
///
public IReadOnlyCollection AllowedStatusCodes { get; set; }
///
- public BasicAuthenticationCredentials BasicAuthenticationCredentials { get; set; }
- ///
- public ApiKeyAuthenticationCredentials ApiKeyAuthenticationCredentials { get; set; }
+ public IAuthenticationHeader AuthenticationHeader { get; set; }
///
public X509CertificateCollection ClientCertificates { get; set; }
///
@@ -195,8 +180,7 @@ public RequestConfigurationDescriptor(IRequestConfiguration config)
Self.DisablePing = config?.DisablePing;
Self.DisableDirectStreaming = config?.DisableDirectStreaming;
Self.AllowedStatusCodes = config?.AllowedStatusCodes;
- Self.BasicAuthenticationCredentials = config?.BasicAuthenticationCredentials;
- Self.ApiKeyAuthenticationCredentials = config?.ApiKeyAuthenticationCredentials;
+ Self.AuthenticationHeader = config?.AuthenticationHeader;
Self.EnableHttpPipelining = config?.EnableHttpPipelining ?? true;
Self.RunAs = config?.RunAs;
Self.ClientCertificates = config?.ClientCertificates;
@@ -210,8 +194,7 @@ public RequestConfigurationDescriptor(IRequestConfiguration config)
string IRequestConfiguration.Accept { get; set; }
IReadOnlyCollection IRequestConfiguration.AllowedStatusCodes { get; set; }
- BasicAuthenticationCredentials IRequestConfiguration.BasicAuthenticationCredentials { get; set; }
- ApiKeyAuthenticationCredentials IRequestConfiguration.ApiKeyAuthenticationCredentials { get; set; }
+ IAuthenticationHeader IRequestConfiguration.AuthenticationHeader { get; set; }
X509CertificateCollection IRequestConfiguration.ClientCertificates { get; set; }
string IRequestConfiguration.ContentType { get; set; }
bool? IRequestConfiguration.DisableDirectStreaming { get; set; }
@@ -329,45 +312,10 @@ public RequestConfigurationDescriptor MaxRetries(int retry)
return this;
}
- ///
- public RequestConfigurationDescriptor BasicAuthentication(string userName, string password)
- {
- Self.BasicAuthenticationCredentials = new BasicAuthenticationCredentials(userName, password);
- return this;
- }
-
- ///
- public RequestConfigurationDescriptor BasicAuthentication(string userName, SecureString password)
- {
- Self.BasicAuthenticationCredentials = new BasicAuthenticationCredentials(userName, password);
- return this;
- }
-
- ///
- public RequestConfigurationDescriptor ApiKeyAuthentication(string id, string apiKey)
- {
- Self.ApiKeyAuthenticationCredentials = new ApiKeyAuthenticationCredentials(id, apiKey);
- return this;
- }
-
- ///
- public RequestConfigurationDescriptor ApiKeyAuthentication(string id, SecureString apiKey)
- {
- Self.ApiKeyAuthenticationCredentials = new ApiKeyAuthenticationCredentials(id, apiKey);
- return this;
- }
-
- ///
- public RequestConfigurationDescriptor ApiKeyAuthentication(string base64EncodedApiKey)
- {
- Self.ApiKeyAuthenticationCredentials = new ApiKeyAuthenticationCredentials(base64EncodedApiKey);
- return this;
- }
-
- ///
- public RequestConfigurationDescriptor ApiKeyAuthentication(SecureString base64EncodedApiKey)
+ ///
+ public RequestConfigurationDescriptor Authentication(IAuthenticationHeader authentication)
{
- Self.ApiKeyAuthenticationCredentials = new ApiKeyAuthenticationCredentials(base64EncodedApiKey);
+ Self.AuthenticationHeader = authentication;
return this;
}
diff --git a/src/Elastic.Transport/Configuration/Security/ApiKey.cs b/src/Elastic.Transport/Configuration/Security/ApiKey.cs
new file mode 100644
index 0000000..45bdd4a
--- /dev/null
+++ b/src/Elastic.Transport/Configuration/Security/ApiKey.cs
@@ -0,0 +1,37 @@
+// Licensed to Elasticsearch B.V under one or more agreements.
+// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information
+
+using System;
+using System.Security;
+
+namespace Elastic.Transport
+{
+ ///
+ /// Credentials for Api Key Authentication
+ ///
+ public class ApiKey : IAuthenticationHeader
+ {
+ ///
+ public ApiKey(string apiKey) => Value = apiKey.CreateSecureString();
+
+ ///
+ public ApiKey(SecureString apiKey) => Value = apiKey;
+
+ private SecureString Value { get; }
+
+ ///
+ public virtual string Header { get; } = "Bearer";
+
+ ///
+ public bool TryGetHeader(out string value)
+ {
+ value = Value.CreateString();
+ return true;
+ }
+
+ ///
+ public void Dispose() => Value?.Dispose();
+
+ }
+}
diff --git a/src/Elastic.Transport/Configuration/Security/ApiKeyAuthenticationCredentials.cs b/src/Elastic.Transport/Configuration/Security/ApiKeyAuthenticationCredentials.cs
deleted file mode 100644
index 2018192..0000000
--- a/src/Elastic.Transport/Configuration/Security/ApiKeyAuthenticationCredentials.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-// Licensed to Elasticsearch B.V under one or more agreements.
-// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
-// See the LICENSE file in the project root for more information
-
-using System;
-using System.Security;
-using System.Text;
-
-namespace Elastic.Transport
-{
- ///
- /// Credentials for Api Key Authentication
- ///
- public class ApiKeyAuthenticationCredentials : IDisposable
- {
- ///
- public ApiKeyAuthenticationCredentials(string id, SecureString apiKey) =>
- Base64EncodedApiKey = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{id}:{apiKey.CreateString()}")).CreateSecureString();
-
- ///
- public ApiKeyAuthenticationCredentials(string id, string apiKey) =>
- Base64EncodedApiKey = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{id}:{apiKey}")).CreateSecureString();
-
- ///
- public ApiKeyAuthenticationCredentials(string base64EncodedApiKey) =>
- Base64EncodedApiKey = base64EncodedApiKey.CreateSecureString();
-
- ///
- public ApiKeyAuthenticationCredentials(SecureString base64EncodedApiKey) =>
- Base64EncodedApiKey = base64EncodedApiKey;
-
- ///
- /// The Base64 encoded api key with which to authenticate
- /// Take the form, id:api_key, which is then base 64 encoded
- ///
- public SecureString Base64EncodedApiKey { get; }
-
- ///
- public void Dispose() => Base64EncodedApiKey?.Dispose();
- }
-}
diff --git a/src/Elastic.Transport/Configuration/Security/Base64ApiKey.cs b/src/Elastic.Transport/Configuration/Security/Base64ApiKey.cs
new file mode 100644
index 0000000..17d32d1
--- /dev/null
+++ b/src/Elastic.Transport/Configuration/Security/Base64ApiKey.cs
@@ -0,0 +1,47 @@
+// Licensed to Elasticsearch B.V under one or more agreements.
+// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information
+
+using System;
+using System.Security;
+using System.Text;
+
+namespace Elastic.Transport
+{
+ ///
+ /// Credentials for Api Key Authentication
+ ///
+ public class Base64ApiKey : IAuthenticationHeader
+ {
+ ///
+ public Base64ApiKey(string id, SecureString apiKey) =>
+ Value = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{id}:{apiKey.CreateString()}")).CreateSecureString();
+
+ ///
+ public Base64ApiKey(string id, string apiKey) =>
+ Value = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{id}:{apiKey}")).CreateSecureString();
+
+ ///
+ public Base64ApiKey(string base64EncodedApiKey) =>
+ Value = base64EncodedApiKey.CreateSecureString();
+
+ ///
+ public Base64ApiKey(SecureString base64EncodedApiKey) =>
+ Value = base64EncodedApiKey;
+
+ private SecureString Value { get; }
+
+ ///
+ public void Dispose() => Value?.Dispose();
+
+ ///
+ public string Header { get; } = "ApiKey";
+
+ ///
+ public bool TryGetHeader(out string value)
+ {
+ value = Value.CreateString();
+ return true;
+ }
+ }
+}
diff --git a/src/Elastic.Transport/Configuration/Security/BasicAuthenticationCredentials.cs b/src/Elastic.Transport/Configuration/Security/BasicAuthenticationCredentials.cs
index 7376b09..074589a 100644
--- a/src/Elastic.Transport/Configuration/Security/BasicAuthenticationCredentials.cs
+++ b/src/Elastic.Transport/Configuration/Security/BasicAuthenticationCredentials.cs
@@ -4,34 +4,53 @@
using System;
using System.Security;
+using System.Text;
namespace Elastic.Transport
{
/// Credentials for Basic Authentication
- public class BasicAuthenticationCredentials : IDisposable
+ public class BasicAuthentication : IAuthenticationHeader
{
- ///
- public BasicAuthenticationCredentials(string username, string password)
+ ///
+ public BasicAuthentication(string username, string password)
{
Username = username;
- Password = password.CreateSecureString();
+ _cachedHeaderValue = GetBase64String($"{Username}:{password}");
}
- ///
- public BasicAuthenticationCredentials(string username, SecureString password)
+ ///
+ public BasicAuthentication(string username, SecureString password)
{
Username = username;
Password = password;
}
+ private readonly string _cachedHeaderValue;
+
/// The password with which to authenticate
- public SecureString Password { get; set; }
+ private SecureString Password { get; }
/// The username with which to authenticate
- public string Username { get; set; }
+ private string Username { get; }
///
public void Dispose() => Password?.Dispose();
+ ///
+ public string Header { get; } = Base64Header;
+
+ /// The default http header used for basic authentication
+ public static string Base64Header { get; } = "Basic";
+
+ ///
+ public bool TryGetHeader(out string value)
+ {
+ value = _cachedHeaderValue ?? GetBase64String($"{Username}:{Password.CreateString()}");
+ return true;
+ }
+
+ /// Get Base64 representation for string
+ public static string GetBase64String(string header) =>
+ Convert.ToBase64String(Encoding.UTF8.GetBytes(header));
}
}
diff --git a/src/Elastic.Transport/Configuration/Security/IAuthenticationHeader.cs b/src/Elastic.Transport/Configuration/Security/IAuthenticationHeader.cs
new file mode 100644
index 0000000..37612a0
--- /dev/null
+++ b/src/Elastic.Transport/Configuration/Security/IAuthenticationHeader.cs
@@ -0,0 +1,21 @@
+using System;
+
+namespace Elastic.Transport
+{
+ ///
+ /// An implementation of describing what http header to use to authenticate with the product.
+ /// for basic authentication
+ /// for simple secret token
+ /// for Elastic Cloud style encoded api keys
+ ///
+ public interface IAuthenticationHeader : IDisposable
+ {
+ /// The header to use to authenticate the request
+ public string Header { get; }
+
+ ///
+ /// If this instance is valid return the header name and value to use for authentication
+ ///
+ bool TryGetHeader(out string value);
+ }
+}
diff --git a/src/Elastic.Transport/Configuration/TransportConfiguration.cs b/src/Elastic.Transport/Configuration/TransportConfiguration.cs
index 7bb4946..6d9a74e 100644
--- a/src/Elastic.Transport/Configuration/TransportConfiguration.cs
+++ b/src/Elastic.Transport/Configuration/TransportConfiguration.cs
@@ -118,14 +118,14 @@ public TransportConfiguration(Uri uri = null, IProductRegistration productRegist
/// Sets up the client to communicate to Elastic Cloud using ,
/// documentation for more information on how to obtain your Cloud Id
///
- public TransportConfiguration(string cloudId, BasicAuthenticationCredentials credentials, IProductRegistration productRegistration = null)
+ public TransportConfiguration(string cloudId, BasicAuthentication credentials, IProductRegistration productRegistration = null)
: this(new CloudConnectionPool(cloudId, credentials), productRegistration: productRegistration) { }
///
/// Sets up the client to communicate to Elastic Cloud using ,
/// documentation for more information on how to obtain your Cloud Id
///
- public TransportConfiguration(string cloudId, ApiKeyAuthenticationCredentials credentials, IProductRegistration productRegistration = null)
+ public TransportConfiguration(string cloudId, Base64ApiKey credentials, IProductRegistration productRegistration = null)
: this(new CloudConnectionPool(cloudId, credentials), productRegistration: productRegistration) { }
///
@@ -156,8 +156,7 @@ public abstract class TransportConfigurationBase : ITransportConfigurationVal
private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1);
private readonly UrlFormatter _urlFormatter;
- private BasicAuthenticationCredentials _basicAuthCredentials;
- private ApiKeyAuthenticationCredentials _apiKeyAuthCredentials;
+ private IAuthenticationHeader _authenticationHeader;
private X509CertificateCollection _clientCertificates;
private Action _completedRequestHandler = DefaultCompletedRequestHandler;
private int _connectionLimit;
@@ -223,8 +222,7 @@ protected TransportConfigurationBase(IConnectionPool connectionPool, IConnection
if (connectionPool is CloudConnectionPool cloudPool)
{
- _basicAuthCredentials = cloudPool.BasicCredentials;
- _apiKeyAuthCredentials = cloudPool.ApiKeyCredentials;
+ _authenticationHeader = cloudPool.AuthenticationHeader;
_enableHttpCompression = true;
}
@@ -238,8 +236,7 @@ protected TransportConfigurationBase(IConnectionPool connectionPool, IConnection
// ReSharper disable once AutoPropertyCanBeMadeGetOnly.Global
protected ITransportSerializer UseThisRequestResponseSerializer { get; set; }
- BasicAuthenticationCredentials ITransportConfigurationValues.BasicAuthenticationCredentials => _basicAuthCredentials;
- ApiKeyAuthenticationCredentials ITransportConfigurationValues.ApiKeyAuthenticationCredentials => _apiKeyAuthCredentials;
+ IAuthenticationHeader ITransportConfigurationValues.AuthenticationHeader => _authenticationHeader;
SemaphoreSlim ITransportConfigurationValues.BootstrapLock => _semaphore;
X509CertificateCollection ITransportConfigurationValues.ClientCertificates => _clientCertificates;
IConnection ITransportConfigurationValues.Connection => _connection;
@@ -392,25 +389,8 @@ public T OnRequestCompleted(Action handler) =>
public T OnRequestDataCreated(Action handler) =>
Assign(handler, (a, v) => a._onRequestDataCreated += v ?? DefaultRequestDataCreated);
- ///
- public T BasicAuthentication(string username, string password) =>
- Assign(new BasicAuthenticationCredentials(username, password), (a, v) => a._basicAuthCredentials = v);
-
- ///
- public T BasicAuthentication(string username, SecureString password) =>
- Assign(new BasicAuthenticationCredentials(username, password), (a, v) => a._basicAuthCredentials = v);
-
- ///
- public T ApiKeyAuthentication(string id, SecureString apiKey) =>
- Assign(new ApiKeyAuthenticationCredentials(id, apiKey), (a, v) => a._apiKeyAuthCredentials = v);
-
- ///
- public T ApiKeyAuthentication(string id, string apiKey) =>
- Assign(new ApiKeyAuthenticationCredentials(id, apiKey), (a, v) => a._apiKeyAuthCredentials = v);
-
- ///
- public T ApiKeyAuthentication(ApiKeyAuthenticationCredentials credentials) =>
- Assign(credentials, (a, v) => a._apiKeyAuthCredentials = v);
+ ///
+ public T Authentication(IAuthenticationHeader header) => Assign(header, (a, v) => a._authenticationHeader = v);
///
public T EnableHttpPipelining(bool enabled = true) => Assign(enabled, (a, v) => a._enableHttpPipelining = v);
@@ -491,8 +471,7 @@ protected virtual void DisposeManagedResources()
_connection?.Dispose();
_semaphore?.Dispose();
_proxyPassword?.Dispose();
- _basicAuthCredentials?.Dispose();
- _apiKeyAuthCredentials?.Dispose();
+ _authenticationHeader?.Dispose();
}
/// Allows subclasses to add/remove default global query string parameters