Full code

CustomMembershipProvider.cs

using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Configuration.Provider;
using System.Linq;
using System.Web.Security;
using Telerik.Sitefinity.Data;
using Telerik.Sitefinity.Localization;
using Telerik.Sitefinity.Model;
using Telerik.Sitefinity.Security;
using Telerik.Sitefinity.Security.Data;
using Telerik.Sitefinity.Security.Model;
using SitefinityWebApp.Model;
namespace SitefinityWebApp.Providers
{
/// <summary>
/// Custom Membership Provider class
/// </summary>
public class CustomMembershipProvider : MembershipDataProvider
{
#region Privates variables
private ManagerInfo managerInfo;
private string providerName = "CustomMembershipProvider";
private DateTime minDate = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
#endregion
#region Public variables
public const string ServiceEndpointKey = "serviceEndpoint";
#endregion
#region Properties
public CustomMembershipProviderEntities ProviderEntities { get; set; }
public string ProviderName
{
get { return this.providerName; }
set { this.providerName = value; }
}
public override string ApplicationName
{
get
{
return "/CustomMembershipProvider";
}
}
private ManagerInfo ManagerInfo
{
get
{
return this.managerInfo ?? (this.managerInfo = new ManagerInfo()
{
ProviderName = this.ProviderName,
ManagerType = "Telerik.Sitefinity.Security.UserManager",
ApplicationName = this.ApplicationName
});
}
}
/// <summary>
/// Gets the provider abilities for the current principal. E.g. which operations are supported and allowed
/// </summary>
/// <value>The provider abilities.</value>
public override ProviderAbilities Abilities
{
get
{
var abilities = new ProviderAbilities { ProviderName = Name, ProviderType = GetType().FullName };
abilities.AddAbility("GetUser", true, true);
abilities.AddAbility("AddUser", true, true);
abilities.AddAbility("DeleteUser", true, true);
abilities.AddAbility("UpdateUser", true, true);
abilities.AddAbility("ValidateUser", true, true);
abilities.AddAbility("ResetPassword", true, true);
abilities.AddAbility("GetPassword", true, true);
return abilities;
}
}
#endregion
#region Methods
/// <summary>
/// Create a new transaction
/// </summary>
/// <param name="transactionName"></param>
/// <returns></returns>
protected override object CreateNewTransaction(string transactionName)
{
return new object();
}
/// <summary>
/// Commit the transaction
/// </summary>
public override void CommitTransaction()
{
}
/// <summary>
/// Get items
/// </summary>
/// <returns></returns>
public override IEnumerable GetItems(Type itemType, string filterExpression, string orderExpression, int skip, int take, ref int? totalCount)
{
return base.GetItems(itemType, filterExpression, orderExpression, skip, take, ref totalCount);
}
/// <summary>
/// Get a new Guid
/// </summary>
/// <returns></returns>
protected override Guid GetNewGuid()
{
return Guid.NewGuid();
}
/// <summary>
/// Dispose
/// </summary>
/// <param name="disposing"></param>
protected override void Dispose(bool disposing)
{
if (!disposing)
{
base.Dispose(false);
}
}
/// <summary>
/// Check if the password is valid
/// </summary>
/// <param name="user"></param>
/// <param name="password"></param>
/// <returns></returns>
private bool CheckValidPassword(User user, string password)
{
if (user == null || !user.IsApproved || string.IsNullOrWhiteSpace(user.Password))
return false;
if (user.IsLockedOut)
{
var failedPasswordAttemptWindowStart = user.FailedPasswordAttemptWindowStart;
if (DateTime.UtcNow <= failedPasswordAttemptWindowStart.AddMinutes((double)this.PasswordAttemptWindow))
{
return false;
}
this.UnlockUser(user);
}
var passwordFormat = (MembershipPasswordFormat)user.PasswordFormat;
return this.CheckValidPassword(string.Concat(password, user.Salt), user.Password, passwordFormat);
}
/// <summary>
/// Check if the password is valid
/// </summary>
/// <param name="enteredByUser"></param>
/// <param name="original"></param>
/// <param name="passwordFormat"></param>
/// <returns></returns>
private bool CheckValidPassword(string enteredByUser, string original, MembershipPasswordFormat passwordFormat)
{
if (passwordFormat != MembershipPasswordFormat.Encrypted)
return original == this.EncodePassword(enteredByUser, null, passwordFormat);
var str = DecodePassword(original, passwordFormat);
return str == enteredByUser;
}
/// <summary>
/// Check if the EmailAddress already exits
/// </summary>
/// <param name="email"></param>
/// <returns></returns>
public override bool EmailExists(string email)
{
return this.ProviderEntities.Customers.SingleOrDefault(c => c.Email == email) != null;
}
/// <summary>
/// Check if the Username already exits
/// </summary>
/// <param name="userName"></param>
/// <returns></returns>
public override bool UserExists(string userName)
{
return this.ProviderEntities.Customers.SingleOrDefault(c => c.Username == userName) != null;
}
/// <summary>
/// Create a new Sitefinity User based on our Customer entity.
/// This method is being used by: GetUsers(), GetUser()
/// </summary>
/// <param name="customer"></param>
/// <returns></returns>
private User GetSitefinityUser(Customer customer)
{
var user = new User
{
ApplicationName = this.ApplicationName,
IsBackendUser = false,
Id = customer.CustomerId,
Email = customer.Email,
Comment = string.Empty,
LastActivityDate = DateTime.UtcNow.AddDays(-1),
LastModified = minDate,
LastLoginDate = minDate,
FailedPasswordAnswerAttemptWindowStart = minDate,
FailedPasswordAttemptWindowStart = minDate,
Password = customer.Password,
Salt = customer.Salt,
ManagerInfo = ManagerInfo,
IsApproved = customer.IsApproved,
PasswordFormat = 2
};
user.SetUserName(customer.Username);
user.SetCreationDate(DateTime.Now);
user.SetIsLockedOut(false);
user.SetLastLockoutDate(DateTime.Now);
user.SetLastPasswordChangedDate(DateTime.Now);
user.SetPasswordQuestion("question");
return user;
}
/// <summary>
/// Initializing
/// </summary>
/// <param name="providerName"></param>
/// <param name="config"></param>
/// <param name="managerType"></param>
protected override void Initialize(string providerName, NameValueCollection config, Type managerType)
{
// Initialize a new instance of our Membership Provider Entity model
this.ProviderEntities = new CustomMembershipProviderEntities();
base.Initialize(providerName, config, managerType);
}
/// <summary>
/// Get Users
/// </summary>
/// <returns></returns>
public override IQueryable<User> GetUsers()
{
var customers = this.ProviderEntities.Customers;
var users = new List<User>();
foreach (var customer in customers)
{
var user = this.GetSitefinityUser(customer);
users.Add(user);
}
return users.AsQueryable();
}
/// <summary>
/// Get User by ID
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public override User GetUser(Guid id)
{
var customer = this.ProviderEntities.Customers.SingleOrDefault(c => c.CustomerId == id);
return customer == null ? null : this.GetSitefinityUser(customer);
}
/// <summary>
/// Get User by Email
/// </summary>
/// <param name="email"></param>
/// <returns></returns>
public override User GetUserByEmail(string email)
{
var customer = this.ProviderEntities.Customers.SingleOrDefault(c => c.Email == email);
return customer == null ? null : this.GetSitefinityUser(customer);
}
/// <summary>
/// Get User by Username
/// </summary>
/// <param name="userName"></param>
/// <returns></returns>
public override User GetUser(string userName)
{
var customer = this.ProviderEntities.Customers.SingleOrDefault(c => c.Username == userName);
return customer == null ? null : this.GetSitefinityUser(customer);
}
/// <summary>
/// Create a new User.
/// </summary>
/// <param name="username"></param>
/// <param name="password"></param>
/// <param name="email"></param>
/// <param name="passwordQuestion"></param>
/// <param name="passwordAnswer"></param>
/// <param name="isApproved"></param>
/// <param name="providerUserKey"></param>
/// <param name="status"></param>
/// <returns></returns>
public override User CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
{
// First we validate the given parameters
if (!this.ValidateParameters(ref username, ref password, ref email, ref passwordQuestion, ref passwordAnswer, ref providerUserKey, out status))
{
return null;
}
// Generate a new Salt
var str = GenerateSalt();
// Get a UTC DateTime
var utcNow = DateTime.UtcNow;
// Create a new user with the parameters entered from the Sitefinity backend
var empty = this.CreateUser((Guid)providerUserKey, username);
empty.Password = this.EncodePassword(password, str, this.PasswordFormat);
empty.PasswordAnswer = this.EncodePassword(passwordAnswer.ToUpperInvariant(), null, this.PasswordFormat);
empty.Salt = str;
empty.Email = email;
empty.Comment = string.Empty;
empty.IsApproved = isApproved;
empty.FailedPasswordAttemptCount = 0;
empty.FailedPasswordAttemptWindowStart = utcNow;
empty.FailedPasswordAnswerAttemptCount = 0;
empty.FailedPasswordAnswerAttemptWindowStart = utcNow;
empty.PasswordFormat = (int)PasswordFormat;
empty.PasswordAnswer = passwordAnswer;
empty.SetPasswordQuestion(passwordQuestion);
empty.SetCreationDate(DateTime.Now);
// Add the new user to the customer table in our custom database
var customer = new Customer
{
CustomerId = empty.Id,
Username = empty.UserName,
Password = empty.Password,
Salt = empty.Salt,
IsApproved = empty.IsApproved,
Email = empty.Email
};
// Save our changes
this.ProviderEntities.Customers.Add(customer);
this.ProviderEntities.SaveChanges();
// Return our new Sitefinity User
return empty;
}
/// <summary>
/// Create a new User
/// </summary>
/// <param name="userName"></param>
/// <returns></returns>
public override User CreateUser(string userName)
{
return this.CreateUser(this.GetNewGuid(), userName);
}
/// <summary>
/// Create a new User
/// </summary>
/// <param name="id"></param>
/// <param name="userName"></param>
/// <returns></returns>
public override User CreateUser(Guid id, string userName)
{
if (id == Guid.Empty) throw new ArgumentNullException("id");
if (!string.IsNullOrEmpty(userName))
{
LoginUtils.CheckParameter(userName, true, true, true, 256, "userName");
if (this.UserExists(userName))
{
throw new ProviderException("Username already exists.");
}
}
var user = new User { ApplicationName = this.ApplicationName, Id = id };
user.SetUserName(userName);
((IDataItem)user).Provider = this;
user.ManagerInfo = ManagerInfo;
return user;
}
/// <summary>
/// Validate User
/// </summary>
/// <param name="userName"></param>
/// <param name="password"></param>
/// <returns></returns>
public override bool ValidateUser(string userName, string password)
{
return this.ValidateUser(this.GetUser(userName), password);
}
/// <summary>
/// Validate User
/// </summary>
/// <param name="user"></param>
/// <param name="password"></param>
/// <returns></returns>
public override bool ValidateUser(User user, string password)
{
if (user == null) return false;
var flag = this.CheckValidPassword(user, password);
if (flag)
{
user.LastLoginDate = DateTime.UtcNow;
user.FailedPasswordAttemptWindowStart = DateTime.UtcNow;
user.FailedPasswordAttemptCount = 0;
}
else
{
this.UpdateFailureCount(user, "password");
}
return flag;
}
/// <summary>
/// Delete User
/// </summary>
/// <param name="item"></param>
public override void Delete(User item)
{
var customer = this.ProviderEntities.Customers.SingleOrDefault(c => c.Username == item.UserName);
if (customer == null) return;
this.ProviderEntities.Customers.Remove(customer);
this.ProviderEntities.SaveChanges();
}
/// <summary>
/// Get Password
/// </summary>
/// <param name="user"></param>
/// <param name="answer"></param>
/// <returns></returns>
public override string GetPassword(User user, string answer)
{
if (!this.EnablePasswordRetrieval)
throw new ProviderException(Res.Get<ErrorMessages>().PasswordRetrievalNotEnabled);
if (user == null) throw new ProviderException(Res.Get<ErrorMessages>().MembershipUserNotFound);
var passwordFormat = (MembershipPasswordFormat)user.PasswordFormat;
if (passwordFormat == MembershipPasswordFormat.Hashed)
throw new ProviderException(Res.Get<ErrorMessages>().CannotRetrieveHashedPasswords);
if (user.IsLockedOut) throw new ProviderException(Res.Get<ErrorMessages>().MembershipUserLocked);
if (this.RequiresQuestionAndAnswer)
{
if (!string.IsNullOrEmpty(answer))
{
var passwordAnswer = user.PasswordAnswer;
if (!this.CheckValidPassword(answer.Trim().ToUpperInvariant(), passwordAnswer, passwordFormat))
{
this.UpdateFailureCount(user, "answer");
throw new ProviderException(Res.Get<ErrorMessages>().WrongPasswordAnswer);
}
}
else
{
this.UpdateFailureCount(user, "answer");
throw new ProviderException(Res.Get<ErrorMessages>().PasswordAnswerRequired);
}
}
var salt = user.Salt;
var str = DecodePassword(user.Password, passwordFormat);
return str.Left(str.Length - salt.Length);
}
/// <summary>
/// Get Password
/// </summary>
/// <param name="userName"></param>
/// <param name="answer"></param>
/// <returns></returns>
public override string GetPassword(string userName, string answer)
{
return this.GetPassword(this.GetUser(userName), answer);
}
/// <summary>
/// Get Password
/// </summary>
/// <param name="userId"></param>
/// <param name="answer"></param>
/// <returns></returns>
public override string GetPassword(Guid userId, string answer)
{
return this.GetPassword(this.GetUser(userId), answer);
}
/// <summary>
/// Reset the password
/// </summary>
/// <param name="user"></param>
/// <param name="answer"></param>
/// <returns></returns>
public override string ResetPassword(User user, string answer)
{
if (this.EnablePasswordReset)
{
if (user != null)
{
var passwordFormat = (MembershipPasswordFormat)user.PasswordFormat;
if (!user.IsLockedOut)
{
if (this.RequiresQuestionAndAnswer)
{
if (!string.IsNullOrEmpty(answer))
{
string passwordAnswer = user.PasswordAnswer;
if (!this.CheckValidPassword(answer.Trim().ToUpperInvariant(), passwordAnswer, passwordFormat))
{
this.UpdateFailureCount(user, "answer");
throw new ProviderException(Res.Get<ErrorMessages>().WrongPasswordAnswer);
}
}
else
{
this.UpdateFailureCount(user, "answer");
throw new ProviderException(Res.Get<ErrorMessages>().PasswordAnswerRequired);
}
}
string str = System.Web.Security.Membership.GeneratePassword(this.NewPasswordLength, this.MinRequiredNonAlphanumericCharacters);
string salt = user.Salt;
string str1 = this.EncodePassword(str, salt, passwordFormat);
user.SetLastPasswordChangedDate(DateTime.UtcNow);
var customer = this.ProviderEntities.Customers.SingleOrDefault(c => c.CustomerId == user.Id);
customer.Password = str1;
return str;
}
else
{
throw new ProviderException(Res.Get<ErrorMessages>().MembershipUserLocked);
}
}
else
{
throw new ProviderException(Res.Get<ErrorMessages>().MembershipUserNotFound);
}
}
else
{
throw new NotSupportedException(Res.Get<ErrorMessages>().PasswordResetIsNotEnabled);
}
}
/// <summary>
/// Reset the password
/// </summary>
/// <param name="userName"></param>
/// <param name="answer"></param>
/// <returns></returns>
public override string ResetPassword(string userName, string answer)
{
return this.ResetPassword(this.GetUser(userName), answer);
}
/// <summary>
/// Reset the password
/// </summary>
/// <param name="userId"></param>
/// <param name="answer"></param>
/// <returns></returns>
public override string ResetPassword(Guid userId, string answer)
{
return this.ResetPassword(this.GetUser(userId), answer);
}
#endregion
#region Not Supported
public override bool ChangePassword(User user, string oldPassword, string newPassword)
{
base.ChangePassword(user, oldPassword, newPassword);
MembershipPasswordFormat passwordFormat = (MembershipPasswordFormat)user.PasswordFormat;
var customer = this.ProviderEntities.Customers.SingleOrDefault(c => c.CustomerId == user.Id);
customer.Password = this.EncodePassword(newPassword, user.Salt, passwordFormat);
return true;
}
#endregion
}
}

Want to learn more?

Increase your Sitefinity skills by signing up for our free trainings. Get Sitefinity-certified at Progress Education Community to boost your credentials.

Get started with Integration Hub | Sitefinity Cloud | Sitefinity SaaS

This free lesson teaches administrators, marketers, and other business professionals how to use the Integration hub service to create automated workflows between Sitefinity and other business systems.

Web Security for Sitefinity Administrators

This free lesson teaches administrators the basics about protecting yor Sitefinity instance and its sites from external threats. Configure HTTPS, SSL, allow lists for trusted sites, and cookie security, among others.

Foundations of Sitefinity ASP.NET Core Development

The free on-demand video course teaches developers how to use Sitefinity .NET Core and leverage its decoupled architecture and new way of coding against the platform.

Was this article helpful?