I am trying to register a new user and also understand how to get the new userID so i can start creating my own user tables with a userID mapping to the asp.net membership user table.
Below is my code:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Register(string userName, string email, string position, string password, string confirmPassword)
{
ViewData["PasswordLength"] = MembershipService.MinPasswordLength;
ViewData["position"] = new SelectList(GetDeveloperPositionList());
if (ValidateRegistration(userName, email, position, password, confirmPassword))
{
// Attempt to register the user
MembershipCreateStatus createStatus = MembershipService.CreateUser(userName, password, email);
if (createStatus == MembershipCreateStatus.Success)
{
FormsAuth.SignIn(userName, false /* createPersistentCookie */);
return RedirectToAction("Index", "Home");
}
else
{
ModelState.AddModelError("_FORM", ErrorCodeToString(createStatus));
}
}
// If we got this far, something failed, redisplay form
return View();
}
I've done some research and many sites inform me to use Membership.GetUser().ProviderUserKey; but this throws an error as Membership is NULL.
I placed this line of code just above "return RedirectToAction("Index", "Home");" within the if statement.
Please can someone advise me on this...
Thanks in advance
Create the user using the MembershipProvider, this will return a MembershipUser instance. Where you can access the ProviderKey to access the Id.
MembershipCreateStatus status;
MembershipUser user = Membership.Provider.CreateUser(userName, password, email, null, null, true, null, out status);
if (status == MembershipCreateStatus.Success)
{
object key = user.ProviderUserKey;
}
This will retrieve the ProviderKey:
if (createStatus == MembershipCreateStatus.Success)
{
FormsAuth.SignIn(userName, false /* createPersistentCookie */);
MembershipUser newUser = Membership.GetUser(model.UserName);
string key = newUser.ProviderUserKey.ToString();
return RedirectToAction("Index", "Home");
}
Related
Below is my login function, I want to change the following:
differentiate between admin login and user login to show different page layouts
get the user's first name and second name according to the login user
please how can I do that any suggestion or examples?
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login(Customers customer)
{
if (ModelState.IsValid)
{
var user = await _context.Customers.SingleOrDefaultAsync(m => m.Email == customer.Email && m.Password == customer.Password);
if (user != null)
{
return RedirectToAction("Account", "Account");
}
else
{
ViewBag.error = "Login Failed";
return RedirectToAction("Login");
}
}
else
{
return RedirectToAction("Index", "Home");
}
}
You need to maintain Role column values in login table in DB.
Add values to the Role column Ex : Admin Role - 1 , User - 0
Change the login procedure to return the Role,FirstName,LastName instead of count
Select Role,Password,FirstName,LastName from Users where Username=#Username and Password=#Password
After authenticating the user(valid authentication, if password matches), redirect to the View based on the role.
if (Validate_User(Customers customer))
{
if (customer.Role == "1")
{
return View("AdminView");
}
else
{
return View("UserView");
}
ViewBag.FirstName=customer.FirstName;
ViewBag.LastName=customer.LastName;
}
else
{
//handle failed login
ViewBag.error = "Login Failed";
return RedirectToAction("Login");
}
Please refer Role Based Access
I have implemented a custom UserStore, it implements IUserStore<DatabaseLogin, int> and IUserPasswordStore<DatabaseLogin, int>.
My Login action method is as below:
if (ModelState.IsValid)
{
if (Authentication.Login(user.Username, user.Password))
{
DatabaseLogin x = await UserManager.FindAsync(user.Username, user.Password);
DatabaseLogin Login = Authentication.FindByName(user.Username);
if (Login != null)
{
ClaimsIdentity ident = await UserManager.CreateIdentityAsync(Login,
DefaultAuthenticationTypes.ApplicationCookie);
AuthManager.SignOut();
AuthManager.SignIn(new AuthenticationProperties
{
IsPersistent = false
}, ident);
return RedirectToAction("Index", "Home");
}
}
else
{
ModelState.AddModelError("", "Invalid Login");
}
}
return View();
In the custom authentication class that I wrote, Authentication, I have a Login method that works fine, also FindByName method returns an app user. But if I try to SignIn with that login, the user isn't recognized as authenticated and HttpContext.User.Identity is always null, so I imagine that I have to try UserManager.FindAsync.
This method calls FindByNameAsync and GetPasswordHashAsync, and it always return null.
public Task<DatabaseLogin> FindByNameAsync(string userName)
{
if (string.IsNullOrEmpty(userName))
throw new ArgumentNullException("userName");
return Task.FromResult<DatabaseLogin>(Authentication.FindByName(userName));
}
public Task<string> GetPasswordHashAsync(DatabaseLogin user)
{
if (user == null)
throw new ArgumentNullException("user");
return Task.FromResult<string>(user.Password);
}
And the Authentication.FindByName
public static DatabaseLogin FindByName(string name)
{
string GetUserQuery = string.Format(
"USE db;SELECT principal_id AS id, name as userName, create_date AS CreateDate, modify_date AS modifyDate FROM sys.database_principals WHERE type='S' AND authentication_type = 1 AND name = '{0}'"
, name);
DatabaseLogin user;
using (var db = new EFDbContext())
{
user = db.Database.SqlQuery<DatabaseLogin>(GetUserQuery).FirstOrDefault();
}
user.Password = Convert.ToBase64String(Encoding.ASCII.GetBytes("pass"));
return user;
}
As you can see I'm using database users, I'm not sure how I can retrieve a hashed password for them. For now, I'm just storing the Base65 of the correct password!
I have no idea where I'm going wrong, any guidance is welcome.
Short answer: nothing's wrong. User is authenticated in other action methods, but apparently not in the current action method.
This is the process that I followed, maybe it will help you debug your app.
After reading the source code, FindAsync first calls FindByNameAsync, followed by CheckPasswordAsync which references VerifyPasswordAsync. So it should be fine If I could override VerifyPasswordAsync.
I created a custom password hasher that implements IPasswordHasher, and registered it in the create method of my UserManager like this:
manager.PasswordHasher = new DbPasswordHasher();
So by now, I can get my user from UserManager.FindAsync, but it turned out that it doesn't matter where you get the user since HttpContext.User.Identity is still null! My mistake was that I didn't notice the user isn't authenticated in the current action, in other action methods it works as expected!
asp.net mvc 4 application using forms authentication. I'm trying to add roles to users when registered. I'm getting a error 500 from the server. so I put a break point on the register action. its jumping out on the Membership.CreateUser method, the username and password are ok. any ideas what could be wrong. and I know the if model state check shouldnt be there.
public ActionResult Register(string username, string password)
{
if (ModelState.IsValid)
{
// Attempt to register the user
MembershipCreateStatus Status;
Membership.CreateUser(username,password,null, null, null, true, null, out Status);
//WebSecurity.CreateUserAndAccount(username, password);
if (Status == MembershipCreateStatus.Success)
{
Roles.AddUserToRole(username, "Mechanic");
FormsAuthentication.SetAuthCookie(username, false);
return RedirectToAction("Index", "Home");
}
else
{
ModelState.AddModelError("", ErrorCodeToString(Status));
}
return RedirectToAction("Mechanics", "Mechanic");
}
// If we got this far, something failed, redisplay form
return View();
}
You could put a try/catch around this method call and inspect the exception:
try
{
Membership.CreateUser(username,password,null, null, null, true, null, out Status);
}
catch (Exception ex)
{
... put the breakpoint here and inspect the exception
}
I am using the standard Simple Membership model for login via forms in my application. I would like to provide the possibility to login via AD as an alternative.
When logging in via AD, the process should be as follows:
Check that AD authenticates the user, but do not use the information for the principal.
Check if any local user exists with the provided Active Directory username (I have a property on my UserProfile model named ActiveDirectoryID).
If it exists, perform a local login using the local username for this UserProfile.
The problem: I cannot retrieve the local password, so in order to login locally after AD authentication, I need to be able to force the login without the password.
I've considered the following strategies:
Create an extension method for Websecurity to allow Websecurity.Login(string username)
Somehow set the logged in user manually, without implicating Websecurity.
Is this doable / feasible? Is it possible for the framework to create the necessary auth cookie without the plaintext password? And how would I do this?
SOLUTION:
This ended being the correct solution:
public ActionResult ActiveDirectoryLogin(LoginModel model, string returnUrl)
{
if (ModelState.IsValid)
{
try
{
DirectoryEntry entry = new DirectoryEntry("LDAP://DC=MyIntranet,DC=MyCompany,DC=com", model.UserName, model.Password);
object NativeObject = entry.NativeObject;
var internalUser = db.UserProfiles.Where(x => x.ActiveDirectoryID == model.UserName).SingleOrDefault();
if (internalUser != null)
{
FormsAuthentication.SetAuthCookie(internalUser.UserName, model.RememberMe);
return RedirectToLocal(returnUrl);
}
}
catch (DirectoryServicesCOMException)
{
// No user existed with the given credentials
}
catch (InvalidOperationException)
{
// Multiple users existed with the same ActiveDirectoryID in the database. This should never happen!
}
}
return RedirectToAction("Login");
}
This is all that the Websecurity.Login method does:
public static bool Login(string userName, string password, bool persistCookie = false)
{
WebSecurity.VerifyProvider();
bool flag = Membership.ValidateUser(userName, password);
if (flag)
{
FormsAuthentication.SetAuthCookie(userName, persistCookie);
}
return flag;
}
You can write your own method that authenticates against AD and then looks up the user name and the does sets the auth cookie something like:
public static bool MyLogin(string userName, string password, bool persistCookie = false)
{
bool flag = CheckADUser(userName, password);
if (flag)
{
string mappedUsername = GetMappedUser(userName);
if(mappedUsername != "")
{
FormsAuthentication.SetAuthCookie(userName, persistCookie);
}
else
{
flag = false;
}
}
return flag;
}
Hope this helps.
public ActionResult Register(RegisterModel RegisterModel, string returnUrl)
{
if (ModelState.IsValid)
{
// Attempt to register the user
MembershipCreateStatus createStatus;
System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
Byte[] Password = encoding.GetBytes(RegisterModel.Password);
var EncryptedPass = MembershipProvider.EncryptPassword(Password);
Membership.CreateUser(RegisterModel.UserName, RegisterModel.Password, RegisterModel.Email, null, null, true, null, out createStatus);
if (createStatus == MembershipCreateStatus.Success)
{
FormsAuthentication.SetAuthCookie(RegisterModel.UserName, false /* createPersistentCookie */);
return Redirect(returnUrl ?? Url.Action("Index", "Education"));
}
else
{
ModelState.AddModelError("", ErrorCodeToString(createStatus));
}
}
// If we got this far, something failed, redisplay form
return View(RegisterModel);
}
Trying to encrypt a password before storing it in the database using the EncryptPassword method and then Dycrypt it with MembershipProvider.DecryptPassword Method but getting a 'Is inaccessible due to its protection level' error warning.
Because both MembershipProvider.EncryptPassword and MembershipProvider.DecryptPassword method are protected.
So, You will not be able to access them out side the class or its derived class definition.
And while creating any user via Membership.CreateUser it automatically encrypt the password.