@@ -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 {
0 commit comments