From e3f3feee1c72020d5eb50714bb546de1b1f825ec Mon Sep 17 00:00:00 2001 From: Jakub Bednar Date: Thu, 7 Apr 2022 09:24:15 +0200 Subject: [PATCH 1/3] fix: Authentication Cookies follow redirects --- Client.Test/InfluxDbClientTest.cs | 40 +++++++++++++++++++++++++++++++ Client/Internal/ApiClient.cs | 25 +++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/Client.Test/InfluxDbClientTest.cs b/Client.Test/InfluxDbClientTest.cs index df5ecb0fa..90d5eaa8b 100644 --- a/Client.Test/InfluxDbClientTest.cs +++ b/Client.Test/InfluxDbClientTest.cs @@ -1,3 +1,4 @@ +using System; using System.Diagnostics; using System.IO; using System.Linq; @@ -283,6 +284,45 @@ public async Task RedirectToken() anotherServer.Stop(); } + [Test] + public async Task RedirectCookie() + { + _client.Dispose(); + _client = InfluxDBClientFactory.Create(new InfluxDBClientOptions.Builder() + .Url(MockServerUrl) + .Authenticate("my-username", "my-password".ToCharArray()) + .AllowRedirects(true) + .Build()); + + var anotherServer = WireMockServer.Start(new WireMockServerSettings + { + UseSSL = false + }); + + // auth cookies + MockServer + .Given(Request.Create().UsingPost()) + .RespondWith(Response.Create().WithHeader("Set-Cookie", "session=xyz")); + + // redirect to another server + MockServer + .Given(Request.Create().UsingGet()) + .RespondWith(Response.Create().WithStatusCode(301).WithHeader("location", anotherServer.Urls[0])); + + // success response + anotherServer + .Given(Request.Create().UsingGet()) + .RespondWith(CreateResponse("{\"status\":\"active\"}", "application/json")); + + var authorization = await _client.GetAuthorizationsApi().FindAuthorizationByIdAsync("id"); + Assert.AreEqual(AuthorizationUpdateRequest.StatusEnum.Active, authorization.Status); + + StringAssert.StartsWith("xyz", MockServer.LogEntries.Last().RequestMessage.Cookies["session"]); + Assert.AreEqual("xyz", anotherServer.LogEntries.Last().RequestMessage.Cookies["session"]); + + anotherServer.Stop(); + } + [Test] public async Task Anonymous() { diff --git a/Client/Internal/ApiClient.cs b/Client/Internal/ApiClient.cs index 6bb23027a..d28e09836 100644 --- a/Client/Internal/ApiClient.cs +++ b/Client/Internal/ApiClient.cs @@ -6,8 +6,10 @@ using System.Net; using System.Security.Cryptography.X509Certificates; using System.Text; +using System.Threading.Tasks; using InfluxDB.Client.Core.Internal; using RestSharp; +using RestSharp.Authenticators; namespace InfluxDB.Client.Api.Client { @@ -126,6 +128,15 @@ private void InitToken() if (authResponse.Cookies != null) { _initializedSessionTokens = true; + // The cookies doesn't follow redirects => we have to manually set `Cookie` header by Authenticator. + if (_options.AllowHttpRedirects && authResponse.Cookies.Count > 0) + { + var headerParameter = authResponse + .Headers? + .FirstOrDefault(it => string.Equals("Set-Cookie", it.Name, StringComparison.OrdinalIgnoreCase)); + + RestClient.Authenticator = new CookieRedirectAuthenticator(headerParameter); + } } } } @@ -145,6 +156,20 @@ protected internal void Signout() var request = new RestRequest("/api/v2/signout", Method.Post); RestClient.ExecuteAsync(request).ConfigureAwait(false).GetAwaiter().GetResult(); + RestClient.Authenticator = null; } } + + /// + /// Set Cookies to HTTP Request. + /// + internal class CookieRedirectAuthenticator : AuthenticatorBase + { + internal CookieRedirectAuthenticator(Parameter setCookie) : base(setCookie.Value?.ToString() ?? "") + { + } + + protected override ValueTask GetAuthenticationParameter(string cookie) + => new ValueTask(new HeaderParameter("Cookie", cookie)); + } } \ No newline at end of file From cd0e1f443ec81f8f0e82fd1b31c3ee7daf1df5ef Mon Sep 17 00:00:00 2001 From: Jakub Bednar Date: Thu, 7 Apr 2022 09:29:11 +0200 Subject: [PATCH 2/3] docs: update CHANGELOG.md --- CHANGELOG.md | 5 ++++- Client/Internal/ApiClient.cs | 9 ++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 55556b46b..2efc9307f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,10 @@ ## 4.1.0 [unreleased] ### Features -1. [#101](https://github.com/influxdata/influxdb-client-csharp/pull/304): Add `InvocableScriptsApi` to create, update, list, delete and invoke scripts by seamless way +1. [#304](https://github.com/influxdata/influxdb-client-csharp/pull/304): Add `InvocableScriptsApi` to create, update, list, delete and invoke scripts by seamless way + +### Bug Fixes +1. [#305](https://github.com/influxdata/influxdb-client-csharp/pull/305): Authentication Cookies follow redirects ## 4.0.0 [2022-03-18] diff --git a/Client/Internal/ApiClient.cs b/Client/Internal/ApiClient.cs index d28e09836..4ee47fd1d 100644 --- a/Client/Internal/ApiClient.cs +++ b/Client/Internal/ApiClient.cs @@ -133,8 +133,9 @@ private void InitToken() { var headerParameter = authResponse .Headers? - .FirstOrDefault(it => string.Equals("Set-Cookie", it.Name, StringComparison.OrdinalIgnoreCase)); - + .FirstOrDefault(it => + string.Equals("Set-Cookie", it.Name, StringComparison.OrdinalIgnoreCase)); + RestClient.Authenticator = new CookieRedirectAuthenticator(headerParameter); } } @@ -170,6 +171,8 @@ internal CookieRedirectAuthenticator(Parameter setCookie) : base(setCookie.Value } protected override ValueTask GetAuthenticationParameter(string cookie) - => new ValueTask(new HeaderParameter("Cookie", cookie)); + { + return new ValueTask(new HeaderParameter("Cookie", cookie)); + } } } \ No newline at end of file From 4e088dcde526a374b96eab4111da3194942e9f4d Mon Sep 17 00:00:00 2001 From: Jakub Bednar Date: Thu, 7 Apr 2022 09:33:41 +0200 Subject: [PATCH 3/3] fix: formatting --- Client.Test/InfluxDbClientTest.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Client.Test/InfluxDbClientTest.cs b/Client.Test/InfluxDbClientTest.cs index 90d5eaa8b..eb9419416 100644 --- a/Client.Test/InfluxDbClientTest.cs +++ b/Client.Test/InfluxDbClientTest.cs @@ -293,17 +293,17 @@ public async Task RedirectCookie() .Authenticate("my-username", "my-password".ToCharArray()) .AllowRedirects(true) .Build()); - + var anotherServer = WireMockServer.Start(new WireMockServerSettings { UseSSL = false }); - + // auth cookies MockServer .Given(Request.Create().UsingPost()) .RespondWith(Response.Create().WithHeader("Set-Cookie", "session=xyz")); - + // redirect to another server MockServer .Given(Request.Create().UsingGet()) @@ -317,7 +317,7 @@ public async Task RedirectCookie() var authorization = await _client.GetAuthorizationsApi().FindAuthorizationByIdAsync("id"); Assert.AreEqual(AuthorizationUpdateRequest.StatusEnum.Active, authorization.Status); - StringAssert.StartsWith("xyz", MockServer.LogEntries.Last().RequestMessage.Cookies["session"]); + Assert.AreEqual("xyz", MockServer.LogEntries.Last().RequestMessage.Cookies["session"]); Assert.AreEqual("xyz", anotherServer.LogEntries.Last().RequestMessage.Cookies["session"]); anotherServer.Stop();