Getting UserId from MVC using WebMetrix - asp.net-mvc-5

I'm using bellow login method to login in a MVC 5 application.
What I want to do is get the id of the user that is currently logged.
I tried to use these 2 methods:
// 1
// This one raise an exception:
Guid loggedUser = (Guid)Membership.GetUser().ProviderUserKey;
Additional information: Object reference not set to an instance of an
object.
// 2
// sets loggedUser variable to null
loggedUser = User.Identity.GetUserId();
// Login Method within Controller
public ActionResult Login(Login logindata, string ReturnUrl)
{
if (ModelState.IsValid)
{
if (WebSecurity.Login(logindata.Username, logindata.Password))
{
if (ReturnUrl != null)
{
return Redirect(ReturnUrl);
}
return RedirectToAction("Index", "Home");
}
}
ModelState.AddModelError("", "Sorry the username or password is invalid ");
return View(logindata);
}
My question is what I'm doing wrong and if it's possible to get the logged user id like this???
Thanks

I used this method and worked:
WebSecurity.GetUserId("loggedUser")

Related

query string param is not url-encoded inside asp.net mvc action

I'm calling ResetPassword action from an Email (ASP.NET MVC 5).
http://localhost:34162/Account/ResetPassword?code=BwEA181bAECFMcn1vwPdrctS/wcyncKPxGT9Zx1tDuPwKGpe9H1W7LI3Zm9fM+3aA5Fok5GhLPBHqbtiGfpL8Cmdx7RNC6RJ7d6t9ZgFBwgwYk3zssU1Nh64PWHJAabVG9Wv9VWDNdj+Fz0UA712XA==
This is the address in my Browser.
However, in debug I receive this string in the ResetPassword Action:
// GET: /Account/ResetPassword
[AllowAnonymous]
public ActionResult ResetPassword(string code)
{
return code == null ? View("Error") : View();
}
The 'code' is:
BwEA181bAECFMcn1vwPdrctS/wcyncKPxGT9Zx1tDuPwKGpe9H1W7LI3Zm9fM 3aA5Fok5GhLPBHqbtiGfpL8Cmdx7RNC6RJ7d6t9ZgFBwgwYk3zssU1Nh64PWHJAabVG9Wv9VWDNdj Fz0UA712XA==
i.e., it is not url-encoded and of course password is not reset with invalid token message.
What can I do for getting the right string in the Action?
You can encode the string in the following way:
[AllowAnonymous]
public ActionResult ResetPassword(string code)
{
code = Server.HtmlEncode(code);
}
Fore more information on how to encode you can look at
https://msdn.microsoft.com/en-us/library/w3te6wfz(v=vs.110).aspx
I still don't know what was the problem. Looks like it shouldn't have worked in the first place. I wish I knew why Microsoft feel the need to use tokens with slashes and pluses.
Anyway, I just Base64 encoded and decoded the token as follows:
before sending the Email to the user:
...
string code = await UserManager.GeneratePasswordResetTokenAsync(user.Id);
code = CommonFuncs.Base64Encode(code);
EmailsBL.PasswordResetEmail(model.Email, code); <-- emailing the link for password rest to the user
And then when receiving:
// POST: /Account/ResetPassword
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> ResetPassword(ResetPasswordViewModel model)
{
/////////////////////////////////////////////////////////////////////
// NOTE: if email is not CONFIRMED then reset password silently fails
////////////////////////////////////////////////////////////////////
if (!ModelState.IsValid)
{
return View(model);
}
model.Code = CommonFuncs.Base64Decode(model.Code);
i.e., decoding the token.
This following is just for completeness:
public static string Base64Encode(string plainText)
{
string base64string = null;
if (plainText != null)
{
var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText);
base64string = System.Convert.ToBase64String(plainTextBytes);
}
return base64string;
}
public static string Base64Decode(string base64EncodedData)
{
string decodedBase64String = null;
if (base64EncodedData != null)
{
var base64EncodedBytes = System.Convert.FromBase64String(base64EncodedData);
decodedBase64String = System.Text.Encoding.UTF8.GetString(base64EncodedBytes);
}
return decodedBase64String;
}

Getting captcha plugin to work with register action

I have the login portion working and the register page displays the captcha clearly, the .dll for RecaptchaMVC5 says that AccountController does not contain a definition for verifyReCAPTCHA but it works with the login portion:
Examples:
Login thats working:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
if (ModelState.IsValid)
{
// Verify the recaptcha response.
ReCaptchaResponse response = await this.verifyReCAPTCHA(model, "key", true);
if (response.Success)
{
var user = await UserManager.FindAsync(model.UserName, model.Password);
if (user != null)
{
await SignInAsync(user, model.RememberMe);
return RedirectToLocal(returnUrl);
}
else
{
ModelState.AddModelError("", "Invalid username or password.");
}
}
else
{
ModelState.AddModelError("", "Invalid Captcha Code!");
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
My Register Mockup that throws errors on verifyReCAPTCHA:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Register(RegisterViewModel model)
{
if (ModelState.IsValid)
{
//Verify the recaptcha response.
ReCaptchaResponse response = await this.verifyReCAPTCHA(model, "key", true);
if (response.Success)
{
var user = new ApplicationUser() { UserName = model.UserName };
var result = await UserManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
await SignInAsync(user, isPersistent: false);
return RedirectToAction("Index", "Home");
}
else
{
AddErrors(result);
}
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
the error I get
Error 1 'ReCaptchaMVC5Test.Controllers.AccountController' does not contain a definition for 'verifyReCAPTCHA'
Inside Models folder > AccountViewModels.cs There is
public class LoginViewModel : ReCaptchaViewModel
and
public class RegisterViewModel : <Place 'RecaptchaViewModel' Here>
That's how you assign the Captcha's view model to other models
assuming both these methods are on the AccountController, what is the method signature for verifyReCAPTCHA as the methods both send different models (LoginViewModel and RegisterViewModel) do both inherit from the correct base?
From what I can tell by the source, there's an extension method you're unable to access. Looks like you need to add using ReCaptcha.Mvc5; to the top of your Controller's source file to gain access.
verifyReCAPTCHA(this Controller, ReCaptchaViewModel, String, Boolean)
Also, make sure your model inherits from ReCaptcha.Mvc5.Model.ReCaptchaViewModel (as demonstrated in their documentation), that way you satisfy the method signature.

ASP.NET Identity: UserManager.PasswordHasher.VerifyHashedPassword keeps failing

I'm using ASP.NET Identity 2 with Entity Framework 5 (because our Oracle data provider does not support EF6). For some reason the password verification by means of UserManager.PasswordHasher.VerifyHashedPassword keeps failing.
My UserStore class contains:
public Task SetPasswordHashAsync(IccmUser user, string passwordHash)
{
IPasswordHasher hasher = new PasswordHasher();
var t = Task.Run(() => {
user.PasswordHash = hasher.HashPassword(passwordHash);
});
return t;
}
The (obviously hashed) password is stored in the database. Thus, this code seems to work just fine.
My AccountController does the password verification like this:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(SignInModel model, string returnUrl)
{
if (ModelState.IsValid) {
// This fails:
//var user = await UserManager.FindAsync(model.UserName, model.Password);
// Thus: do it step by step.
PasswordVerificationResult result = PasswordVerificationResult.Failed;
// Step 1: find user.
IccmUser user = await UserManager.FindByNameAsync(model.UserName);
if (user == null) {
ModelState.AddModelError("", "Couldn't find the user.");
} else {
// Step 2: validate password
result = UserManager.PasswordHasher.VerifyHashedPassword(user.PasswordHash, model.Password);
if (result != PasswordVerificationResult.Success) {
ModelState.AddModelError("", "The password is not valid.");
} else {
// Step 3: sign-in user.
await SignInAsync(user, model.RememberMe);
return Redirect(returnUrl);
}
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
The VerifyHashedPassword() in step 2 always returns Failed. Both parameters (PasswordHash and Password) are passed in correctly.
Any pointers to what I'm missing are greatly appreciated.
The error is in the UserStore implementation. SetPasswordHashAsync() is not supposed to hash the password. Instead, it receives the hashed password from UserManager.CreateAsync(). Thus, the following change in UserStore does the trick:
public Task SetPasswordHashAsync(IccmUser user, string passwordHash)
{
return Task.FromResult(user.PasswordHash = passwordHash);
}
Sorry for the noise.

How to delete user with UserManager in mvc5

I'm using mvc5, and everything about user account management I do with UserManager. It works good with roles, claims, etc. But I didn't find how to delete user with UserManager. Is there a way to delete user with UserManager? I can create Database context with dbset and then delete it from this context, but I don't want create dbcontext, userclass, etc. for one delete method.
I had issues with the above answer, though I was able to work out what's wrong. I kept getting a cascading error. Basically the user was being deleted without the role being deleted. DeleteAsync was not doing that for me (I have the latest build of Identity Framework). Ended up passing both the userid and role into my code, deleting the user from the role, then deleting the user. Seems to work fine.
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Delete(string id, string role)
{
// Check for for both ID and Role and exit if not found
if (id == null || role == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
// Look for user in the UserStore
var user = UserManager.Users.SingleOrDefault(u => u.Id == id);
// If not found, exit
if (user == null)
{
return HttpNotFound();
}
// Remove user from role first!
var remFromRole = await UserManager.RemoveFromRoleAsync(id, role);
// If successful
if (remFromRole.Succeeded)
{
// Remove user from UserStore
var results = await UserManager.DeleteAsync(user);
// If successful
if (results.Succeeded)
{
// Redirect to Users page
return RedirectToAction("Index", "Users", new {area = "Dashboard"});
}
else
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
}
else
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
}
Delete was not supported in UserManager in 1.0, but its supported in the upcoming 2.0 release, and in the current 2.0 nightly builds if you want to preview the changes early.
Using the updated asp.net identity I have the following code:
public UserManagerController()
: this(new UserManager<User>(new UserStore<User>(new ApplicationDbContext())))
{
}
public UserManagerController(UserManager<User> userManager)
{
UserManager = userManager;
}
public UserManager<User> UserManager { get; private set; }
public async Task<ActionResult> Delete (string id)
{
var userContext = new ApplicationDbContext();
var user = UserManager.Users.SingleOrDefault(u => u.Id == id);
var userStore = new UserStore<User>(userContext);
await UserManager.DeleteAsync(user);
// var userManager = new UserManager<User>(userStore);
// await userManager.DeleteAsync(user);
return RedirectToAction("Index");
}
This one now deletes the user. It is also no need to delete from UserRoles table as that is taken care of by UserManager.DeleteAsync(user).
Hope this helps a few. I spent some time figuring out why I got some errors.
Trond

ASP.net Identity Disable User

Using the new ASP.net Identity in MVC 5, How do we disable a user from logging in? I don't want to delete them, maybe just disable their account for a time period.
Does anyone have any ideas on this as I don't see a status column or anything on the ASPNetUsers table.
await userManager.SetLockoutEnabledAsync(applicationUser.Id, true);
await userManager.SetLockoutEndDateAsync(DateTime.Today.AddYears(10));
Update: As CountZero points out, if you're using v2.1+, then you should try and use the lockout functionality they added first, before trying the solution below. See their blog post for a full sample: http://blogs.msdn.com/b/webdev/archive/2014/08/05/announcing-rtm-of-asp-net-identity-2-1-0.aspx
Version 2.0 has the IUserLockoutStore interface that you can use to lockout users, but the downside is that there is no OOB functionality to actually leverage it beyond the pass-through methods exposed by the UserManager class. For instance, it would be nice if it would actually increment the lockout count as a part of the standard username/password verification process. However, it's fairly trivial to implement yourself.
Step #1: Create a custom user store that implements IUserLockoutStore.
// I'm specifying the TKey generic param here since we use int's for our DB keys
// you may need to customize this for your environment
public class MyUserStore : IUserLockoutStore<MyUser, int>
{
// IUserStore implementation here
public Task<DateTimeOffset> GetLockoutEndDateAsync(MyUser user)
{
//..
}
public Task SetLockoutEndDateAsync(MyUser user, DateTimeOffset lockoutEnd)
{
//..
}
public Task<int> IncrementAccessFailedCountAsync(MyUser user)
{
//..
}
public Task ResetAccessFailedCountAsync(MyUser user)
{
//..
}
public Task<int> GetAccessFailedCountAsync(MyUser user)
{
//..
}
public Task<bool> GetLockoutEnabledAsync(MyUser user)
{
//..
}
public Task SetLockoutEnabledAsync(MyUser user, bool enabled)
{
//..
}
}
Step #2: Instead of UserManager, use the following class in your login/logout actions, passing it an instance of your custom user store.
public class LockingUserManager<TUser, TKey> : UserManager<TUser, TKey>
where TUser : class, IUser<TKey>
where TKey : IEquatable<TKey>
{
private readonly IUserLockoutStore<TUser, TKey> _userLockoutStore;
public LockingUserManager(IUserLockoutStore<TUser, TKey> store)
: base(store)
{
if (store == null) throw new ArgumentNullException("store");
_userLockoutStore = store;
}
public override async Task<TUser> FindAsync(string userName, string password)
{
var user = await FindByNameAsync(userName);
if (user == null) return null;
var isUserLockedOut = await GetLockoutEnabled(user);
if (isUserLockedOut) return user;
var isPasswordValid = await CheckPasswordAsync(user, password);
if (isPasswordValid)
{
await _userLockoutStore.ResetAccessFailedCountAsync(user);
}
else
{
await IncrementAccessFailedCount(user);
user = null;
}
return user;
}
private async Task<bool> GetLockoutEnabled(TUser user)
{
var isLockoutEnabled = await _userLockoutStore.GetLockoutEnabledAsync(user);
if (isLockoutEnabled == false) return false;
var shouldRemoveLockout = DateTime.Now >= await _userLockoutStore.GetLockoutEndDateAsync(user);
if (shouldRemoveLockout)
{
await _userLockoutStore.ResetAccessFailedCountAsync(user);
await _userLockoutStore.SetLockoutEnabledAsync(user, false);
return false;
}
return true;
}
private async Task IncrementAccessFailedCount(TUser user)
{
var accessFailedCount = await _userLockoutStore.IncrementAccessFailedCountAsync(user);
var shouldLockoutUser = accessFailedCount > MaxFailedAccessAttemptsBeforeLockout;
if (shouldLockoutUser)
{
await _userLockoutStore.SetLockoutEnabledAsync(user, true);
var lockoutEndDate = new DateTimeOffset(DateTime.Now + DefaultAccountLockoutTimeSpan);
await _userLockoutStore.SetLockoutEndDateAsync(user, lockoutEndDate);
}
}
}
Example:
[AllowAnonymous]
[HttpPost]
public async Task<ActionResult> Login(string userName, string password)
{
var userManager = new LockingUserManager<MyUser, int>(new MyUserStore())
{
DefaultAccountLockoutTimeSpan = /* get from appSettings */,
MaxFailedAccessAttemptsBeforeLockout = /* get from appSettings */
};
var user = await userManager.FindAsync(userName, password);
if (user == null)
{
// bad username or password; take appropriate action
}
if (await _userManager.GetLockoutEnabledAsync(user.Id))
{
// user is locked out; take appropriate action
}
// username and password are good
// mark user as authenticated and redirect to post-login landing page
}
If you want to manually lock someone out, you can set whatever flag you're checking in MyUserStore.GetLockoutEnabledAsync().
You can have a new class, which should be derived from IdentityUser class. YOu can add a boolean property in the new class and can use this new property of take care per check for login process. I also done it pretty well. I might wanna take a look at : blog
UserManager.RemovePasswordAsync("userId") will effectively disable a user. If the user has no password he will not be able to log in. You will need to set a new password to enable the user again.

Resources