get current user email in Identity - c#

I use IIdentity interface For Getting current userid and username.
so implement following Method:
private static IIdentity GetIdentity()
{
if (HttpContext.Current != null && HttpContext.Current.User != null)
{
return HttpContext.Current.User.Identity;
}
return ClaimsPrincipal.Current != null ? ClaimsPrincipal.Current.Identity : null;
}
And Add this code: _.For<IIdentity>().Use(() => GetIdentity()); in my IoC Container[structuremap].
Usage
this._identity.GetUserId();
this._identity.GetUserName();
this._identity.IsAuthenticated
Now I Want to Implement GetEmailAdress Method, How To do this?
Example
this._identity.GetEmailAdress();
When use this._identity.GetUserName(); do not get username form database.

You could do something on these lines:
public static class IdentityExtensions
{
public static string GetEmailAdress(this IIdentity identity)
{
var userId = identity.GetUserId();
using (var context = new DbContext())
{
var user = context.Users.FirstOrDefault(u => u.Id == userId);
return user.Email;
}
}
}
and then you will be able to access it like:
this._identity.GetEmailAdress();

You can get the current user in ASP.NET Identity as shown below:
ApplicationUser user = System.Web.HttpContext.Current.GetOwinContext()
.GetUserManager<ApplicationUserManager>()
.FindById(System.Web.HttpContext.Current.User.Identity.GetUserId());
//If you use int instead of string for primary key, use this:
ApplicationUser user = System.Web.HttpContext.Current.GetOwinContext()
.GetUserManager<ApplicationUserManager>()
.FindById(Convert.ToInt32(System.Web.HttpContext.Current.User.Identity.GetUserId()));
For getting custom properties from `AspNetUsers` table:
ApplicationUser user = UserManager.FindByName(userName);
string mail= user.Email;

Home Controler
[AllowAnonymous]
public ActionResult GetUserEmail()
{
try
{
var userID = User.Identity.GetUserId();
ViewBag.EmailData = db.AspNetUsers.Where(s => s.Id == userID).Select(x => x.Email).FirstOrDefault().ToString();
return Content(ViewBag.EmailData);
}
catch
{
return null;
}
}
And in View
#{
string USREmail = Html.Action("GetUserEmail", "Home").ToString();
}
You Can Show Email
#USREmail

Related

Does HttpContext.User.GetUserId always return an int using .Net Core?

Will 'GetUserId()' always return an int?
My users can't get to this controller method anonymously, they have to be logged in and have a claims principal.
var id = HttpContext.User.GetUserId();
public static int GetUserId(this ClaimsPrincipal user)
{
return int.Parse(user.FindFirst(ClaimTypes.NameIdentifier)?.Value);
}
Why I ask.
If I have a null check below my call, is it unnecessary and useless?
var id = HttpContext.User.GetUserId();
var user = await _dbContext.Users.FirstOrDefaultAsync(p => p.Id == id);
if (user == null) return NotFound(new ApiResponse(404));

ASP.NET MVC: Get user id of currently logged in user

I am new to ASP.NET MVC and am trying to create a web app.
The problem I have is that in the controller class I need to get the UserID of the current user, but I am very confused about how one would do that.
Also, it seems that the user is not authenticated after logging in, because if I use the [Authorize] annotation it throws an HTTP Error 401.0 - Unauthorized error.
This is my Authentication.cs class:
public static class Authentication
{
public static bool CreateNewTicket(User user, bool rememberMe)
{
try
{
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
1,
user.Email,
DateTime.Now,
DateTime.Now.AddDays(5),
rememberMe,
user.ID.ToString(),
FormsAuthentication.FormsCookiePath
);
string encryptedTicket = FormsAuthentication.Encrypt(ticket);
HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
cookie.HttpOnly = true;
if (!HttpContext.Current.Request.IsLocal)
cookie.Secure = true;
HttpContext.Current.Response.Cookies.Add(cookie);
return true;
}
catch
{
return false;
}
}
public static bool AuthUser(string Email, string Password)
{
using (var db = new AntContext())
{
string password = Password;
string email = Email;
string hashedPW = GetHash(password);
bool userValid = db.Users.Any(user => user.Email == email && user.Password == hashedPW);
if (userValid)
{
var actUser = db.Users.FirstOrDefault(u => u.Email == Email && u.Password == hashedPW);
if (!actUser.IsLocked)
{
if (CreateNewTicket(actUser, false))
{
return true;
}
else
{
return false;
}
}
else if (actUser.IsLocked)
{
}
}
return false;
}
}
The actual problem happens when I try to store data in a database.
[HttpPost]
public ActionResult Q_FirstPage(ViewModels.Q1_Answer_VM vm)
{
vm.Qst = new Models.Questionnaire();
vm.Qst.NumericAnswers = new List<Models.NumericAnswer>();
vm.Qst.TextAnswers = new List<Models.TextAnswer>();
vm.Qst.IsComplete = false;
vm.Qst.StartedOn = DateTime.Now;
vm.Qst.NumericAnswers.Add(vm.Breite);
vm.Qst.NumericAnswers.Add(vm.Tiefe);
vm.Qst.NumericAnswers.Add(vm.Hoehe);
vm.Qst.TextAnswers.Add(vm.Sonstiges);
//vm.qst.User_ID = 22; if I set the User ID manually, it works
db.Questionnaires.Add(vm.Qst);
db.SaveChanges();
return View();
}
The Viewmodel works fine and returns the data input, but the UserID is null. The data table "Questionnaire" uses the UserID as a foreign key, which makes it throw an error when it comes to the savedata() part because I guess it expects the correct UserID. So I guess I need to get the current UserID, pass it to the instantiated object which is then passed to the data context and then saved into the database.
Unfortunately, I find it very hard to find complete information about how user authentication works in ASP.NET.
If you need more information, please let me know.
This is my Login method:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Login(Login_VM login_vm)
{
if (!ModelState.IsValid)
{
return View(login_vm);
}
if (Authentication.AuthUser(login_vm.Email, login_vm.Password) == true && (login_vm.Email != null || login_vm.Password != null))
{
Classes.Authentication.CreateNewTicket(login_vm.usr, true);
return RedirectToAction("Login");
}
else
return View("~/Views/Home/Index.cshtml");
}
And this is my registration method:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult AddUser(User model)
// add new User to db
{
if (ModelState.IsValid)
{
User usr = new Models.User();
usr = model;
model.Password = Authentication.GetHash(model.Password);
db.Users.Add(model);
db.SaveChanges();
}
return View();
}
Solved the problem by following this link: howto get the user id from a FormsAuthentication page in asp.net MVC? posted by https://stackoverflow.com/users/2516718/derloopkat
The System.Web.HttpContext.Current.User.Identity.Name Function returns the "name" attribute in the Authentication Ticket, which in my case was the email address. I then got the User ID by having a query to the Users database.
db.Users.Where(x => x.Email == System.Web.HttpContext.Current.User.Identity.Name).FirstOrDefault().ID;
Thanks for everybody's help.
Update in 2020: The query can be simplified to:
db.Users.FirstOrDefault(x => x.Email == System.Web.HttpContext.Current.User.Identity.Name).ID;
There are two simple ways to get current user in MVC 5.
If you are inside the controller class,the current user can be fetched as follows,
string userId = User.Identity.GetUserId();
Do not forget to add namespace:
using Microsoft.AspNet.Identity;
Other scenario could be that you are not inside the controller class and want to fetch the user information. You can fetch that using HttpContext class.
HttpContext.Current.User.Identity.GetUserId();

How to allow user to register with duplicate UserName using Identity Framework 1.0

I want to develop an application in MVC using Identity Framework 1.0 which allow users to register with same username used by some other user.
When deleting a user I want to set its IsDeleted custom property to true rather than deleting the user from database. In this case another user can use the UserName of the user whose IsDeleted is set to true.
But the default UserManager.CreateAsync(user, password); method is preventing doing this.
I had overridden the ValidateEntity method of IdentityDbContext like this
protected override DbEntityValidationResult ValidateEntity(DbEntityEntry entityEntry, IDictionary<object, object> items)
{
if ((entityEntry != null) && (entityEntry.State == EntityState.Added))
{
ApplicationUser user = entityEntry.Entity as ApplicationUser;
if ((user != null) && this.Users.Any<ApplicationUser>(u => string.Equals(u.UserName, user.UserName) && u.IsDeleted==false))
{
return new DbEntityValidationResult(entityEntry, new List<DbValidationError>()) {
ValidationErrors = {
new DbValidationError("User", string.Format(CultureInfo.CurrentCulture,
"", new object[] { user.UserName }))
}
};
}
IdentityRole role = entityEntry.Entity as IdentityRole;
if ((role != null) && this.Roles.Any<IdentityRole>(r => string.Equals(r.Name, role.Name)))
{
return new DbEntityValidationResult(entityEntry, new List<DbValidationError>()) {
ValidationErrors = {
new DbValidationError("Role", string.Format(CultureInfo.CurrentCulture,
"", new object[] { role.Name })) } };
}
}
return base.ValidateEntity(entityEntry, items);
}
Here is my register method where user is created
public async Task<ActionResult> Register(RegisterViewModel model)
{
if (ModelState.IsValid)
{
var user = new ApplicationUser() { UserName = model.UserName, Email = model.Email.ToLower(), CreatedBy = model.UserName, CreatedDate = DateTime.UtcNow, };
user.ConfirmedEmail = false;
var result = await _accountService.CreateAsync(user, model.Password);
if (result.Succeeded)
{
TempData["MessageConfirm"] = user.Email;
return RedirectToAction("Confirm", "Account");
}
else
{
AddErrors(result);
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
ValidateEntity method should be executed when await _accountService.CreateAsync(user, model.Password); executes. But it is executing after the register method completes it's execution. So the result throws error.
Any suggestions how I can achieve this?
My pet peeve is when people decide to give advice in lieu of answering the question asked. usernames don't have to be unique. The db key is userid not user name. If you have application that services several companies there is a chance that employees of different companies will have the same username. In order to do this you have to extent aspnet identity.
https://www.scottbrady91.com/ASPNET-Identity/Quick-and-Easy-ASPNET-Identity-Multitenancy
IdentityUser
To start with we’ll need to add the claim of TenantId (you can rename this as fits your business requirements) by extending the IdentityUser class. Whilst this is conceptually a claim, we will take advantage of the AspNetUser table and add TenantId as a property, as we will be querying by this property a fair bit. For simplicity I have added the TenantId as an int however a non-iterative alternative would be to use a string.
public class ApplicationUser : IdentityUser {
public int TenantId { get; set; }
}
UserStore
Next we’ll implement the UserStore for our new user that is aware of our new property. Here we are using a property within our UserStore class to set our TenantId, allowing us to override the base implementation with our multi-tenanted implementation.
public class ApplicationUserStore<TUser> : UserStore<TUser>
where TUser : ApplicationUser {
public ApplicationUserStore(DbContext context)
: base(context) {
}
public int TenantId { get; set; }
}
CreateUserAsync
public override Task CreateAsync(TUser user) {
if (user == null) {
throw new ArgumentNullException("user");
}
user.TenantId = this.TenantId;
return base.CreateAsync(user);
}
FindByEmailAsync
public override Task<TUser> FindByEmailAsync(string email) {
return this.GetUserAggregateAsync(u => u.Email.ToUpper() == email.ToUpper()
&& u.TenantId == this.TenantId);
}
FindByNameAsync
public override Task<TUser> FindByNameAsync(string userName) {
return this.GetUserAggregateAsync(u => u.UserName.ToUpper() == userName.ToUpper()
&& u.TenantId == this.TenantId);
}
UserValidator
Whilst the default UserValidator has hardcoded checks for duplicate user names, our new implementation of the UserStore methods FindByNameAsync and FindByEmailAsync will allow for the correct multi-tenanted behaviour (assuming you have set a TenantId within the UserStore). This means we can take full advantage of the default UserValidator and extend it if necessary.
IdentityDbContext
Now here’s an awkward bit. The ASP.NET Identity team have again hardcoded a check for duplicate usernames within the IdentityDbContext class, however this time it is both within the ValidateEntity method and in the EF database schema itself using an index.
The index can be solved by extending the OnModelCreating method to change the unique index based on username to also look for our TenantId (a composite index). This saves us losing this useful index and optimises our database for multitenancy. You can do this with the following override method:
public class ApplicationUserDbContext<TUser> : IdentityDbContext<TUser>
where TUser : ApplicationUser {
public ApplicationUserDbContext(string nameOrConnectionString)
: base(nameOrConnectionString) {
}
protected override void OnModelCreating(DbModelBuilder modelBuilder) {
base.OnModelCreating(modelBuilder);
var user = modelBuilder.Entity<TUser>();
user.Property(u => u.UserName)
.IsRequired()
.HasMaxLength(256)
.HasColumnAnnotation("Index", new IndexAnnotation(
new IndexAttribute("UserNameIndex") { IsUnique = true, Order = 1}));
user.Property(u => u.TenantId)
.IsRequired()
.HasColumnAnnotation("Index", new IndexAnnotation(
new IndexAttribute("UserNameIndex") { IsUnique = true, Order = 2 }));
}
}
The ValidateEntity method is a bit more tricky however, as we will have to reimplement the entire method in order to remove the hardcoded username checks:
protected override DbEntityValidationResult ValidateEntity(
DbEntityEntry entityEntry, IDictionary<object, object> items) {
if (entityEntry != null && entityEntry.State == EntityState.Added) {
var errors = new List<DbValidationError>();
var user = entityEntry.Entity as TUser;
if (user != null) {
if (this.Users.Any(u => string.Equals(u.UserName, user.UserName)
&& u.TenantId == user.TenantId)) {
errors.Add(new DbValidationError("User",
string.Format("Username {0} is already taken for AppId {1}",
user.UserName, user.TenantId)));
}
if (this.RequireUniqueEmail
&& this.Users.Any(u => string.Equals(u.Email, user.Email)
&& u.TenantId == user.TenantId)) {
errors.Add(new DbValidationError("User",
string.Format("Email Address {0} is already taken for AppId {1}",
user.UserName, user.TenantId)));
}
}
else {
var role = entityEntry.Entity as IdentityRole;
if (role != null && this.Roles.Any(r => string.Equals(r.Name, role.Name))) {
errors.Add(new DbValidationError("Role",
string.Format("Role {0} already exists", role.Name)));
}
}
if (errors.Any()) {
return new DbEntityValidationResult(entityEntry, errors);
}
}
return new DbEntityValidationResult(entityEntry, new List<DbValidationError>());
}
Client
All that remains now is to initialise the classes. Don't forget you will need to supply the TenantId each time you new up the context. See the below example (note the use of 'example', these classes are all disposable...).
var context = new ApplicationUserDbContext<ApplicationUser>("DefaultConnection");
var userStore = new ApplicationUserStore<ApplicationUser>(context) { TenantId = 1 };
var userManager = new UserManager<ApplicationUser, string>(userStore);

How to add roles from database

I have my ASP.NET MVC 4 project and database (SQL Server 2008)
And I've created an entity framework model, with auto-generated models.
And in the database there is a table called Roles (2 fields, Id and name)
There are 3 roles: admin, moderator, user.
Plus Account controller:
public class AccountController : Controller
{
private korovin_idzEntities db = new korovin_idzEntities();
//
// GET: /Account/LogOn
public ActionResult LogOn()
{
return View();
}
//
// POST: /Account/LogOn
[HttpPost]
public ActionResult LogOn(LogOnModel model/*, string returnUrl*/)
{
if (ModelState.IsValid)
{
var user = db.Users.Where(x => x.username == model.UserName && x.password == model.Password).FirstOrDefault();
if (user != null)
{
user.isRemember = model.RememberMe;
db.SaveChanges();
ViewBag.UserName = model.UserName;
FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
FormsAuthentication.RedirectFromLoginPage(model.UserName, false);
}
else
{
ModelState.AddModelError("", "The user name or password provided is incorrect.");
}
}
return View(model);
}
}
Where and how can i initialize roles in my asp.net mvc application? I've tried to check whether role exists and to initialize role by rolemanager in account controller, but i think it's not a good solution.
Is it possible to initialize roles in global.asax.cs?
I know that I should attach roles to user in log on function.
Thanks in advance :)
Here is my solution, I thought that there is some kind of a structure for storing a names of roles and there is needed to initialize this structure, but i was wrong, and after googling, I've found the solution:
protected void Application_PostAuthenticateRequest(object sender, EventArgs e)
{
var context = HttpContext.Current;
if (context.Request.IsAuthenticated)
{
string[] roles = LookupRolesForUser(context.User.Identity.Name);
var newUser = new GenericPrincipal(context.User.Identity, roles);
context.User = Thread.CurrentPrincipal = newUser;
}
}
#region helper
private string[] LookupRolesForUser(string userName)
{
string[] roles = new string[1];
CosmosMusic.Models.korovin_idzEntities db = new CosmosMusic.Models.korovin_idzEntities();
var roleId = db.Users.Where(x => x.username == userName).FirstOrDefault().id_role;
roles[0] = db.Role.Where(y => y.id_role == roleId).FirstOrDefault().name;
return roles;
}
#endregion

How to change username and password in MVC 4 application using Simple membership

I am building an MVC 4 web application with simple membership provider and i have administration where i can edit user's username and password.When i edit just username or password it is okay, but when i try to edit both username and password at the same time when i try to log in with the new username the UserProfiles username that is shown in the users list is the old one, although the record in the database has changed.Here is a code sample :
[HttpPost]
public ActionResult EditUser(RegisterUserModel model, FormCollection form)
{
if (ModelState.IsValid)
{
var oldUserName = form["userHidden"];
var newUserName = model.UserName;
bool isOldPassword = Membership.ValidateUser(oldUserName , model.Password);
if (!isOldPassword)
{
var token = WebSecurity.GeneratePasswordResetToken(oldUserName );
try
{
//Reset password using the reset token and the new password
WebSecurity.ResetPassword(token, model.Password);
}
catch (Exception e)
{
ModelState.AddModelError("", String.Format("{0} Exception caught.", e));
}
}
if (newUserName != null && oldUserName != null)
{
if (newUserName.ToLower() != oldUserName.ToLower())
{
myRepository.ChangeUserName(oldUserName, newUserName);
myRepository.Save();
}
}
return RedirectToAction("Users", "Administration");
}
ModelState.AddModelError("", "Please enter correct username and password.");
return View(model);
}
And here is my ChangeUserName method:
public void ChangeUserName(string oldUserName, string newUserName)
{
var userToUpdate = (from user
in context.Users
where user.Username == oldUserName
select user).FirstOrDefault();
if (userToUpdate != null)
{
var updatedUser = new Users();
updatedUser.UserId = userToUpdate.UserId;
updatedUser.UserName = newUserName;
context.Entry(userToUpdate).CurrentValues.SetValues(updatedUser);
}
}
I have extended my membership like this:
public class ExtendMembership
{
private static IMyRepository myRepository= new MyRepository(new MyEntities());
public static bool ValidateUser(string username, string password, string companyName)
{
int companyId = myRepository.GetCompanyName(companyName);
int? userId = companyId == 0 ? null : GetUserId(username, companyId);
if (userId.HasValue && userId.Value != 0)
{
var userKeyToCompany = username + "#" + companyName.ToLower();
return WebSecurity.Login(userKeyToCompany , password);
}
else
{
return false;
}
}
private static int? GetUserId(string username, int companyId)
{
var userId = (from users
in myRepository.GetUsers()
where (users.UserName.ToLower() == username.ToLower()) && (users.CompanyId == companyId)
select users.UserId).FirstOrDefault();
return userId;
}
}
The GetUserId method fetches the id of the user for company
You should consider using construction instead of the static repository. Static repositories would fire back if you handle lots of requests. Here is a sample of the using you could use :
using(var myRepository = new MyRepository(new MyEntities())) {
... code here
}
It turns out that my GetUserId method should be in MyRepository implemented on the changed context and also change password and change username actions should be separated. That solved everything.

Categories

Resources