Skip to content

Commit

Permalink
* removed AuthenticationHeaderValue ctor from user credentials (and t…
Browse files Browse the repository at this point in the history
…ests).
  • Loading branch information
RagingKore committed Nov 13, 2023
1 parent 82ad41b commit 519ec26
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 122 deletions.
136 changes: 48 additions & 88 deletions src/EventStore.Client/UserCredentials.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,92 +3,52 @@
using static System.Convert;

namespace EventStore.Client {
/// <summary>
/// Represents either a username/password pair or a JWT token used for authentication and
/// authorization to perform operations on the EventStoreDB.
/// </summary>
public class UserCredentials {
// ReSharper disable once InconsistentNaming
static readonly UTF8Encoding UTF8NoBom = new UTF8Encoding(false);

/// <summary>
/// Constructs a new <see cref="UserCredentials"/>.
/// </summary>
public UserCredentials(string username, string password) {
Username = username;
Password = password;

Authorization = new(
Constants.Headers.BasicScheme,
ToBase64String(UTF8NoBom.GetBytes($"{username}:{password}"))
);
}

/// <summary>
/// Constructs a new <see cref="UserCredentials"/>.
/// </summary>
public UserCredentials(string bearerToken) {
Authorization = new(Constants.Headers.BearerScheme, bearerToken);
}

/// <summary>
/// Constructs a new <see cref="UserCredentials"/>.
/// </summary>
public UserCredentials(AuthenticationHeaderValue authorization) {
Authorization = authorization;

if (authorization.Scheme != Constants.Headers.BasicScheme)
return;

var (username, password) = DecodeBasicCredentials(Authorization);

Username = username;
Password = password;

return;

static (string? Username, string? Password) DecodeBasicCredentials(AuthenticationHeaderValue value) {
if (value.Parameter is null)
return (null, null);

var credentials = UTF8NoBom.GetString(FromBase64String(value.Parameter)).AsSpan();

var passwordStart = credentials.IndexOf(':') + 1;
var password = credentials[passwordStart..].ToString();

var usernameLength = credentials.Length - password.Length - 1;
var username = credentials[..usernameLength].ToString();

return (username, password);

// var decoded = UTF8NoBom.GetString(FromBase64String(header.Parameter));
// var parts = decoded.Split(':');
//
// return parts.Length == 2
// ? (parts[0], parts[1])
// : (null, null); // should we throw?
}
}

AuthenticationHeaderValue Authorization { get; }

/// <summary>
/// The username
/// </summary>
public string? Username { get; }

/// <summary>
/// The password
/// </summary>
public string? Password { get; }

/// <inheritdoc />
public override string ToString() => Authorization.ToString();

/// <summary>
/// Implicitly convert a <see cref="UserCredentials"/> to a <see cref="string"/>.
/// </summary>

public static implicit operator string(UserCredentials self) => self.ToString();
}
/// <summary>
/// Represents either a username/password pair or a JWT token used for authentication and
/// authorization to perform operations on the EventStoreDB.
/// </summary>
public class UserCredentials {
// ReSharper disable once InconsistentNaming
static readonly UTF8Encoding UTF8NoBom = new UTF8Encoding(false);

/// <summary>
/// Constructs a new <see cref="UserCredentials"/>.
/// </summary>
public UserCredentials(string username, string password) {
Username = username;
Password = password;

Authorization = new(
Constants.Headers.BasicScheme,
ToBase64String(UTF8NoBom.GetBytes($"{username}:{password}"))
);
}

/// <summary>
/// Constructs a new <see cref="UserCredentials"/>.
/// </summary>
public UserCredentials(string bearerToken) {
Authorization = new(Constants.Headers.BearerScheme, bearerToken);
}

AuthenticationHeaderValue Authorization { get; }

/// <summary>
/// The username
/// </summary>
public string? Username { get; }

/// <summary>
/// The password
/// </summary>
public string? Password { get; }

/// <inheritdoc />
public override string ToString() => Authorization.ToString();

/// <summary>
/// Implicitly convert a <see cref="UserCredentials"/> to a <see cref="string"/>.
/// </summary>
public static implicit operator string(UserCredentials self) => self.ToString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,40 +31,6 @@ public void from_username_and_password() {
credentials.ToString().ShouldBe(basicAuthInfo);
}

[Theory]
[InlineData("madison", "itwill:befine")]
[InlineData("admin", "changeit")]
public void from_authentication_header_with_basic_scheme(string username, string password) {
var value = new AuthenticationHeaderValue(
Constants.Headers.BasicScheme,
EncodeCredentials(username, password)
);

var basicAuthInfo = value.ToString();

var credentials = new UserCredentials(value);

credentials.Username.ShouldBe(username);
credentials.Password.ShouldBe(password);
credentials.ToString().ShouldBe(basicAuthInfo);
}

[Fact]
public void from_authentication_header_with_bearer_scheme() {
var value = new AuthenticationHeaderValue(
Constants.Headers.BearerScheme,
JwtToken
);

var bearerToken = value.ToString();

var credentials = new UserCredentials(value);

credentials.Username.ShouldBeNull();
credentials.Password.ShouldBeNull();
credentials.ToString().ShouldBe(bearerToken);
}

[Fact]
public void from_bearer_token() {
var credentials = new UserCredentials(JwtToken);
Expand Down

0 comments on commit 519ec26

Please sign in to comment.