diff --git a/RELEASES.md b/RELEASES.md
index 49d72b2..166598f 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -18,4 +18,8 @@
## v2.0.0
-- Changes the compatibility to the RestSharp version `111.2.0` or greater.
\ No newline at end of file
+- Changes the compatibility to the RestSharp version `111.2.0` or greater.
+
+## v2.0.1
+
+- Add ability to change client options from digest RestClient object
\ No newline at end of file
diff --git a/src/DigestAuthenticator/DigestAuthenticator.cs b/src/DigestAuthenticator/DigestAuthenticator.cs
index 90a4e9e..c1ec638 100644
--- a/src/DigestAuthenticator/DigestAuthenticator.cs
+++ b/src/DigestAuthenticator/DigestAuthenticator.cs
@@ -16,6 +16,7 @@ public class DigestAuthenticator : IAuthenticator
private readonly string _username;
private readonly TimeSpan _timeout;
+ private readonly RestClientOptions? _handshakeClientOptions;
///
/// Creates a new instance of class.
@@ -24,7 +25,7 @@ public class DigestAuthenticator : IAuthenticator
/// The password.
/// The optional logger.
/// The request timeout.
- public DigestAuthenticator(string username, string password, int timeout = DEFAULT_TIMEOUT, ILogger? logger = null)
+ public DigestAuthenticator(string username, string password, int timeout = DEFAULT_TIMEOUT, ILogger? logger = null, RestClientOptions? restClientOptions=null)
{
if (string.IsNullOrWhiteSpace(username))
{
@@ -45,6 +46,7 @@ public DigestAuthenticator(string username, string password, int timeout = DEFAU
_password = password;
_timeout = TimeSpan.FromMilliseconds(timeout);
_logger = logger ?? NullLogger.Instance;
+ _handshakeClientOptions = restClientOptions;
}
///
@@ -52,8 +54,8 @@ public async ValueTask Authenticate(IRestClient client, RestRequest request)
{
_logger.LogDebug("Initiate Digest authentication");
var uri = client.BuildUri(request);
- var manager = new DigestAuthenticatorManager(client.BuildUri(new RestRequest()), _username, _password, _timeout, _logger);
- await manager.GetDigestAuthHeader(uri.PathAndQuery, request.Method,client.Options.Proxy).ConfigureAwait(false);
+ var manager = new DigestAuthenticatorManager(client.BuildUri(new RestRequest()), _username, _password, _timeout, _handshakeClientOptions, _logger);
+ await manager.GetDigestAuthHeader(uri.PathAndQuery, request.Method, client.Options.Proxy).ConfigureAwait(false);
var digestHeader = manager.GetDigestHeader(uri.PathAndQuery, request.Method);
request.AddOrUpdateHeader("Connection", "Keep-Alive");
request.AddOrUpdateHeader(KnownHeaders.Authorization, digestHeader);
diff --git a/src/DigestAuthenticator/DigestAuthenticatorManager.cs b/src/DigestAuthenticator/DigestAuthenticatorManager.cs
index 2115b5e..71a4236 100644
--- a/src/DigestAuthenticator/DigestAuthenticatorManager.cs
+++ b/src/DigestAuthenticator/DigestAuthenticatorManager.cs
@@ -2,6 +2,7 @@
using System.Globalization;
using System.Linq;
using System.Net;
+using System.Net.Security;
using System.Reflection;
using System.Security.Authentication;
using System.Security.Cryptography;
@@ -47,6 +48,7 @@ internal class DigestAuthenticatorManager
///
private string? _realm;
+ private readonly RestClientOptions? _handshakeClientOptions;
///
/// The opaque that is returned by the first digest request (without the data).
///
@@ -65,7 +67,7 @@ static DigestAuthenticatorManager()
/// The password.
/// The timeout.
///
- public DigestAuthenticatorManager(Uri host, string username, string password, TimeSpan timeout, ILogger logger)
+ public DigestAuthenticatorManager(Uri host, string username, string password, TimeSpan timeout, RestClientOptions? handshakeClientOptions, ILogger logger)
{
if (string.IsNullOrWhiteSpace(username))
{
@@ -87,6 +89,7 @@ public DigestAuthenticatorManager(Uri host, string username, string password, Ti
_password = password;
_timeout = timeout;
_logger = logger;
+ _handshakeClientOptions = handshakeClientOptions;
}
///
@@ -98,7 +101,7 @@ public DigestAuthenticatorManager(Uri host, string username, string password, Ti
public async Task GetDigestAuthHeader(
string path,
Method method,
- IWebProxy? proxy = default)
+ IWebProxy? proxy = null)
{
_logger.LogDebug("Initiating GetDigestAuthHeader");
var uri = new Uri(_host, path);
@@ -108,11 +111,19 @@ public async Task GetDigestAuthHeader(
request.AddOrUpdateHeader("User-Agent", $"RestSharp.Authenticators.Digest/{_assemblyVersion}");
request.AddOrUpdateHeader("Accept-Encoding", "gzip, deflate, br");
request.Timeout = _timeout;
- using var client = new RestClient(new RestClientOptions()
+
+ RestClient client;
+ if (_handshakeClientOptions != null)
+ {
+ client = new RestClient(_handshakeClientOptions);
+ }
+ else
{
- Proxy = proxy
- });
+ client = new RestClient(new RestClientOptions() { Proxy = proxy });
+ }
+
var response = await client.ExecuteAsync(request).ConfigureAwait(false);
+ client.Dispose();
GetDigestDataFromFailResponse(response);
_logger.LogDebug("GetDigestAuthHeader completed");
}
diff --git a/test/DigestAuthenticator.Tests/DigestIntegrationTest.cs b/test/DigestAuthenticator.Tests/DigestIntegrationTest.cs
index d4470b9..582c8aa 100644
--- a/test/DigestAuthenticator.Tests/DigestIntegrationTest.cs
+++ b/test/DigestAuthenticator.Tests/DigestIntegrationTest.cs
@@ -37,4 +37,31 @@ public async Task Given_ADigestAuthEndpoint_When_ITryToGetInfo_Then_TheAuthMustB
response.StatusCode.Should().Be(HttpStatusCode.OK);
loggerMock.ReceivedWithAnyArgs().LogDebug("NONONO");
}
+
+
+ [Fact]
+ public async Task Given_ADigestAuthEndpoint_When_ITryToInjectOwnClient_Then_TheAuthMustBeResolved()
+ {
+ bool proxyCalled = false;
+
+ var loggerMock = Substitute.For();
+ loggerMock.BeginScope("DigestServerStub");
+
+ var request = new RestRequest("values");
+ request.AddHeader("Content-Type", "application/json");
+
+ RestClientOptions options = new RestClientOptions()
+ {
+ Proxy = new TestProxy(() => proxyCalled = true)
+ };
+
+ var client = _fixture.CreateInjectedOptionClient(loggerMock, options);
+ var response = await client.ExecuteAsync(request);
+
+ response.StatusCode.Should().Be(HttpStatusCode.OK);
+ loggerMock.ReceivedWithAnyArgs().LogDebug("NONONO");
+
+ Assert.True(proxyCalled, "Injected RestClientOptions.Proxy should be used in digest handshake.");
+
+ }
}
diff --git a/test/DigestAuthenticator.Tests/Fixtures/DigestServerStub.cs b/test/DigestAuthenticator.Tests/Fixtures/DigestServerStub.cs
index fbd207d..1ebb73f 100644
--- a/test/DigestAuthenticator.Tests/Fixtures/DigestServerStub.cs
+++ b/test/DigestAuthenticator.Tests/Fixtures/DigestServerStub.cs
@@ -15,7 +15,7 @@ public class DigestServerStub : IAsyncDisposable
{
private readonly CancellationTokenSource _cancellationTokenSource;
private readonly Task _serverTask;
-
+
private const string REALM = "test-realm";
private const string USERNAME = "test-user";
private const string PASSWORD = "test-password";
@@ -26,7 +26,7 @@ public DigestServerStub()
var nonce = GenerateNonce();
_cancellationTokenSource = new CancellationTokenSource();
-
+
_serverTask = StartServer(REALM, USERNAME, PASSWORD, nonce, PORT);
Console.WriteLine($"Server started! port: {PORT}.");
}
@@ -41,6 +41,17 @@ public IRestClient CreateClient(ILogger logger)
return new RestClient(restOptions);
}
+ public IRestClient CreateInjectedOptionClient(ILogger logger, RestClientOptions clientOptions )
+ {
+
+ var restOptions = new RestClientOptions($"http://localhost:{PORT}")
+ {
+ Authenticator = new DigestAuthenticator(USERNAME, PASSWORD, logger: logger, restClientOptions: clientOptions)
+ };
+
+ return new RestClient(restOptions);
+ }
+
public async ValueTask DisposeAsync()
{
GC.SuppressFinalize(this);
diff --git a/test/DigestAuthenticator.Tests/Fixtures/TestProxy.cs b/test/DigestAuthenticator.Tests/Fixtures/TestProxy.cs
new file mode 100644
index 0000000..035419c
--- /dev/null
+++ b/test/DigestAuthenticator.Tests/Fixtures/TestProxy.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace RestSharp.Authenticators.Digest.Tests.Fixtures;
+internal class TestProxy : IWebProxy
+{
+ private readonly Action _onProxyCalled;
+
+ public TestProxy(Action onProxyCalled)
+ {
+ _onProxyCalled = onProxyCalled;
+ }
+
+ public Uri GetProxy(Uri destination)
+ {
+ _onProxyCalled();
+ return destination;
+ }
+
+ public bool IsBypassed(Uri host) => false;
+
+ public ICredentials? Credentials { get; set; }
+}