A very simple membership class library for your .NET/C# application with Entity Framework 6 Code-First.
User.cs
Properties
Property | Type | Description |
---|---|---|
Id | int | A database-generated unique number which identifies the user |
string | Unique username or email | |
Password Hash/Salt | byte[] | Encrypted password data [read only] |
LastLogin | Nullable DateTime | The last successful login of the user |
Roles | string | Comma-separated role(s) of a user |
UserProfiles | any | You can add more user profile data e.g. FirstName, LastName, BirthDate, Gender, Phone, Address, etc |
Public Static Methods
Method | Type | Description |
---|---|---|
Create(User, strUserPassword, optional requiresActivation) | User | Creates new User. Return null if registration fails. requiresActivation set to true needs account be activated by the Administrator |
Authenticate(userEmail, userPassword) | bool | Returns true if login is valid |
ChangePassword(userName, currentPassword, newPassword) | User | Change user password |
GetAll() | List<User> | Returns all users |
GetAllUsersInRole(rolename) | List<User> | Returns all users belong to a role |
GetUserById(id) | User | Returns User by Id |
GetUserByEmail(email) | User | Returns User by email or username |
GetCurrentUser() | User | Returns currently logged-in user |
GetUserRoles(id or email) | string[] | Returns the roles of user as string array |
Deactivate() | User | Disables user from logging in |
Activate() | User | Re-enables user |
Setup
Copy paste User.cs in your project and set the username and password for the auto-generated default administrator. The code below automatically creates user with username, password, and role set to "admin".
private const string DEFAULT_ADMIN_LOGIN = "admin";
Then change the type of _db instance to your app DbContext.
private static MyDbContext _db = new MyDbContext();
In your DbContext class, add database mapping to User class
public DbSet<User> Users { get; set; }
Execute update-database
Usage
Sign up
public void Register()
{
if (txtPassword.Text == txtVerifyPass.Text)
{
var newUser = new User();
newUser.Email = txtEmail.Text;
newUser.FirstName = txtFirstName.Text;
newUser.LastName = txtLastName.Text;
newUser.Phone = txtPhone.Text;
var user = User.Create(newUser, txtPassword.Text);
if (user != null)
{
MessageBox.Show("You have successfully registered. \nUserId: " + user.Id);
// Logic for successful registration...
}
else
MessageBox.Show("Registration failed.");
}
else
MessageBox.Show("Password is not the same.");
}
Sign in
public void Login()
{
var valid = User.Authenticate(txtLoginEmail.Text, txtLoginPassword.Text);
if(valid)
{
var currentUser = User.GetCurrentUser();
MessageBox.Show("Hello " + currentUser.UserName + ", you have successfully logged in to the system.");
// Do what you want to do as login is successful...
}
else
MessageBox.Show("Invalid email and/or password.");
}
User.cs Complete Code
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
[Table("_Users")]
public partial class User
{
// Change this to your desired default admin login and password
public const string DEFAULT_ADMIN_LOGIN = "admin";
// Change this to your DbContext class
private static YourDbContext _db = new YourDbContext();
#region UserAccountRepository
public int Id { get; set; }
//Login info
[Required]
[StringLength(254)]
public string UserName { get; set; }
public byte[] PasswordHash { get; set; }
public byte[] PasswordSalt { get; set; }
public DateTime CreatedOn { get; set; }
public DateTime? LastLogin { get; set; }
public bool IsActive { get; set; }
public string Roles { get; set; } // comma-separated
private static User currentUser = null;
public static bool Authenticate(string userName, string userPassword)
{
CreateAdmin(); // Comment out this line if you already have admin account
if (string.IsNullOrWhiteSpace(userName) || string.IsNullOrWhiteSpace(userPassword))
return false;
var user = _db.Users.Where(x => x.UserName == userName.Trim().ToLower()).FirstOrDefault();
if (user == null)
return false;
if (!user.IsActive)
return false;
bool valid = VerifyPasswordHash(userPassword, user.PasswordSalt, user.PasswordHash);
if (valid)
{
user.LastLogin = DateTime.Now;
_db.Entry(user).State = System.Data.Entity.EntityState.Modified;
_db.SaveChanges();
currentUser = user; // Set current user
return true;
}
return false;
}
private static bool VerifyPasswordHash(string userPassword, byte[] passwordSalt, byte[] passwordHash)
{
// Verify PasswordHash
using (var hmac = new System.Security.Cryptography.HMACSHA512(passwordSalt))
{
var computedHash = hmac.ComputeHash(System.Text.Encoding.UTF8.GetBytes(userPassword));
for (int i = 0; i < computedHash.Length; i++)
{
if (computedHash[i] != passwordHash[i])
return false;
}
}
return true;
}
public static User Create(string userName, string userPassword, string userRoles = "", bool requiresActivation = false)
{
if (string.IsNullOrWhiteSpace(userPassword))
return null;
if (string.IsNullOrWhiteSpace(userName))
return null;
var user = new User();
user.UserName = userName.Trim().ToLower();
var userExists = _db.Users.Where(x => x.UserName == user.UserName).Count() > 0;
if (userExists)
return null;
// Create PasswordHash
using (var hmac = new System.Security.Cryptography.HMACSHA512())
{
user.PasswordSalt = hmac.Key;
user.PasswordHash = hmac.ComputeHash(System.Text.Encoding.UTF8.GetBytes(userPassword));
}
user.Roles = userRoles;
user.CreatedOn = DateTime.Now;
user.IsActive = !requiresActivation;
_db.Users.Add(user);
_db.SaveChanges();
return user;
}
private static void CreateAdmin()
{
var hasAdmin = _db.Users.Where(x => x.Roles == DEFAULT_ADMIN_LOGIN).Any();
if (!hasAdmin)
{
Create(DEFAULT_ADMIN_LOGIN, DEFAULT_ADMIN_LOGIN, DEFAULT_ADMIN_LOGIN);
}
}
public static bool ChangePassword(string userName, string userPassword = "", string newPassword = "", bool forceChange = false)
{
if (string.IsNullOrWhiteSpace(newPassword))
return false;
if (forceChange == false && string.IsNullOrWhiteSpace(userPassword))
return false;
var user = _db.Users.Where(x => x.UserName == userName.Trim()).FirstOrDefault();
if (user == null)
return false;
var validPassword = !forceChange ? VerifyPasswordHash(userPassword, user.PasswordSalt, user.PasswordHash) : true;
if (validPassword)
{
// Overwrite with new PasswordHash
using (var hmac = new System.Security.Cryptography.HMACSHA512())
{
user.PasswordSalt = hmac.Key;
user.PasswordHash = hmac.ComputeHash(System.Text.Encoding.UTF8.GetBytes(newPassword));
}
_db.Entry(user).State = System.Data.Entity.EntityState.Modified;
_db.SaveChanges();
return true;
}
else
return false;
}
public static List<User> GetAll()
{
var users = _db.Users.ToList();
return users;
}
public static List<User> GetAllUsersInRole(string role)
{
var users = _db.Users.ToList().Where(x => x.Roles.Split(',').Contains(role)).ToList();
return users;
}
public static User GetUserById(int userId)
{
var user = _db.Users.Find(userId);
return user;
}
public static User GetUserByUserName(string userName)
{
var user = _db.Users.Where(x => x.UserName.ToLower() == userName.ToLower()).FirstOrDefault();
return user;
}
public static User GetCurrentUser()
{
if(currentUser != null)
{
currentUser.PasswordHash = null;
currentUser.PasswordSalt = null;
}
return currentUser;
}
public static string[] GetUserRoles(int userId)
{
var user = GetUserById(userId);
if (user != null)
return user.Roles.Split(',');
else
return new string[] { string.Empty };
}
public static string[] GetUserRoles(string userName)
{
var user = GetUserByUserName(userName);
return GetUserRoles(user.Id);
}
public static User Deactivate(string userName)
{
var user = _db.Users.Where(x => x.UserName == userName).FirstOrDefault();
if (user != null)
{
user.IsActive = false;
_db.Entry(user).State = System.Data.Entity.EntityState.Modified;
_db.SaveChanges();
return user;
}
else
return null;
}
public static User Activate(string userName)
{
var user = _db.Users.Where(x => x.UserName == userName).FirstOrDefault();
if (user != null)
{
user.IsActive = true;
_db.Entry(user).State = System.Data.Entity.EntityState.Modified;
_db.SaveChanges();
return user;
}
else
return null;
}
#endregion
}