AccountController identity cleanup

Use SignInManager where appropriate
Misc cleanup of controller actions
This commit is contained in:
Hao Kung 2014-04-15 11:03:18 -07:00
parent 46da4ba9e4
commit 70b45dbe2d
3 changed files with 113 additions and 48 deletions

View File

@ -1,5 +1,7 @@
using Microsoft.AspNet.Abstractions.Security; using System;
using System.Security.Claims;
using Microsoft.AspNet.Identity; using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.Security;
using Microsoft.AspNet.Mvc; using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Mvc.ModelBinding; using Microsoft.AspNet.Mvc.ModelBinding;
using MusicStore.Models; using MusicStore.Models;
@ -14,19 +16,34 @@ namespace MusicStore.Controllers
public AccountController() public AccountController()
//Bug: Using an in memory store //Bug: Using an in memory store
//: this(new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext()))) //: this(new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext())))
//: this(new UserManager<ApplicationUser>(new InMemoryUserStore<ApplicationUser>())) : this(new UserManager<ApplicationUser>(Startup.UserStore))
{ {
} }
//public AccountController(UserManager<ApplicationUser> userManager) public AccountController(UserManager<ApplicationUser> userManager)
//{ {
// UserManager = userManager; UserManager = userManager;
//} }
/// <summary> public UserManager<ApplicationUser> UserManager { get; set; }
/// TODO: Temporary ugly work around (making this static) to enable creating a static InMemory UserManager. Will go away shortly.
/// </summary> private SignInManager<ApplicationUser> _signInManager;
public static UserManager<ApplicationUser> UserManager { get; set; } public SignInManager<ApplicationUser> SignInManager {
get
{
if (_signInManager == null)
{
_signInManager = new SignInManager<ApplicationUser>()
{
UserManager = UserManager,
Context = Context,
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie
};
}
return _signInManager;
}
set { _signInManager = value; }
}
// //
// GET: /Account/Login // GET: /Account/Login
@ -47,15 +64,18 @@ namespace MusicStore.Controllers
{ {
if (ModelState.IsValid == true) if (ModelState.IsValid == true)
{ {
var user = await UserManager.FindByUserNamePasswordAsync(model.UserName, model.Password); var signInStatus = await SignInManager.PasswordSignInAsync(model.UserName, model.Password, model.RememberMe, shouldLockout: false);
if (user != null) switch (signInStatus)
{ {
await SignIn(user, model.RememberMe); case SignInStatus.Success:
return RedirectToLocal(returnUrl); return RedirectToLocal(returnUrl);
} case SignInStatus.LockedOut:
else ModelState.AddModelError("", "User is locked out, try again later.");
{ return View(model);
ModelState.AddModelError("", "Invalid username or password."); case SignInStatus.Failure:
default:
ModelState.AddModelError("", "Invalid username or password.");
return View(model);
} }
} }
@ -86,7 +106,7 @@ namespace MusicStore.Controllers
var result = await UserManager.CreateAsync(user, model.Password); var result = await UserManager.CreateAsync(user, model.Password);
if (result.Succeeded) if (result.Succeeded)
{ {
await SignIn(user, isPersistent: false); await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);
//Bug: No helper methods //Bug: No helper methods
//return RedirectToAction("Index", "Home"); //return RedirectToAction("Index", "Home");
return Redirect("/"); return Redirect("/");
@ -130,8 +150,8 @@ namespace MusicStore.Controllers
{ {
if (ModelState.IsValid == true) if (ModelState.IsValid == true)
{ {
var user = new ApplicationUser() { UserName = this.Context.User.Identity.GetUserId() }; var user = await GetCurrentUser();
IdentityResult result = await UserManager.ChangePasswordAsync(user, model.OldPassword, model.NewPassword); var result = await UserManager.ChangePasswordAsync(user, model.OldPassword, model.NewPassword);
if (result.Succeeded) if (result.Succeeded)
{ {
//Bug: No helper method //Bug: No helper method
@ -157,8 +177,8 @@ namespace MusicStore.Controllers
if (ModelState.IsValid == true) if (ModelState.IsValid == true)
{ {
var user = new ApplicationUser() { UserName = this.Context.User.Identity.GetUserId() }; var user = await GetCurrentUser();
IdentityResult result = await UserManager.ChangePasswordAsync(user, model.OldPassword, model.NewPassword); var result = await UserManager.ChangePasswordAsync(user, model.OldPassword, model.NewPassword);
if (result.Succeeded) if (result.Succeeded)
{ {
//Bug: No helper method //Bug: No helper method
@ -181,32 +201,15 @@ namespace MusicStore.Controllers
//[ValidateAntiForgeryToken] //[ValidateAntiForgeryToken]
public IActionResult LogOff() public IActionResult LogOff()
{ {
// Bug: This should call SignInManager.SignOut() once its available
this.Context.Response.SignOut(); this.Context.Response.SignOut();
//Bug: No helper //Bug: No helper
//return RedirectToAction("Index", "Home"); //return RedirectToAction("Index", "Home");
return Redirect("/"); return Redirect("/");
} }
//Bug: Controllers need to be disposable?
protected void Dispose(bool disposing)
{
if (disposing && UserManager != null)
{
UserManager.Dispose();
UserManager = null;
}
//base.Dispose(disposing);
}
#region Helpers #region Helpers
private async Task SignIn(ApplicationUser user, bool isPersistent)
{
var identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
this.Context.Response.SignIn(identity, new AuthenticationProperties() { IsPersistent = isPersistent });
}
private void AddErrors(IdentityResult result) private void AddErrors(IdentityResult result)
{ {
foreach (var error in result.Errors) foreach (var error in result.Errors)
@ -215,12 +218,17 @@ namespace MusicStore.Controllers
} }
} }
private async Task<ApplicationUser> GetCurrentUser()
{
return await UserManager.FindByIdAsync(Context.User.Identity.GetUserId());
}
private async Task<bool> HasPassword() private async Task<bool> HasPassword()
{ {
var user = await UserManager.FindByNameAsync(this.Context.User.Identity.GetUserId()); var user = await GetCurrentUser();
if (user != null) if (user != null)
{ {
return user.PasswordHash != null; return await UserManager.HasPasswordAsync(user);
} }
return false; return false;
} }
@ -255,9 +263,58 @@ namespace MusicStore.Controllers
/// </summary> /// </summary>
public static class Extensions public static class Extensions
{ {
public static string GetUserId(this IIdentity user) /// <summary>
/// Return the user name using the UserNameClaimType
/// </summary>
/// <param name="identity"></param>
/// <returns></returns>
public static string GetUserName(this IIdentity identity)
{ {
return user.Name; if (identity == null)
{
throw new ArgumentNullException("identity");
}
var ci = identity as ClaimsIdentity;
if (ci != null)
{
return ci.FindFirstValue(ClaimsIdentity.DefaultNameClaimType);
}
return null;
}
/// <summary>
/// Return the user id using the UserIdClaimType
/// </summary>
/// <param name="identity"></param>
/// <returns></returns>
public static string GetUserId(this IIdentity identity)
{
if (identity == null)
{
throw new ArgumentNullException("identity");
}
var ci = identity as ClaimsIdentity;
if (ci != null)
{
return ci.FindFirstValue(ClaimTypes.NameIdentifier);
}
return null;
}
/// <summary>
/// Return the claim value for the first claim with the specified type if it exists, null otherwise
/// </summary>
/// <param name="identity"></param>
/// <param name="claimType"></param>
/// <returns></returns>
public static string FindFirstValue(this ClaimsIdentity identity, string claimType)
{
if (identity == null)
{
throw new ArgumentNullException("identity");
}
var claim = identity.FindFirst(claimType);
return claim != null ? claim.Value : null;
} }
} }

View File

@ -13,6 +13,7 @@ using Microsoft.AspNet.RequestContainer;
using Microsoft.AspNet.Routing; using Microsoft.AspNet.Routing;
using Microsoft.AspNet.Security.Cookies; using Microsoft.AspNet.Security.Cookies;
using Microsoft.Net.Runtime; using Microsoft.Net.Runtime;
using MusicStore.Controllers;
using MusicStore.Logging; using MusicStore.Logging;
using MusicStore.Models; using MusicStore.Models;
using MusicStore.Web.Models; using MusicStore.Web.Models;
@ -21,6 +22,12 @@ using System.IO;
public class Startup public class Startup
{ {
/// <summary>
/// TODO: Temporary ugly work around (making this static) to enable creating a static InMemory UserManager. Will go away shortly.
/// </summary>
public static InMemoryUserStore<ApplicationUser> UserStore = new InMemoryUserStore<ApplicationUser>();
public static InMemoryRoleStore<IdentityRole> RoleStore = new InMemoryRoleStore<IdentityRole>();
public void Configuration(IBuilder app) public void Configuration(IBuilder app)
{ {
CreateAdminUser(app.ServiceProvider); CreateAdminUser(app.ServiceProvider);
@ -37,7 +44,7 @@ public class Startup
app.UseCookieAuthentication(new CookieAuthenticationOptions() app.UseCookieAuthentication(new CookieAuthenticationOptions()
{ {
AuthenticationType = "Application", AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login") LoginPath = new PathString("/Account/Login")
}); });
@ -71,8 +78,8 @@ public class Startup
string _password = configuration.Get("DefaultAdminPassword"); string _password = configuration.Get("DefaultAdminPassword");
string _role = "Administrator"; string _role = "Administrator";
var userManager = new UserManager<ApplicationUser>(new InMemoryUserStore<ApplicationUser>()); var userManager = new UserManager<ApplicationUser>(UserStore);
var roleManager = new RoleManager<IdentityRole>(new InMemoryRoleStore<IdentityRole>()); var roleManager = new RoleManager<IdentityRole>(RoleStore);
var role = new IdentityRole(_role); var role = new IdentityRole(_role);
var result = await roleManager.RoleExistsAsync(_role); var result = await roleManager.RoleExistsAsync(_role);

View File

@ -19,6 +19,7 @@
"Microsoft.AspNet.Identity": "0.1-alpha-*", "Microsoft.AspNet.Identity": "0.1-alpha-*",
"Microsoft.AspNet.Identity.Entity": "0.1-alpha-*", "Microsoft.AspNet.Identity.Entity": "0.1-alpha-*",
"Microsoft.AspNet.Identity.InMemory": "0.1-alpha-*", "Microsoft.AspNet.Identity.InMemory": "0.1-alpha-*",
"Microsoft.AspNet.Identity.Security": "0.1-alpha-*",
"Microsoft.Data.Entity": "0.1-alpha-*", "Microsoft.Data.Entity": "0.1-alpha-*",
"Microsoft.Data.Relational": "0.1-alpha-*", "Microsoft.Data.Relational": "0.1-alpha-*",
"Microsoft.Data.SqlServer": "0.1-pre-*", "Microsoft.Data.SqlServer": "0.1-pre-*",