Skip to content

Commit

Permalink
Allow AAD syntax
Browse files Browse the repository at this point in the history
Fixes #76
  • Loading branch information
mattjohnsonpint committed Jan 6, 2022
1 parent 69e5de6 commit 94ff38d
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 5 deletions.
43 changes: 38 additions & 5 deletions src/UserCredentials.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.ComponentModel;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Principal;
Expand Down Expand Up @@ -190,8 +191,23 @@ private static void ValidateDomainAndUser(string domain, string username)
if (domain.IndexOfAny(new[] { '\\', '@' }) != -1)
throw new ArgumentException("Domain cannot contain \\ or @ characters.", nameof(domain));

if (username.IndexOfAny(new[] { '\\', '@' }) != -1)
throw new ArgumentException("Username cannot contain \\ or @ characters when domain is provided separately.", nameof(username));
if (string.Equals(domain, "AzureAD", StringComparison.OrdinalIgnoreCase))
{
if (username.IndexOf('\\') != -1)
throw new ArgumentException("Username cannot contain \\ when the domain is AzureAD.", nameof(username));

int i = username.IndexOf('@');
if (i == -1)
throw new ArgumentException("Username must contain @ when the domain is AzureAD.", nameof(username));

if (username.IndexOf('@', i+1) != -1)
throw new ArgumentException("Username cannot contain more than one @ when the domain is AzureAD.", nameof(username));
}
else
{
if (username.IndexOfAny(new[] { '\\', '@' }) != -1)
throw new ArgumentException("Username cannot contain \\ or @ characters when domain is provided separately.", nameof(username));
}
}

private static void ValidateUserWithoutDomain(string username)
Expand All @@ -202,18 +218,35 @@ private static void ValidateUserWithoutDomain(string username)
if (username.Trim() == string.Empty)
throw new ArgumentException("Username cannot be empty or consist solely of whitespace characters.", nameof(username));

char[] validSeparators;
if (username.StartsWith(@"AzureAD\", StringComparison.OrdinalIgnoreCase))
{
username = username.Substring(8);
if (username.IndexOf('@') == -1)
throw new ArgumentException("Username must contain @ when the domain is AzureAD.", nameof(username));

if (username.IndexOf('\\') != -1)
throw new ArgumentException("Username cannot contain another \\ when the domain is AzureAD.", nameof(username));

validSeparators = new[] { '@' };
}
else
{
validSeparators = new[] { '@', '\\' };
}

int separatorCount = 0;
foreach (var c in username)
{
if (c == '\\' || c == '@')
if (validSeparators.Contains(c))
separatorCount++;
}

if (separatorCount == 0)
return;

if (separatorCount > 1)
throw new ArgumentException("Username cannot contain more than one \\ or @ character.", nameof(username));
throw new ArgumentException("Username cannot contain more than one separator.", nameof(username));

var firstChar = username[0];
var lastChar = username[username.Length - 1];
Expand Down Expand Up @@ -258,7 +291,7 @@ private static void SplitDomainFromUsername(ref string username, out string doma
/// <inheritdoc />
public override string ToString()
{
return _domain == null ? _username : _username + "@" + _domain;
return _domain == null ? _username : _username.IndexOf('@') != -1 ? $@"{_domain}\{_username}" : $"{_username}@{_domain}";
}
}
}
50 changes: 50 additions & 0 deletions test/UserCredentialsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,56 @@ public void UserCredentials_LocalService_Valid()
Assert.Equal("LOCAL SERVICE@NT AUTHORITY", UserCredentials.LocalService.ToString(), ignoreCase: true);
}

[Fact]
public void UserCredentials_Constructor_Valid_AzureAD_1()
{
var creds = new UserCredentials(@"AzureAD\user@domain", "password");
Assert.Equal(@"AzureAD\user@domain", creds.ToString());
}

[Fact]
public void UserCredentials_Constructor_Valid_AzureAD_2()
{
var creds = new UserCredentials("AzureAD", "user@domain", "password");
Assert.Equal(@"AzureAD\user@domain", creds.ToString());
}

[Fact]
public void UserCredentials_Constructor_Invalid_AzureAD_1()
{
Assert.Throws<ArgumentException>(() =>
{
var _ = new UserCredentials(@"AzureAD\user", "password");
});
}

[Fact]
public void UserCredentials_Constructor_Invalid_AzureAD_2()
{
Assert.Throws<ArgumentException>(() =>
{
var _ = new UserCredentials("AzureAD", "user", "password");
});
}

[Fact]
public void UserCredentials_Constructor_Invalid_AzureAD_3()
{
Assert.Throws<ArgumentException>(() =>
{
var _ = new UserCredentials("AzureAD", @"domain\user", "password");
});
}

[Fact]
public void UserCredentials_Constructor_Invalid_AzureAD_4()
{
Assert.Throws<ArgumentException>(() =>
{
var _ = new UserCredentials("AzureAD", "user@foo@bar", "password");
});
}

private static SecureString CreateSecureStringPasswordForTesting()
{
// Note: This is obviously not really a secure password. We just need something to test the API with.
Expand Down

0 comments on commit 94ff38d

Please sign in to comment.