.net 6, Identity Core, using emails for usernames, MVC
The user is created in code with
var user = new DBModels.ApplicationUser
{
UserName = "Valid Email",
Email = "Valid Email",
Approved = true,
LockoutEnabled = false,
PhoneNumber = "(123) 456-7890",
FirstName = "John",
LastName = "Doe",
EmailConfirmed = true,
CreationDate = DateTime.Now,
RenewalDate = DateTime.Now.AddYears(50),
ScreenName = "John.Doe",
State = "AK",
Avatar = "/assets/user.png"
};
var userResult = _userManager.CreateAsync(user, "Password123!").Result;
var roleResult = _userManager.AddToRoleAsync(user, "Default").Result;
I know the email/password pair I'm trying to compare is valid because I can login to the web app just fine. I am trying to create an API controller for a mobile companion app and need to verify the email/password pair in the login method from the app. The API controller login method looks like:
public async Task<IActionResult> Login(string email, string password)
{
try
{
var curUser = await UserManager.FindByEmailAsync(email);
if (curUser != null)
{
var verifyPassword = await UserManager.CheckPasswordAsync(curUser, password);
if (verifyPassword) .....
No matter what I do, when trying to verify a password, the check is always false. I find the correct user just fine but the password comparison is always false. Any advice?
So sorry ... this works perfectly fine when you enter the actually correct password in your test code!
Related
In the ExternalLoginConfirmation method of the AccountController.cs a new user will be created according to user = new ApplicationUser { UserName = model.Email, Email = model.Email }.
I want to create the new user prepending the login provider name in the UserName property:
user = new ApplicationUser { UserName = provider ?? model.Email + model.Email, Email = model.Email };
My idea is to try to do like that:
var loginProviders = _signInManager.GetExternalAuthenticationSchemes().ToList();
var provider = loginProviders[index].DisplayName.ToString();
How can I select index to return the used loginProvider?
Unfortunately var provider = loginProviders.DisplayName.ToString(); does not work.
For Authentication I'm using
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
});
app.UseGoogleAuthentication(new GoogleOptions()
{
ClientId = Configuration["Authentication:Google:ClientId"],
ClientSecret = Configuration["Authentication:Google:ClientSecret"]
});
app.UseMicrosoftAccountAuthentication(new MicrosoftAccountOptions()
{
ClientId = Configuration["Authentication:Microsoft:ClientId"],
ClientSecret = Configuration["Authentication:Microsoft:ClientSecret"]
});
app.UseFacebookAuthentication(new FacebookOptions()
{
AppId = Configuration["Authentication:Facebook:AppId"],
AppSecret = Configuration["Authentication:Facebook:AppSecret"]
});
While testing my web site I use my credential.
Letting UserName = model.Email, Email = model.Email turns out to give an error.
I can use the same Email, by setting up
services.AddIdentity<ApplicationUser, IdentityRole>(opts => {
opts.User.RequireUniqueEmail = false;
})
But I can not have the same UserName
Any idea?
Thanks a lot.
In the meantime I've found the solution.
In the method
public async Task<IActionResult> ExternalLoginConfirmation(ExternalLoginConfirmationViewModel model, string returnUrl = null)
you can get the information about the user from the external login provider by calling
var info = await _signInManager.GetExternalLoginInfoAsync();
You can then add a new user by simply prepending info.LoginProvider in the UserName field like that
var user = new ApplicationUser { UserName = info.LoginProvider + model.Email, Email = model.Email };
Doing that you can use your credentials (you email address) to test multiple login provides avoiding conflics while trying to insert in the dbo.AspNetUsers identical UserName fields.
Hope it helps!
In my ASP.MVC site user have additional field email, so now i want to reset password by sending token to email address like this:
var token = WebSecurity.GeneratePasswordResetToken(model.Pesel);
var userID = WebSecurity.GetUserIdFromPasswordResetToken(token);
var callbackUrl = Url.Action("ResetPassword", "Account", new { UserId = userID, code = token }, protocol: Request.Url.Scheme);
But the problem is how can I get email address that I have added to User table?
It will be nice to create method like:
WebSecurity.GetUserIdFromEmailResetToken
Why don't you? Such as
public UserEmailTable GetUserIdFromEmailResetToken(int userEmailId)
{
return _db.UserEmail.Where(s => s.UserEmailId == userEmailId)
}
this allows you to get the user email by Id.
I have an MVC 5 application with .NET Identity 2.0. I need to migrate users from the clients legacy database. I am going to use an INSERT statement to insert them into the SQL Server tables (ASPNetUsers, ASPNetUserROles etc).
The problem is I want to insert a temporary password (firstname+lastname). Then I will separately send them an email and ask them to log in and change the password on the first log in.
How do I insert a hashed password (based on firstname+lastname) through a SQL Insert statement into the table?
Thanks,
Sanjeev
Wrote the following code. It seems to work. The first part uses the UserManager methods and the second part inserts the person into my own db tables.
Please comment if this is the right approach!
public ActionResult Seed()
{
string lastname;
string firstname;
string email;
string password;
lastname = "LastNAme";
firstname = "FirstName";
email = "Email#gmail.com";
password = "TempPassword";
var user = new ApplicationUser { UserName = email, Email = email };
var result = UserManager.Create(user, password);
UserManager.AddToRole(user.Id, "User");
var person = new Person()
{
UserName = user.UserName,
UserId = user.Id,
LastName = lastname,
FirstName = firstname,
Email = email
};
db.People.Add(person);
db.SaveChanges();
}
I'm trying to find the user associated with the currently logged on user:
public ActionResult Root(string path)
{
var id = User.Identity.GetUserId(); //This works
var currentUser = manager.FindById(id); //This returns null
return View(db.Folders.ToList()
.Where(folder => folder.User.Id == currentUser.Id)
.Where(folder => folder.Path == path));
}
This only works if I do not use the indicated part in my seed method. If I do execute this part, manager.FindById() returns null.
protected override void Seed(ApplicationDbContext context)
{
if (context == null)
{
throw new ArgumentNullException("context", "Context must not be null.");
}
const string UserName = "admin#tad.com";
const string RoleName = "Admin";
var userRole = new IdentityRole { Name = RoleName, Id = Guid.NewGuid().ToString() };
context.Roles.Add(userRole);
var hasher = new PasswordHasher();
var user = new ApplicationUser
{
UserName = UserName,
PasswordHash = hasher.HashPassword("123456"),
Email = "admin#tad.com",
EmailConfirmed = true,
SecurityStamp = Guid.NewGuid().ToString()
};
user.Roles.Add(new IdentityUserRole { RoleId = userRole.Id, UserId = user.Id });
context.Users.Add(user);
//If I leave this part out, there are no issues.
new List<Folder>
{
new Folder{Name = "Test", Path = "", User = user},
new Folder{Name = "Bla", Path = "Test", User = user},
new Folder{Name = "Lala", Path = "Test/Bla", User = user}
}.ForEach(f => context.Folders.Add(f));
context.SaveChanges();
base.Seed(context);
}
EDIT: Starting to narrow it down. If I relog my user, everything works just fine. The active user during testing remains logged in from the previous debugging session.
I see the problem:
The active user during testing remains logged in from the previous debugging session.
Authentication cookie contains the Guid for userId from the previous session. And if you re-create users every time, guid for userId is getting changed in the database and does not match for whatever Id is stored in the cookie. So either don't re-create users on every debug session, or kill your cookies on every debug.
I know that we can initialise the database when doing a Entity Framework migration using the Seed method, as below.
protected override void Seed(CraigSheppardSoftware.Models.ApplicationDbContext context)
{
context.Users.AddOrUpdate(p => p.UserName,
new ApplicationUser { FullName = "System Admin", UserName="CssOp", UserRole = UserType.SystemAdmin,
LandlinePhone=new ComplexDataTypes.PhoneNumber(), MobilePhone= new ComplexDataTypes.PhoneNumber()
} );
context.SaveChanges();
}
The problem is that the when I try to use that user to login with, I can't as I dont know what the password is.
There is no password field on the database. I notice that there is a PasswordHash field and suspect that this is an encrypted password. How do I create a password hash ?
Use UserManager to create / update the user.
var manager = new UserManager<ApplicationUser>(
new UserStore<ApplicationUser>(context));
var user = manager.Find("CssOp", "ThePassword");
if (user == null)
{
user = new ApplicationUser { UserName = "CssOp", Email = "email#mail.com" };
manager.Create(user, "ThePassword");
}
else
{
user.Email = "newemail#mail.com";
manager.Update(user);
}