From 50240b3a7af97a6a49519992bdaaa1fba905a68f Mon Sep 17 00:00:00 2001 From: Ziya Suzen Date: Sun, 3 Nov 2024 06:56:42 +0000 Subject: [PATCH] Implement URL encoding for user credentials --- src/NATS.Client.Core/NatsConnection.cs | 8 ++-- .../OptsUrlTests.cs | 40 +++++++++++++++++++ 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/src/NATS.Client.Core/NatsConnection.cs b/src/NATS.Client.Core/NatsConnection.cs index 23287d7f..fa1b673a 100644 --- a/src/NATS.Client.Core/NatsConnection.cs +++ b/src/NATS.Client.Core/NatsConnection.cs @@ -315,8 +315,8 @@ private static NatsOpts ReadUserInfoFromConnectionString(NatsOpts opts) { AuthOpts = opts.AuthOpts with { - Username = uriBuilder.UserName, - Password = uriBuilder.Password, + Username = Uri.UnescapeDataString(uriBuilder.UserName), + Password = Uri.UnescapeDataString(uriBuilder.Password), Token = null, // override token in case it was set }, }; @@ -333,7 +333,7 @@ private static NatsOpts ReadUserInfoFromConnectionString(NatsOpts opts) { AuthOpts = opts.AuthOpts with { - Token = uriBuilder.UserName, + Token = Uri.UnescapeDataString(uriBuilder.UserName), Username = null, // override user-password in case it was set Password = null, }, @@ -344,7 +344,7 @@ private static NatsOpts ReadUserInfoFromConnectionString(NatsOpts opts) if (usesPasswordInUrl) { - uriBuilder.UserName = opts.AuthOpts.Username; // show actual used username in logs + uriBuilder.UserName = Uri.EscapeDataString(opts.AuthOpts.Username!); // show actual used username in logs uriBuilder.Password = "***"; // to redact the password from logs } else if (usesTokenInUrl) diff --git a/tests/NATS.Client.CoreUnit.Tests/OptsUrlTests.cs b/tests/NATS.Client.CoreUnit.Tests/OptsUrlTests.cs index a19591b2..9b38e434 100644 --- a/tests/NATS.Client.CoreUnit.Tests/OptsUrlTests.cs +++ b/tests/NATS.Client.CoreUnit.Tests/OptsUrlTests.cs @@ -50,4 +50,44 @@ public void URL_should_override_auth_options(string url, string expected, string Assert.Equal(pass, opts.AuthOpts.Password); Assert.Equal(token, opts.AuthOpts.Token); } + + [Fact] + public void URL_escape_user_password() + { + var opts = new NatsConnection(new NatsOpts { Url = "nats://u%2C:p%2C@host1,host2" }).Opts; + Assert.Equal("nats://u%2C:***@host1:4222,nats://u%2C:***@host2:4222", opts.Url); + Assert.Equal("u,", opts.AuthOpts.Username); + Assert.Equal("p,", opts.AuthOpts.Password); + Assert.Null(opts.AuthOpts.Token); + + var uris = opts.GetSeedUris(true); + uris[0].Uri.Scheme.Should().Be("nats"); + uris[0].Uri.Host.Should().Be("host1"); + uris[0].Uri.Port.Should().Be(4222); + uris[0].Uri.UserInfo.Should().Be("u%2C:***"); + uris[1].Uri.Scheme.Should().Be("nats"); + uris[1].Uri.Host.Should().Be("host2"); + uris[1].Uri.Port.Should().Be(4222); + uris[1].Uri.UserInfo.Should().Be("u%2C:***"); + } + + [Fact] + public void URL_escape_token() + { + var opts = new NatsConnection(new NatsOpts { Url = "nats://t%2C@host1,nats://t%2C@host2" }).Opts; + Assert.Equal("nats://***@host1:4222,nats://***@host2:4222", opts.Url); + Assert.Null(opts.AuthOpts.Username); + Assert.Null(opts.AuthOpts.Password); + Assert.Equal("t,", opts.AuthOpts.Token); + + var uris = opts.GetSeedUris(true); + uris[0].Uri.Scheme.Should().Be("nats"); + uris[0].Uri.Host.Should().Be("host1"); + uris[0].Uri.Port.Should().Be(4222); + uris[0].Uri.UserInfo.Should().Be("***"); + uris[1].Uri.Scheme.Should().Be("nats"); + uris[1].Uri.Host.Should().Be("host2"); + uris[1].Uri.Port.Should().Be(4222); + uris[1].Uri.UserInfo.Should().Be("***"); + } }