diff --git a/src/Umbraco.Core/Security/MembershipProviderBase.cs b/src/Umbraco.Core/Security/MembershipProviderBase.cs
index 9d76c8e595..3794327781 100644
--- a/src/Umbraco.Core/Security/MembershipProviderBase.cs
+++ b/src/Umbraco.Core/Security/MembershipProviderBase.cs
@@ -11,76 +11,6 @@ using Umbraco.Core.Logging;
namespace Umbraco.Core.Security
{
-
- public abstract class UmbracoMembershipProviderBase : MembershipProviderBase
- {
- protected UmbracoMembershipProviderBase()
- {
- //Set the defaults!
- DefaultMemberTypeAlias = "Member";
- }
-
- public string DefaultMemberTypeAlias { get; protected set; }
-
- ///
- /// Adds a new membership user to the data source.
- ///
- /// The user name for the new user.
- /// The password for the new user.
- /// The e-mail address for the new user.
- /// The password question for the new user.
- /// The password answer for the new user
- /// Whether or not the new user is approved to be validated.
- /// The unique identifier from the membership data source for the user.
- /// A enumeration value indicating whether the user was created successfully.
- ///
- /// A object populated with the information for the newly created user.
- ///
- protected sealed override MembershipUser PerformCreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
- {
- return PerformCreateUser(DefaultMemberTypeAlias, username, password, email, passwordQuestion, passwordAnswer, isApproved, providerUserKey, out status);
- }
-
- ///
- /// Adds a new membership user to the data source.
- ///
- /// The member type alias to use when creating the member
- /// The user name for the new user.
- /// The password for the new user.
- /// The e-mail address for the new user.
- /// The password question for the new user.
- /// The password answer for the new user
- /// Whether or not the new user is approved to be validated.
- /// The unique identifier from the membership data source for the user.
- /// A enumeration value indicating whether the user was created successfully.
- ///
- /// A object populated with the information for the newly created user.
- ///
- public MembershipUser CreateUser(string memberTypeAlias, string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
- {
- //do the base validation first
- base.CreateUser(username, password, email, passwordQuestion, passwordAnswer, isApproved, providerUserKey, out status);
-
- return PerformCreateUser(memberTypeAlias, username, password, email, passwordQuestion, passwordAnswer, isApproved, providerUserKey, out status);
- }
-
- ///
- /// Adds a new membership user to the data source.
- ///
- /// The member type alias to use when creating the member
- /// The user name for the new user.
- /// The password for the new user.
- /// The e-mail address for the new user.
- /// The password question for the new user.
- /// The password answer for the new user
- /// Whether or not the new user is approved to be validated.
- /// The unique identifier from the membership data source for the user.
- /// A enumeration value indicating whether the user was created successfully.
- ///
- /// A object populated with the information for the newly created user.
- ///
- protected abstract MembershipUser PerformCreateUser(string memberTypeAlias, string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status);
- }
///
/// A base membership provider class offering much of the underlying functionality for initializing and password encryption/hashing.
///
@@ -741,7 +671,7 @@ namespace Umbraco.Core.Security
///
///
///
- protected string EncryptOrHashNewPassword(string newPassword, out string salt)
+ protected internal string EncryptOrHashNewPassword(string newPassword, out string salt)
{
salt = GenerateSalt();
return EncryptOrHashPassword(newPassword, salt);
diff --git a/src/Umbraco.Core/Security/UmbracoMembershipProviderBase.cs b/src/Umbraco.Core/Security/UmbracoMembershipProviderBase.cs
new file mode 100644
index 0000000000..6ecb6eedce
--- /dev/null
+++ b/src/Umbraco.Core/Security/UmbracoMembershipProviderBase.cs
@@ -0,0 +1,78 @@
+using System.Web.Security;
+
+namespace Umbraco.Core.Security
+{
+
+ ///
+ /// A base membership provider class for umbraco members (not users)
+ ///
+ public abstract class UmbracoMembershipProviderBase : MembershipProviderBase
+ {
+ protected UmbracoMembershipProviderBase()
+ {
+ //Set the defaults!
+ DefaultMemberTypeAlias = "Member";
+ }
+
+ public string DefaultMemberTypeAlias { get; protected set; }
+
+ ///
+ /// Adds a new membership user to the data source.
+ ///
+ /// The user name for the new user.
+ /// The password for the new user.
+ /// The e-mail address for the new user.
+ /// The password question for the new user.
+ /// The password answer for the new user
+ /// Whether or not the new user is approved to be validated.
+ /// The unique identifier from the membership data source for the user.
+ /// A enumeration value indicating whether the user was created successfully.
+ ///
+ /// A object populated with the information for the newly created user.
+ ///
+ protected sealed override MembershipUser PerformCreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
+ {
+ return PerformCreateUser(DefaultMemberTypeAlias, username, password, email, passwordQuestion, passwordAnswer, isApproved, providerUserKey, out status);
+ }
+
+ ///
+ /// Adds a new membership user to the data source.
+ ///
+ /// The member type alias to use when creating the member
+ /// The user name for the new user.
+ /// The password for the new user.
+ /// The e-mail address for the new user.
+ /// The password question for the new user.
+ /// The password answer for the new user
+ /// Whether or not the new user is approved to be validated.
+ /// The unique identifier from the membership data source for the user.
+ /// A enumeration value indicating whether the user was created successfully.
+ ///
+ /// A object populated with the information for the newly created user.
+ ///
+ public MembershipUser CreateUser(string memberTypeAlias, string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
+ {
+ //do the base validation first
+ base.CreateUser(username, password, email, passwordQuestion, passwordAnswer, isApproved, providerUserKey, out status);
+
+ return PerformCreateUser(memberTypeAlias, username, password, email, passwordQuestion, passwordAnswer, isApproved, providerUserKey, out status);
+ }
+
+ ///
+ /// Adds a new membership user to the data source.
+ ///
+ /// The member type alias to use when creating the member
+ /// The user name for the new user.
+ /// The password for the new user.
+ /// The e-mail address for the new user.
+ /// The password question for the new user.
+ /// The password answer for the new user
+ /// Whether or not the new user is approved to be validated.
+ /// The unique identifier from the membership data source for the user.
+ /// A enumeration value indicating whether the user was created successfully.
+ ///
+ /// A object populated with the information for the newly created user.
+ ///
+ protected abstract MembershipUser PerformCreateUser(string memberTypeAlias, string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status);
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Services/IMemberService.cs b/src/Umbraco.Core/Services/IMemberService.cs
index 87c15573c6..05bcafba38 100644
--- a/src/Umbraco.Core/Services/IMemberService.cs
+++ b/src/Umbraco.Core/Services/IMemberService.cs
@@ -8,7 +8,7 @@ namespace Umbraco.Core.Services
///
/// Defines the MemberService, which is an easy access to operations involving (umbraco) members.
///
- internal interface IMemberService : IMembershipMemberService
+ public interface IMemberService : IMembershipMemberService
{
///
/// Checks if a member with the id exists
diff --git a/src/Umbraco.Core/Services/IMembershipMemberService.cs b/src/Umbraco.Core/Services/IMembershipMemberService.cs
index 6c3027d21c..0b9ff79665 100644
--- a/src/Umbraco.Core/Services/IMembershipMemberService.cs
+++ b/src/Umbraco.Core/Services/IMembershipMemberService.cs
@@ -10,7 +10,7 @@ namespace Umbraco.Core.Services
///
/// Idea is to have this is an isolated interface so that it can be easily 'replaced' in the membership provider impl.
///
- internal interface IMembershipMemberService : IService
+ public interface IMembershipMemberService : IService
{
///
/// Checks if a member with the username exists
diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj
index 9f7bd325a1..3119ae7cf0 100644
--- a/src/Umbraco.Core/Umbraco.Core.csproj
+++ b/src/Umbraco.Core/Umbraco.Core.csproj
@@ -741,6 +741,7 @@
+
diff --git a/src/Umbraco.Tests/App.config b/src/Umbraco.Tests/App.config
index d86051cdee..0af67e158b 100644
--- a/src/Umbraco.Tests/App.config
+++ b/src/Umbraco.Tests/App.config
@@ -82,6 +82,7 @@
+
diff --git a/src/Umbraco.Tests/Membership/MembershipProviderBaseTests.cs b/src/Umbraco.Tests/Membership/MembershipProviderBaseTests.cs
index cf29e71eab..2af97b49e2 100644
--- a/src/Umbraco.Tests/Membership/MembershipProviderBaseTests.cs
+++ b/src/Umbraco.Tests/Membership/MembershipProviderBaseTests.cs
@@ -7,8 +7,13 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Security;
+using Moq;
using NUnit.Framework;
+using Umbraco.Core;
+using Umbraco.Core.Models;
using Umbraco.Core.Security;
+using Umbraco.Core.Services;
+using Umbraco.Tests.TestHelpers.Entities;
using Umbraco.Web.Security.Providers;
namespace Umbraco.Tests.Membership
@@ -20,31 +25,243 @@ namespace Umbraco.Tests.Membership
//public void Set_Default_Member_Type_On_Init()
//[Test]
- //public void Question_Answer_Is_Encrypted()
+ //public void Create_User_Already_Exists()
+ //{
+
+ //}
+
+ //[Test]
+ //public void Create_User_Requires_Unique_Email()
+ //{
+
+ //}
+
+ [Test]
+ public void Answer_Is_Encrypted()
+ {
+ IMember createdMember = null;
+ var memberType = MockedContentTypes.CreateSimpleMemberType();
+ foreach (var p in Constants.Conventions.Member.GetStandardPropertyTypeStubs())
+ {
+ memberType.AddPropertyType(p.Value);
+ }
+ var mServiceMock = new Mock();
+ mServiceMock.Setup(service => service.Exists("test")).Returns(false);
+ mServiceMock.Setup(service => service.GetByEmail("test@test.com")).Returns(() => null);
+ mServiceMock.Setup(
+ service => service.CreateMember(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()))
+ .Callback((string u, string e, string p, string m) =>
+ {
+ createdMember = new Member("test", e, u, p, memberType);
+ })
+ .Returns(() => createdMember);
+ var provider = new MembersMembershipProvider(mServiceMock.Object);
+
+ MembershipCreateStatus status;
+ provider.CreateUser("test", "test", "test", "test@test.com", "test", "test", true, "test", out status);
+
+ Assert.AreNotEqual("test", createdMember.PasswordAnswer);
+ Assert.AreEqual(provider.EncryptString("test"), createdMember.PasswordAnswer);
+ }
+
+ [Test]
+ public void Password_Encrypted_With_Salt()
+ {
+ IMember createdMember = null;
+ var memberType = MockedContentTypes.CreateSimpleMemberType();
+ foreach (var p in Constants.Conventions.Member.GetStandardPropertyTypeStubs())
+ {
+ memberType.AddPropertyType(p.Value);
+ }
+ var mServiceMock = new Mock();
+ mServiceMock.Setup(service => service.Exists("test")).Returns(false);
+ mServiceMock.Setup(service => service.GetByEmail("test@test.com")).Returns(() => null);
+ mServiceMock.Setup(
+ service => service.CreateMember(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()))
+ .Callback((string u, string e, string p, string m) =>
+ {
+ createdMember = new Member("test", e, u, p, memberType);
+ })
+ .Returns(() => createdMember);
+
+ var provider = new MembersMembershipProvider(mServiceMock.Object);
+ provider.Initialize("test", new NameValueCollection { { "passwordFormat", "Encrypted" } });
+ MembershipCreateStatus status;
+ provider.CreateUser("test", "test", "test", "test@test.com", "test", "test", true, "test", out status);
+
+ Assert.AreNotEqual("test", createdMember.Password);
+ //Assert.AreNotEqual(provider.EncryptString("test"), createdMember.PasswordAnswer);
+ string salt;
+ var encodedPassword = provider.EncryptOrHashNewPassword("test", out salt);
+ Assert.AreEqual(encodedPassword, createdMember.Password);
+ }
+
+ //[Test]
+ //public void Password_Hashed_With_Salt()
+ //{
+ // IMember createdMember = null;
+ // var memberType = MockedContentTypes.CreateSimpleMemberType();
+ // foreach (var p in Constants.Conventions.Member.GetStandardPropertyTypeStubs())
+ // {
+ // memberType.AddPropertyType(p.Value);
+ // }
+ // var mServiceMock = new Mock();
+ // mServiceMock.Setup(service => service.Exists("test")).Returns(false);
+ // mServiceMock.Setup(service => service.GetByEmail("test@test.com")).Returns(() => null);
+ // mServiceMock.Setup(
+ // service => service.CreateMember(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()))
+ // .Callback((string u, string e, string p, string m) =>
+ // {
+ // createdMember = new Member("test", e, u, p, memberType);
+ // })
+ // .Returns(() => createdMember);
+
+ // var provider = new MembersMembershipProvider(mServiceMock.Object);
+ // provider.Initialize("test", new NameValueCollection { { "passwordFormat", "Hashed" } });
+ // MembershipCreateStatus status;
+ // provider.CreateUser("test", "test", "test", "test@test.com", "test", "test", true, "test", out status);
+
+ // Assert.AreNotEqual("test", createdMember.Password);
+ // Assert.AreNotEqual(provider.EncryptString("test"), createdMember.PasswordAnswer);
+ // string salt;
+ // var encodedPassword = provider.EncryptOrHashNewPassword("test", out salt);
+ // Assert.AreEqual(encodedPassword, createdMember.Password);
+ //}
+
+ //[Test]
+ //public void Password_Encrypted_Validated_With_Salt()
+
+ //[Test]
+ //public void Password_Encrypted_Validated_With_Salt()
+
}
[TestFixture]
public class MembershipProviderBaseTests
{
- //[Test]
- //public void Change_Password_Base_Validation()
- //[Test]
- //public void ChangePasswordQuestionAndAnswer_Base_Validation()
- //[Test]
- //public void CreateUser_Base_Validation()
+ [Test]
+ public void Change_Password_Without_AllowManuallyChangingPassword_And_No_Pass_Validation()
+ {
+ var providerMock = new Mock() { CallBase = true };
+ providerMock.Setup(@base => @base.AllowManuallyChangingPassword).Returns(false);
+ var provider = providerMock.Object;
- //[Test]
- //public void GetPassword_Base_Validation()
+ Assert.Throws(() => provider.ChangePassword("test", "", "test"));
+ }
- //[Test]
- //public void ResetPassword_Base_Validation()
+ [Test]
+ public void Change_Password_With_AllowManuallyChangingPassword_And_Invalid_Creds()
+ {
+ var providerMock = new Mock() { CallBase = true };
+ providerMock.Setup(@base => @base.AllowManuallyChangingPassword).Returns(false);
+ providerMock.Setup(@base => @base.ValidateUser("test", "test")).Returns(false);
+ var provider = providerMock.Object;
+
+ Assert.IsFalse(provider.ChangePassword("test", "test", "test"));
+
+ }
+
+ [Test]
+ public void ChangePasswordQuestionAndAnswer_Without_RequiresQuestionAndAnswer()
+ {
+ var providerMock = new Mock() { CallBase = true };
+ providerMock.Setup(@base => @base.RequiresQuestionAndAnswer).Returns(false);
+ var provider = providerMock.Object;
+
+ Assert.Throws(() => provider.ChangePasswordQuestionAndAnswer("test", "test", "test", "test"));
+ }
+
+ [Test]
+ public void ChangePasswordQuestionAndAnswer_Without_AllowManuallyChangingPassword_And_Invalid_Creds()
+ {
+ var providerMock = new Mock() { CallBase = true };
+ providerMock.Setup(@base => @base.RequiresQuestionAndAnswer).Returns(true);
+ providerMock.Setup(@base => @base.AllowManuallyChangingPassword).Returns(false);
+ providerMock.Setup(@base => @base.ValidateUser("test", "test")).Returns(false);
+ var provider = providerMock.Object;
+
+ Assert.IsFalse(provider.ChangePasswordQuestionAndAnswer("test", "test", "test", "test"));
+ }
+
+ [Test]
+ public void CreateUser_Not_Whitespace()
+ {
+ var providerMock = new Mock() {CallBase = true};
+ var provider = providerMock.Object;
+
+ MembershipCreateStatus status;
+ var result = provider.CreateUser("", "", "test@test.com", "", "", true, "", out status);
+
+ Assert.IsNull(result);
+ Assert.AreEqual(MembershipCreateStatus.InvalidUserName, status);
+ }
+
+ [Test]
+ public void CreateUser_Invalid_Question()
+ {
+ var providerMock = new Mock() { CallBase = true };
+ providerMock.Setup(@base => @base.RequiresQuestionAndAnswer).Returns(true);
+ var provider = providerMock.Object;
+
+ MembershipCreateStatus status;
+ var result = provider.CreateUser("test", "test", "test@test.com", "", "", true, "", out status);
+
+ Assert.IsNull(result);
+ Assert.AreEqual(MembershipCreateStatus.InvalidQuestion, status);
+ }
+
+ [Test]
+ public void CreateUser_Invalid_Answer()
+ {
+ var providerMock = new Mock() { CallBase = true };
+ providerMock.Setup(@base => @base.RequiresQuestionAndAnswer).Returns(true);
+ var provider = providerMock.Object;
+
+ MembershipCreateStatus status;
+ var result = provider.CreateUser("test", "test", "test@test.com", "test", "", true, "", out status);
+
+ Assert.IsNull(result);
+ Assert.AreEqual(MembershipCreateStatus.InvalidAnswer, status);
+ }
+
+ [Test]
+ public void GetPassword_Without_EnablePasswordRetrieval()
+ {
+ var providerMock = new Mock() { CallBase = true };
+ providerMock.Setup(@base => @base.EnablePasswordRetrieval).Returns(false);
+ var provider = providerMock.Object;
+
+ Assert.Throws(() => provider.GetPassword("test", "test"));
+ }
+
+ [Test]
+ public void GetPassword_With_Hashed()
+ {
+ var providerMock = new Mock() { CallBase = true };
+ providerMock.Setup(@base => @base.EnablePasswordRetrieval).Returns(true);
+ providerMock.Setup(@base => @base.PasswordFormat).Returns(MembershipPasswordFormat.Hashed);
+ var provider = providerMock.Object;
+
+ Assert.Throws(() => provider.GetPassword("test", "test"));
+ }
+
+ [Test]
+ public void ResetPassword_Without_EnablePasswordReset()
+ {
+ var providerMock = new Mock() { CallBase = true };
+ providerMock.Setup(@base => @base.EnablePasswordReset).Returns(false);
+ var provider = providerMock.Object;
+
+ Assert.Throws(() => provider.ResetPassword("test", "test"));
+ }
[Test]
public void Sets_Defaults()
{
- var provider = new TestProvider();
+ var providerMock = new Mock() { CallBase = true };
+ var provider = providerMock.Object;
provider.Initialize("test", new NameValueCollection());
Assert.AreEqual("test", provider.Name);
@@ -65,7 +282,8 @@ namespace Umbraco.Tests.Membership
[Test]
public void Throws_Exception_With_Hashed_Password_And_Password_Retrieval()
{
- var provider = new TestProvider();
+ var providerMock = new Mock() { CallBase = true };
+ var provider = providerMock.Object;
Assert.Throws(() => provider.Initialize("test", new NameValueCollection()
{
@@ -125,88 +343,5 @@ namespace Umbraco.Tests.Membership
Assert.AreEqual(salt, initSalt);
}
- private class TestProvider : MembershipProviderBase
- {
- public override void UpdateUser(MembershipUser user)
- {
- throw new NotImplementedException();
- }
-
- public override bool ValidateUser(string username, string password)
- {
- throw new NotImplementedException();
- }
-
- public override bool UnlockUser(string userName)
- {
- throw new NotImplementedException();
- }
-
- public override MembershipUser GetUser(object providerUserKey, bool userIsOnline)
- {
- throw new NotImplementedException();
- }
-
- public override MembershipUser GetUser(string username, bool userIsOnline)
- {
- throw new NotImplementedException();
- }
-
- public override string GetUserNameByEmail(string email)
- {
- throw new NotImplementedException();
- }
-
- public override bool DeleteUser(string username, bool deleteAllRelatedData)
- {
- throw new NotImplementedException();
- }
-
- public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords)
- {
- throw new NotImplementedException();
- }
-
- public override int GetNumberOfUsersOnline()
- {
- throw new NotImplementedException();
- }
-
- public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords)
- {
- throw new NotImplementedException();
- }
-
- public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords)
- {
- throw new NotImplementedException();
- }
-
- protected override bool PerformChangePassword(string username, string oldPassword, string newPassword)
- {
- throw new NotImplementedException();
- }
-
- protected override bool PerformChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer)
- {
- throw new NotImplementedException();
- }
-
- protected override MembershipUser PerformCreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
- {
- throw new NotImplementedException();
- }
-
- protected override string PerformGetPassword(string username, string answer)
- {
- throw new NotImplementedException();
- }
-
- protected override string PerformResetPassword(string username, string answer, string generatedPassword)
- {
- throw new NotImplementedException();
- }
- }
-
}
}
diff --git a/src/Umbraco.Web/Security/Providers/MembersMembershipProvider.cs b/src/Umbraco.Web/Security/Providers/MembersMembershipProvider.cs
index 5e263f76a4..e4fbda1d08 100644
--- a/src/Umbraco.Web/Security/Providers/MembersMembershipProvider.cs
+++ b/src/Umbraco.Web/Security/Providers/MembersMembershipProvider.cs
@@ -6,6 +6,7 @@ using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
+using System.Web.Configuration;
using System.Web.Hosting;
using System.Web.Security;
using Umbraco.Core;
@@ -30,6 +31,15 @@ namespace Umbraco.Web.Security.Providers
get { return _memberService ?? (_memberService = ApplicationContext.Current.Services.MemberService); }
}
+ public MembersMembershipProvider()
+ {
+ }
+
+ internal MembersMembershipProvider(IMemberService memberService)
+ {
+ _memberService = memberService;
+ }
+
public string ProviderName
{
get { return "MembersMembershipProvider"; }
@@ -80,7 +90,7 @@ namespace Umbraco.Web.Security.Providers
// This is allowed based on the overridden AllowManuallyChangingPassword option.
// in order to support updating passwords from the umbraco core, we can't validate the old password
- var m = _memberService.GetByUsername(username);
+ var m = MemberService.GetByUsername(username);
if (m == null) return false;
string salt;
@@ -88,8 +98,8 @@ namespace Umbraco.Web.Security.Providers
m.Password = FormatPasswordForStorage(encodedPassword, salt);
m.LastPasswordChangeDate = DateTime.Now;
-
- _memberService.Save(m);
+
+ MemberService.Save(m);
return true;
}
@@ -113,7 +123,7 @@ namespace Umbraco.Web.Security.Providers
}
member.PasswordQuestion = newPasswordQuestion;
- member.PasswordAnswer = newPasswordAnswer;
+ member.PasswordAnswer = EncryptString(newPasswordAnswer);
MemberService.Save(member);
@@ -158,10 +168,14 @@ namespace Umbraco.Web.Security.Providers
string salt;
var encodedPassword = EncryptOrHashNewPassword(password, out salt);
- var member = MemberService.CreateMember(email, username, encodedPassword, memberTypeAlias);
+ var member = MemberService.CreateMember(
+ email,
+ username,
+ FormatPasswordForStorage(encodedPassword, salt),
+ memberTypeAlias);
member.PasswordQuestion = passwordQuestion;
- member.PasswordAnswer = passwordAnswer;
+ member.PasswordAnswer = EncryptString(passwordAnswer);
member.IsApproved = isApproved;
member.LastLoginDate = DateTime.Now;
member.LastPasswordChangeDate = DateTime.Now;
@@ -289,9 +303,9 @@ namespace Umbraco.Web.Security.Providers
throw new ProviderException("The supplied user is not found");
}
- //TODO: We need to encrypt the answer here to match against the encrypted answer in the database
+ var encAnswer = EncryptString(answer);
- if (RequiresQuestionAndAnswer && m.PasswordAnswer != answer)
+ if (RequiresQuestionAndAnswer && m.PasswordAnswer != encAnswer)
{
throw new ProviderException("Incorrect password answer");
}
@@ -301,6 +315,15 @@ namespace Umbraco.Web.Security.Providers
return decodedPassword;
}
+ internal string EncryptString(string str)
+ {
+ var bytes = Encoding.Unicode.GetBytes(str);
+ var password = new byte[bytes.Length];
+ Buffer.BlockCopy(bytes, 0, password, 0, bytes.Length);
+ var encBytes = EncryptPassword(password, MembershipPasswordCompatibilityMode.Framework40);
+ return Convert.ToBase64String(encBytes);
+ }
+
///
/// Gets information from the data source for a user. Provides an option to update the last-activity date/time stamp for the user.
///
@@ -395,16 +418,16 @@ namespace Umbraco.Web.Security.Providers
throw new ProviderException("The member is locked out.");
}
- //TODO: We need to encrypt the answer here to match against the encrypted answer in the database
+ var encAnswer = EncryptString(answer);
- if (RequiresQuestionAndAnswer && m.PasswordAnswer != answer)
+ if (RequiresQuestionAndAnswer && m.PasswordAnswer != encAnswer)
{
throw new ProviderException("Incorrect password answer");
}
string salt;
var encodedPassword = EncryptOrHashNewPassword(generatedPassword, out salt);
- m.Password = encodedPassword;
+ m.Password = FormatPasswordForStorage(encodedPassword, salt);
m.LastPasswordChangeDate = DateTime.Now;
MemberService.Save(m);