Skip to content
This repository was archived by the owner on Dec 14, 2017. It is now read-only.

Commit c4a2af9

Browse files
committed
Merge branch 'dev'
2 parents 2b861a8 + 367ba60 commit c4a2af9

22 files changed

+665
-119
lines changed

samples/SingleTenant/SingleTenantWebApp/Web.config

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@
152152
<mailSettings>
153153
<smtp from="[email protected]" deliveryMethod="SpecifiedPickupDirectory">
154154
<!-- <network host="smtp.gmail.com" userName="[email protected]" password="" port="587" enableSsl="true" />-->
155-
<specifiedPickupDirectory pickupDirectoryLocation="C:\Scrap" />
155+
<specifiedPickupDirectory pickupDirectoryLocation="C:\logs" />
156156
</smtp>
157157
</mailSettings>
158158
</system.net>

src/BrockAllen.MembershipReboot.Test/AccountService/UserAccountServiceTests.cs

Lines changed: 179 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -936,21 +936,32 @@ public void Authenticate_ValidCredentials_ReturnsTrue()
936936
{
937937
configuration.RequireAccountVerification = false;
938938
var acct = subject.CreateAccount("test", "pass", "[email protected]");
939-
Assert.IsTrue(subject.Authenticate("test", "pass"));
939+
AuthenticationFailureCode failureCode;
940+
Assert.IsTrue(subject.Authenticate("test", "pass", out failureCode));
941+
Assert.AreEqual(AuthenticationFailureCode.None, failureCode);
940942
}
941943

944+
942945
[TestMethod]
943946
public void Authenticate_InvalidCredentials_ReturnsFalse()
944947
{
945948
configuration.RequireAccountVerification = false;
946949
var acct = subject.CreateAccount("test", "pass", "[email protected]");
947-
Assert.IsFalse(subject.Authenticate("test", "abc"));
948-
Assert.IsFalse(subject.Authenticate("test", "123"));
949-
Assert.IsFalse(subject.Authenticate("test", ""));
950-
Assert.IsFalse(subject.Authenticate("test", null));
951-
Assert.IsFalse(subject.Authenticate("", "pass"));
952-
Assert.IsFalse(subject.Authenticate((string)null, "pass"));
953-
Assert.IsFalse(subject.Authenticate("test2", "pass"));
950+
AuthenticationFailureCode failureCode;
951+
Assert.IsFalse(subject.Authenticate("test", "abc", out failureCode));
952+
Assert.AreEqual(AuthenticationFailureCode.InvalidCredentials, failureCode);
953+
Assert.IsFalse(subject.Authenticate("test", "123", out failureCode));
954+
Assert.AreEqual(AuthenticationFailureCode.InvalidCredentials, failureCode);
955+
Assert.IsFalse(subject.Authenticate("test", "", out failureCode));
956+
Assert.AreEqual(AuthenticationFailureCode.InvalidCredentials, failureCode);
957+
Assert.IsFalse(subject.Authenticate("test", null, out failureCode));
958+
Assert.AreEqual(AuthenticationFailureCode.InvalidCredentials, failureCode);
959+
Assert.IsFalse(subject.Authenticate("", "pass", out failureCode));
960+
Assert.AreEqual(AuthenticationFailureCode.InvalidCredentials, failureCode);
961+
Assert.IsFalse(subject.Authenticate((string) null, "pass", out failureCode));
962+
Assert.AreEqual(AuthenticationFailureCode.InvalidCredentials, failureCode);
963+
Assert.IsFalse(subject.Authenticate("test2", "pass", out failureCode));
964+
Assert.AreEqual(AuthenticationFailureCode.InvalidCredentials, failureCode);
954965
}
955966

956967
[TestMethod]
@@ -965,7 +976,9 @@ public void Authenticate_TooManyBadPasswords_Fails()
965976
subject.Authenticate("test", "bad");
966977
subject.Authenticate("test", "bad");
967978
subject.Authenticate("test", "bad");
968-
Assert.IsFalse(subject.Authenticate("test", "pass"));
979+
AuthenticationFailureCode failureCode;
980+
Assert.IsFalse(subject.Authenticate("test", "pass", out failureCode));
981+
Assert.AreEqual(AuthenticationFailureCode.FailedLoginAttemptsExceeded, failureCode);
969982
}
970983

971984
[TestMethod]
@@ -1012,6 +1025,82 @@ public void Authenticate_AccountLocked_AfterLockoutDuration_FailedAttemptsReset(
10121025
Assert.AreEqual(1, acct.FailedLoginCount);
10131026
}
10141027

1028+
[TestMethod]
1029+
public void Authenticate_AccountNotVerified_Fails()
1030+
{
1031+
this.configuration.RequireAccountVerification = true;
1032+
1033+
var acc = subject.CreateAccount("test", "pass", "[email protected]");
1034+
AuthenticationFailureCode failureCode;
1035+
Assert.IsFalse(subject.Authenticate("test", "pass", out failureCode));
1036+
Assert.AreEqual(AuthenticationFailureCode.AccountNotVerified, failureCode);
1037+
}
1038+
1039+
[TestMethod]
1040+
public void Authenticate_LoginNotAllowed_Fails()
1041+
{
1042+
this.configuration.RequireAccountVerification = false;
1043+
1044+
var acc = subject.CreateAccount("test", "pass", "[email protected]");
1045+
acc.IsLoginAllowed = false;
1046+
AuthenticationFailureCode failureCode;
1047+
Assert.IsFalse(subject.Authenticate("test", "pass", out failureCode));
1048+
Assert.AreEqual(AuthenticationFailureCode.LoginNotAllowed, failureCode);
1049+
}
1050+
1051+
[TestMethod]
1052+
public void Authenticate_AccountClosed_Fails()
1053+
{
1054+
this.configuration.RequireAccountVerification = false;
1055+
1056+
var acc = subject.CreateAccount("test", "pass", "[email protected]");
1057+
acc.IsAccountClosed = true;
1058+
AuthenticationFailureCode failureCode;
1059+
Assert.IsFalse(subject.Authenticate("test", "pass", out failureCode));
1060+
Assert.AreEqual(AuthenticationFailureCode.AccountClosed, failureCode);
1061+
}
1062+
1063+
[TestMethod]
1064+
public void Authenticate_AccountMissingPassword_Fails()
1065+
{
1066+
this.configuration.RequireAccountVerification = false;
1067+
1068+
string nullPassword = null;
1069+
// ReSharper disable ExpressionIsAlwaysNull
1070+
subject.CreateAccount("test", nullPassword, "[email protected]");
1071+
AuthenticationFailureCode failureCode;
1072+
Assert.IsFalse(subject.Authenticate("test", nullPassword, out failureCode));
1073+
Assert.AreEqual(AuthenticationFailureCode.InvalidCredentials, failureCode);
1074+
// ReSharper restore ExpressionIsAlwaysNull
1075+
}
1076+
1077+
[TestMethod]
1078+
public void Authenticate_MobileTwoFactorAuthRequired_MissingMobileNumber_Fails()
1079+
{
1080+
this.configuration.RequireAccountVerification = false;
1081+
1082+
var acc = subject.CreateAccount("test", "pass", "[email protected]");
1083+
acc.MobilePhoneNumber = "";
1084+
acc.AccountTwoFactorAuthMode = TwoFactorAuthMode.Mobile;
1085+
1086+
AuthenticationFailureCode failureCode;
1087+
Assert.IsFalse(subject.Authenticate("test", "pass", out failureCode));
1088+
Assert.AreEqual(AuthenticationFailureCode.AccountNotConfiguredWithMobilePhone, failureCode);
1089+
}
1090+
1091+
[TestMethod]
1092+
public void Authenticate_CertificateTwoFactorAuthRequired_NoConfiguredCerts_Fails()
1093+
{
1094+
this.configuration.RequireAccountVerification = false;
1095+
1096+
var acc = subject.CreateAccount("test", "pass", "[email protected]");
1097+
acc.AccountTwoFactorAuthMode = TwoFactorAuthMode.Certificate;
1098+
1099+
AuthenticationFailureCode failureCode;
1100+
Assert.IsFalse(subject.Authenticate("test", "pass", out failureCode));
1101+
Assert.AreEqual(AuthenticationFailureCode.AccountNotConfiguredWithCertificates, failureCode);
1102+
}
1103+
10151104
[TestMethod]
10161105
public void Authenticate_ReturnsCorrectAccount()
10171106
{
@@ -1027,7 +1116,9 @@ public void AuthenticateWithEmail_ValidEmail_ReturnsTrue()
10271116
{
10281117
configuration.RequireAccountVerification = false;
10291118
var acct = subject.CreateAccount("test", "pass", "[email protected]");
1030-
Assert.IsTrue(subject.AuthenticateWithEmail("[email protected]", "pass"));
1119+
AuthenticationFailureCode failureCode;
1120+
Assert.IsTrue(subject.AuthenticateWithEmail("[email protected]", "pass", out failureCode));
1121+
Assert.AreEqual(AuthenticationFailureCode.None, failureCode);
10311122
}
10321123

10331124
[TestMethod]
@@ -1045,13 +1136,21 @@ public void AuthenticateWithEmail_InvalidCredentials_ReturnsFalse()
10451136
{
10461137
configuration.RequireAccountVerification = false;
10471138
var acct = subject.CreateAccount("test", "pass", "[email protected]");
1048-
Assert.IsFalse(subject.Authenticate("[email protected]", "abc"));
1049-
Assert.IsFalse(subject.Authenticate("[email protected]", "123"));
1050-
Assert.IsFalse(subject.Authenticate("[email protected]", ""));
1051-
Assert.IsFalse(subject.Authenticate("[email protected]", null));
1052-
Assert.IsFalse(subject.Authenticate("", "pass"));
1053-
Assert.IsFalse(subject.Authenticate((string)null, "pass"));
1054-
Assert.IsFalse(subject.Authenticate("test2", "pass"));
1139+
AuthenticationFailureCode failureCode;
1140+
Assert.IsFalse(subject.AuthenticateWithEmail("[email protected]", "abc", out failureCode));
1141+
Assert.AreEqual(AuthenticationFailureCode.InvalidCredentials, failureCode);
1142+
Assert.IsFalse(subject.AuthenticateWithEmail("[email protected]", "123", out failureCode));
1143+
Assert.AreEqual(AuthenticationFailureCode.InvalidCredentials, failureCode);
1144+
Assert.IsFalse(subject.AuthenticateWithEmail("[email protected]", "", out failureCode));
1145+
Assert.AreEqual(AuthenticationFailureCode.InvalidCredentials, failureCode);
1146+
Assert.IsFalse(subject.AuthenticateWithEmail("[email protected]", null, out failureCode));
1147+
Assert.AreEqual(AuthenticationFailureCode.InvalidCredentials, failureCode);
1148+
Assert.IsFalse(subject.AuthenticateWithEmail("", "pass", out failureCode));
1149+
Assert.AreEqual(AuthenticationFailureCode.InvalidCredentials, failureCode);
1150+
Assert.IsFalse(subject.AuthenticateWithEmail(null, "pass", out failureCode));
1151+
Assert.AreEqual(AuthenticationFailureCode.InvalidCredentials, failureCode);
1152+
Assert.IsFalse(subject.AuthenticateWithEmail("test2", "pass", out failureCode));
1153+
Assert.AreEqual(AuthenticationFailureCode.InvalidCredentials, failureCode);
10551154
}
10561155

10571156
[TestMethod]
@@ -1072,8 +1171,11 @@ public void AuthenticateWithUsernameOrEmail_ValidCredentials_ReturnsTrue()
10721171
configuration.RequireAccountVerification = false;
10731172
subject.CreateAccount("test", "pass", "[email protected]");
10741173
UserAccount acct;
1075-
Assert.IsTrue(subject.AuthenticateWithUsernameOrEmail("test", "pass", out acct));
1076-
Assert.IsTrue(subject.AuthenticateWithUsernameOrEmail("[email protected]", "pass", out acct));
1174+
AuthenticationFailureCode failureCode;
1175+
Assert.IsTrue(subject.AuthenticateWithUsernameOrEmail("test", "pass", out acct, out failureCode));
1176+
Assert.AreEqual(AuthenticationFailureCode.None, failureCode);
1177+
Assert.IsTrue(subject.AuthenticateWithUsernameOrEmail("[email protected]", "pass", out acct, out failureCode));
1178+
Assert.AreEqual(AuthenticationFailureCode.None, failureCode);
10771179
}
10781180

10791181
[TestMethod]
@@ -1083,8 +1185,10 @@ public void AuthenticateWithUsernameOrEmail_SecuritySettingsEmailIsUsername_Retu
10831185
configuration.RequireAccountVerification = false;
10841186
subject.CreateAccount("test", "pass", "[email protected]");
10851187
UserAccount acct;
1086-
Assert.IsFalse(subject.AuthenticateWithUsernameOrEmail("test", "pass", out acct));
1087-
Assert.IsTrue(subject.AuthenticateWithUsernameOrEmail("[email protected]", "pass", out acct));
1188+
AuthenticationFailureCode failureCode;
1189+
Assert.IsFalse(subject.AuthenticateWithUsernameOrEmail("test", "pass", out acct, out failureCode));
1190+
Assert.IsTrue(subject.AuthenticateWithUsernameOrEmail("[email protected]", "pass", out acct, out failureCode));
1191+
Assert.AreEqual(AuthenticationFailureCode.None, failureCode);
10881192
}
10891193

10901194
[TestMethod]
@@ -1174,6 +1278,24 @@ public void AuthenticateWithCode_InvalidAccountId_Throws()
11741278
}
11751279
}
11761280

1281+
[TestMethod]
1282+
public void AuthenticationFailureCode_GetValidationMessage()
1283+
{
1284+
var failureCodes = GetEnumToSymbols<AuthenticationFailureCode>().Except(new[] { AuthenticationFailureCode.None });
1285+
foreach (AuthenticationFailureCode code in failureCodes)
1286+
{
1287+
Assert.IsFalse(String.IsNullOrEmpty(subject.GetValidationMessage(code)));
1288+
}
1289+
}
1290+
1291+
static IEnumerable<TEnum> GetEnumToSymbols<TEnum>() where TEnum : struct
1292+
{
1293+
return (from f in typeof(TEnum).GetFields()
1294+
where !f.IsSpecialName
1295+
select f.GetRawConstantValue()).Cast<TEnum>();
1296+
}
1297+
1298+
11771299
static X509Certificate2 GetTestCert()
11781300
{
11791301
using (var s = Assembly.GetExecutingAssembly().GetManifestResourceStream("BrockAllen.MembershipReboot.Test.test.cer"))
@@ -1668,6 +1790,42 @@ public void ChangePasswordFromResetKey_EmptyNewPass_Fails()
16681790
}
16691791
}
16701792

1793+
[TestMethod]
1794+
public void ChangePasswordFromResetKey_ResetsFailedLoginCount()
1795+
{
1796+
var id = subject.CreateAccount("test", "pass", "[email protected]").ID;
1797+
subject.VerifyEmailFromKey(this.LastVerificationKey, "pass");
1798+
1799+
subject.Authenticate("test", "bad_pass");
1800+
1801+
var account = subject.GetByID(id);
1802+
Assert.AreEqual(1, account.FailedLoginCount);
1803+
1804+
subject.ResetPassword("[email protected]");
1805+
var key = LastVerificationKey;
1806+
subject.ChangePasswordFromResetKey(key, "new_pass");
1807+
1808+
account = subject.GetByID(id);
1809+
Assert.AreEqual(0, account.FailedLoginCount);
1810+
}
1811+
1812+
[TestMethod]
1813+
public void ResetFailedLoginCount_ResetsFailedLoginCount()
1814+
{
1815+
var id = subject.CreateAccount("test", "pass", "[email protected]").ID;
1816+
subject.VerifyEmailFromKey(this.LastVerificationKey, "pass");
1817+
1818+
subject.Authenticate("test", "bad_pass");
1819+
1820+
var account = subject.GetByID(id);
1821+
Assert.AreEqual(1, account.FailedLoginCount);
1822+
1823+
subject.ResetFailedLoginCount(id);
1824+
1825+
account = subject.GetByID(id);
1826+
Assert.AreEqual(0, account.FailedLoginCount);
1827+
}
1828+
16711829
[TestMethod]
16721830
public void ChangeUsername_ChangesUsername()
16731831
{

src/BrockAllen.MembershipReboot.Test/Authentication/SignInWithLinkedAccountTests.cs

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,21 +48,47 @@ public void Use_NameClaim_As_Username_For_New_UserAccount()
4848
subject.SignInWithLinkedAccount("google", "123", new[]
4949
{
5050
new Claim(ClaimTypes.Email, "[email protected]"),
51-
new Claim(ClaimTypes.Name, "Christian"),
51+
new Claim(ClaimTypes.Name, "Christian")
5252
});
5353
var addedAccount = repository.UserAccounts[0];
5454
Assert.AreEqual("Christian", addedAccount.Username);
5555
}
5656

5757
[TestMethod]
58-
public void Failback_To_Guessing_Username_From_Email_For_New_UserAccount()
58+
public void Use_NameClaim_Stripped_Of_Invalid_Chars_For_New_UserAccount()
5959
{
6060
subject.SignInWithLinkedAccount("google", "123", new[]
6161
{
62-
new Claim(ClaimTypes.Email, "[email protected]")
62+
new Claim(ClaimTypes.Email, "[email protected]"),
63+
new Claim(ClaimTypes.Name, " ~ Christian Crowhurst @ ")
64+
});
65+
var addedAccount = repository.UserAccounts[0];
66+
Assert.AreEqual("Christian Crowhurst", addedAccount.Username);
67+
}
68+
69+
[TestMethod]
70+
public void Guessed_Username_Should_Strip_Invalid_Chars()
71+
{
72+
subject.SignInWithLinkedAccount("google", "123", new[]
73+
{
74+
new Claim(ClaimTypes.Email, "[email protected]"),
75+
new Claim(ClaimTypes.Name, " ~ Christian Crowhurst @ ")
76+
});
77+
var addedAccount = repository.UserAccounts[0];
78+
Assert.AreEqual("Christian Crowhurst", addedAccount.Username);
79+
}
80+
81+
[TestMethod]
82+
[Description("For list of allowed special chars see UserAccountValidation<TAccount>")]
83+
public void Guessed_Username_Should_Allow_Special_Chars()
84+
{
85+
subject.SignInWithLinkedAccount("google", "123", new[]
86+
{
87+
new Claim(ClaimTypes.Email, "[email protected]"),
88+
new Claim(ClaimTypes.Name, @" ~ Christian.Forrest-Smith_OK @ ")
6389
});
6490
var addedAccount = repository.UserAccounts[0];
65-
Assert.AreEqual("test", addedAccount.Username);
91+
Assert.AreEqual("Christian.Forrest-Smith_OK", addedAccount.Username);
6692
}
6793
}
6894
}

src/BrockAllen.MembershipReboot.Test/BrockAllen.MembershipReboot.Test.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
<Compile Include="FakeUserAccountRepository.cs" />
6969
<Compile Include="GroupService\TestGroupService.cs" />
7070
<Compile Include="KeyNotification.cs" />
71+
<Compile Include="Localisation\LocalisationTests.cs" />
7172
<Compile Include="Properties\AssemblyInfo.cs" />
7273
<Compile Include="AccountService\UserAccountServiceTests.cs" />
7374
<Compile Include="TestUserAccountService.cs" />

src/BrockAllen.MembershipReboot.Test/Crypto/CryptoHelperTests.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,23 +28,23 @@ public override int GetCurrentYear()
2828
public void HashPassword_CountStoredInHashedPassword()
2929
{
3030
{
31-
var result = crypto.HashPassword("pass", SecuritySettings.Instance.PasswordHashingIterationCount);
32-
StringAssert.StartsWith(result, crypto.EncodeIterations(IterationsForCurrentYear) + DefaultCrypto.PasswordHashingIterationCountSeparator);
31+
var result = crypto.HashPassword("pass", new SecuritySettings().PasswordHashingIterationCount);
32+
StringAssert.StartsWith(result, crypto.EncodeIterations(IterationsForCurrentYear) + DefaultCrypto.PasswordHashingIterationCountSeparator, "Default Count");
3333
}
3434
{
3535
SecuritySettings.Instance.PasswordHashingIterationCount = 5000;
3636
var result = crypto.HashPassword("pass", SecuritySettings.Instance.PasswordHashingIterationCount);
37-
StringAssert.StartsWith(result, crypto.EncodeIterations(5000) + DefaultCrypto.PasswordHashingIterationCountSeparator);
37+
StringAssert.StartsWith(result, crypto.EncodeIterations(5000) + DefaultCrypto.PasswordHashingIterationCountSeparator, "5000");
3838
}
3939
{
4040
SecuritySettings.Instance.PasswordHashingIterationCount = 10000;
4141
var result = crypto.HashPassword("pass", SecuritySettings.Instance.PasswordHashingIterationCount);
42-
StringAssert.StartsWith(result, crypto.EncodeIterations(10000) + DefaultCrypto.PasswordHashingIterationCountSeparator);
42+
StringAssert.StartsWith(result, crypto.EncodeIterations(10000) + DefaultCrypto.PasswordHashingIterationCountSeparator, "10000");
4343
}
4444
{
4545
SecuritySettings.Instance.PasswordHashingIterationCount = 50;
4646
var result = crypto.HashPassword("pass", SecuritySettings.Instance.PasswordHashingIterationCount);
47-
StringAssert.StartsWith(result, crypto.EncodeIterations(50) + DefaultCrypto.PasswordHashingIterationCountSeparator);
47+
StringAssert.StartsWith(result, crypto.EncodeIterations(50) + DefaultCrypto.PasswordHashingIterationCountSeparator, "50");
4848
}
4949
}
5050

0 commit comments

Comments
 (0)