Show only one Register error instead of two - asp.net

I have an ASP.Net MVC site that uses ASP.Net Identity for managing users.
I use the default mechanism that the Email of the user is also his username. When a user wants to register with an Email which is already taken two error messages are shown:
Name myEmail#gmail.com is already taken.
Email 'myEmail#gmail.com' is already taken.
The structure of the Register form:
HttpPost Register Method of AccountController:
public async Task<ActionResult> Register(RegisterViewModel model)
{
if (ModelState.IsValid)
{
var user = new ApplicationUser {UserName = model.Email, Email = model.Email};
var result = await UserManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
string callbackUrl =
await SendEmailConfirmationTokenAsync(user.Id, "Confirm your account");
return View("Info");
}
AddErrors(result);
}
// If we got this far, something failed, redisplay form
return View(model);
}
How can I only show the Email Error message to the user?

Replace your AddErrors() method with
ModelState.AddModelError("", String.Format("{0} is already taken", model.Email))
or, if you have included #Html.ValidationMessageFor(m => m.Email) in the view and want the message to be associated with the form control, rather than in the summary
ModelState.AddModelError("Email", String.Format("{0} is already taken", model.Email))
Side note: You might also want to consider using a RemoteAttribute so that you get client side validation before submitting the form - refer How to: Implement Remote Validation in ASP.NET MVC (although you should also keep the code above in (the rare) case 2 users submit the same Email at the same time).

Related

adding a custom rule in default asp.net login system

Hi guys I'm working on a project in which we can disable our users. There is a column name status in user table that can be true or false. Now I want to add a new rule in default asp.net user login that if a user is disable(his column name status equals false), should not able to login with an error message that "Admin have disabled your account".
I have looked in,
ManageController.cs
IdentityConfig.cs
ManageViewModles.cs
IdentityModel.cs
but I didn't get any clue. How can I add this rule in my asp.net MVC-5 application
You could define a verification with an async function in your login view controller and call it on Login button press.
Good place to start: here
EDIT
Here some code sample you could have in your HomeController->Index Action. Note that this isn't async but you could implement an async action with your db call:
[HttpGet]
public ActionResult Index()
{
//Verification of user
//if true
return View();
//else false
return ErrorView(); //View that contains the error message
}
In login method of account controller i achieved it using this code.
I updated code in my switch(result) of case SignInStatus.Success:
case SignInStatus.Success:
var userID = SignInManager.AuthenticationManager.AuthenticationResponseGrant.Identity.GetUserId();
AspNetUser res = db.AspNetUsers.Where(x => x.Id == userID).Select(x => x).FirstOrDefault();
if (res.Status == "False")
{
AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
// return RedirectToAction("Index", "Home");
ModelState.AddModelError("", "Admin has disabled your account.");
return View(model);
}
//remaining code here

Asp.NET MVC 5 validate user by e-mail and password

I'm using a Asp.NET MVC 5 project that came with a Bootstrap 3 theme we bought and in its login method they just look for the user based on his e-mail, the password is not validated. Login method below:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(AccountLoginModel viewModel)
{
// Ensure we have a valid viewModel to work with
if (!ModelState.IsValid)
return View(viewModel);
// Verify if a user exists with the provided identity information
var user = await _manager.FindByEmailAsync(viewModel.Email);
var hashPass = new PasswordHasher().HashPassword(viewModel.Password); // this is a line I added which gerenates a different hash everytime
// If a user was found
if (user != null)
{
// Then create an identity for it and sign it in
await SignInAsync(user, viewModel.RememberMe);
// If the user came from a specific page, redirect back to it
return RedirectToLocal(viewModel.ReturnUrl);
}
// No existing user was found that matched the given criteria
ModelState.AddModelError("", "Invalid username or password.");
// If we got this far, something failed, redisplay form
return View(viewModel);
}
The line I'm trying to insert the password validation is the if (user != null). I tried using _manager.Find(email,password) but it doesn't work.
How can I login the user with his e-mail and validate the password?
That is because you are hashing the password before trying to find the user.
Do
var user = _manager.Find(viewModel.Email, viewModel.Password);
// If a user was found
if (user != null)
{
//...other code removed for brevity.
which is the standard way to do it.
-------Try this code------
var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: false);
switch (result)
{
case SignInStatus.Success:
return View("SuccessView");
case SignInStatus.Failure:
return View("LoginView");
}

Migrate Identity Authentication from ASP.NET MVC to ASP.NET Web API

I have a ASP.NET MVC web application and I want to register and login using angular. I'm calling a Login and Register Method on my WebAPI when the user wants to Login/Register. The problem is that I don't know how to transfer my MVC Login and Register in the AccountController to my WebAPI.
My current Register method looks like this:
// POST api/RegisterApi
public async Task<HttpResponseMessage> Post([FromBody]RegisterViewModel model)
{
if (!ModelState.IsValid)
{
return await this.BadRequest(this.ModelState).ExecuteAsync(new CancellationToken());
}
var user = new ApplicationUser
{
Email = model.Email,
UserName = model.Email
};
IdentityResult result = await this.UserManager.CreateAsync(user, model.Password);
if (!result.Succeeded)
{
return await this.GetErrorResult(result).ExecuteAsync(new CancellationToken());
}
// Auto login after register (successful user registration should return access_token)
var loginResult = this.LoginUser(new LoginViewModel()
{
Email = model.Email,
Password = model.Password
});
return await loginResult;
}
My main issue is the following line:
IdentityResult result = await this.UserManager.CreateAsync(user, model.Password);
Somehow i can't call the CreateAsync-Method and I don't really know why.
I get the following error:
Task' does not contain a definition for 'CreateAsync'
and no extension method 'CreateAsync' accepting a first argument of
type 'Task
Do you guys can give my any input on doing this properly? Everything I've seen so far seemed far too complicated for my problem.
EDIT: Okay the error is solved, but now there's a new problem. The CreateAsync method does not Create a User and returns to the error function in my AngularJs. Do you guys have any suggestion why CreateAsync could fail?

How to set up two-factor authentication in ASP.NET MVC 5.2.3 and Katana correctly?

In the code that you get in the ASP.NET MVC 5.2.3 templates with Visual Studio 2015 Community RC, if you run them as they came, and if you register with your email address (and not with an external service provider such as Facebook or Google or Linked In or Twitter), and then if you login into the website by entering your user name and password, it straight-away lets you login and does not trigger two-factor authentication. It just logs you in successfully.
Specifically, the PasswordSignInAsync method on the SignInManager always returns a SignInStatus of Success if you enter your correct user name and password. It never evaluates to SignInStatus.RequiresVerification.
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel model,
string returnUrl)
{
if (!ModelState.IsValid)
{
return View(model);
}
// This doesn't count login failures towards account lockout
// To enable password failures to trigger account lockout,
// change to shouldLockout: true
var result = await SignInManager.PasswordSignInAsync(
model.Email, model.Password,
model.RememberMe, shouldLockout: true);
switch (result)
{
case SignInStatus.Success:
// if I sign-in with my correct user name
// and password, the flow-of-control always
// comes here. The SignInStatus never evaluates
// to RequiresVerification
return RedirectToLocal(returnUrl);
case SignInStatus.LockedOut:
return View("Lockout");
case SignInStatus.RequiresVerification:
// the flow-of-control never reaches here
return RedirectToAction("SendCode",
new
{
ReturnUrl = returnUrl,
RememberMe = model.RememberMe
});
case SignInStatus.Failure:
default:
ModelState.AddModelError("", "Invalid login attempt.");
return View(model);
}
}
This happens even though the default code has got two-factor authentication enabled and set up as indicated by the following snippets of code.
In Startup.ConfigureAuth
app.UseTwoFactorSignInCookie(DefaultAuthenticationTypes.TwoFactorCookie,
TimeSpan.FromMinutes(5));
app.UseTwoFactorRememberBrowserCookie(
DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie);
In ApplicationUserManager.Create, the factory method.
// Register two factor authentication providers. This application uses Phone
// and Emails as a step of receiving a code for verifying the user
// You can write your own provider and plug it in here.
manager.RegisterTwoFactorProvider("Phone Code",
new PhoneNumberTokenProvider<ApplicationUser>
{
MessageFormat = "Your security code is {0}"
});
manager.RegisterTwoFactorProvider("Email Code",
new EmailTokenProvider<ApplicationUser>
{
Subject = "Security Code",
BodyFormat = "Your security code is {0}"
});
var container = Unity.Container;
manager.EmailService = container.Resolve<EmailService>();
manager.SmsService = container.Resolve<SmsService>();
I've got my EmailService and SmsService set up in a Unity container and they're configured properly.
What else do I need to do to set it up correctly? I have read this article and a few pieces of documentation from the MSDN, and a few forums posts on other websites about setting this up, but I am not very certain if I am missing something.
This guy isn't called / redirected to from anywhere. I guess this is what's missing.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> EnableTwoFactorAuthentication()
{
await UserManager.SetTwoFactorEnabledAsync(User.Identity.GetUserId(),
true);
var user = await UserManager.FindByIdAsync(User.Identity.GetUserId());
if (user != null)
{
await SignInManager.SignInAsync(user, isPersistent: false,
rememberBrowser: false);
}
return RedirectToAction("Index", "Manage");
}
It does seem that I am missing the part where I have to specifically have the user call the EnableTwoFactorAuthentication action as there is currently no call to it, but I can't be sure how that should integrate with the rest of the login workflow.
Click f12 from your browser and delete application Cookies

Where I can find documentation for ASP.NET Identity RC1?

After Microsoft updated ASP.NET Identity framework to version 1.0.0-rc1, I can't find any documentation or guide how to use it. There is 2 sample projects on github (one, two), but they not covering advanced things like tokens, password reset, roles, etc.
i believe the only real documentation is replies on this forum. The structure of several entities have changed since the beta as well.
I also could do with some more in depth information, particularly
linking to your own custom user table
having access to this custom table from the controller's User property
access to the user and roles from a authorise attribute regardless of the actual login method (local,gmail,twitter etc)
I have added a project called WebCustomUser to https://github.com/onybo/Asp.Net-Identity-RC1-sample-app/tree/master/WebApplication.
This project demonstrates use of the methods:
RequireTokenConfirmationForSignInAsync
ConfirmSignInTokenAsync
to implement token activation of user accounts.
Update:
The project now include a custom entity framework model with custom users which have an email address added (just as an example).
The modeling project that contains two diagrams that shows some of the new classes in ASP.NET identity is now in a separate solution so that the main solution can be opened in the profession SKU.
Heres the modified Register action and the Activate action.
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Register(RegisterViewModel model)
{
if (ModelState.IsValid)
{
// Create a profile, password, and link the local login before signing in the user
User user = new User(model.UserName);
var result = await new UserManager(IdentityManager).CreateLocalUserAsync(user, model.Password);
if (result.Success)
{
var token = Guid.NewGuid();
var tokenResult = await AuthenticationManager.RequireTokenConfirmationForSignInAsync(token.ToString(), user.Id, DateTime.Now.AddDays(2));
if (tokenResult.Success)
{
return RedirectToAction("Registered", "Account", new { userId = user.Id.ToString(), token = token.ToString() });
}
else
AddModelError(tokenResult, "RequireTokenConfirmation failed");
}
else
{
AddModelError(result, "Failed to register user name: " + model.UserName);
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
[AllowAnonymous]
public async Task<ActionResult> Activate(string userId, string token)
{
var tokenResult = await AuthenticationManager.ConfirmSignInTokenAsync(token);
return RedirectToAction("Login", new {returnUrl="/home"});
}
You can find samples to the nightly build of the identity library here.

Resources