3 using System.Threading.Tasks;
6 using Microsoft.AspNet.Identity;
7 using Microsoft.AspNet.Identity.Owin;
8 using Microsoft.Owin.Security;
11 namespace Projects.Controllers
14 public class ManageController : Controller
16 private ApplicationSignInManager _signInManager;
17 private ApplicationUserManager _userManager;
19 public ManageController()
23 public ManageController(ApplicationUserManager userManager, ApplicationSignInManager signInManager)
25 UserManager = userManager;
26 SignInManager = signInManager;
29 public ApplicationSignInManager SignInManager
33 return _signInManager ?? HttpContext.GetOwinContext().Get<ApplicationSignInManager>();
37 _signInManager = value;
41 public ApplicationUserManager UserManager
45 return _userManager ?? HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
55 public async Task<ActionResult> Index(ManageMessageId? message)
57 ViewBag.StatusMessage =
58 message == ManageMessageId.ChangePasswordSuccess ? "Your password has been changed."
59 : message == ManageMessageId.SetPasswordSuccess ? "Your password has been set."
60 : message == ManageMessageId.SetTwoFactorSuccess ? "Your two-factor authentication provider has been set."
61 : message == ManageMessageId.Error ? "An error has occurred."
62 : message == ManageMessageId.AddPhoneSuccess ? "Your phone number was added."
63 : message == ManageMessageId.RemovePhoneSuccess ? "Your phone number was removed."
66 var userId = User.Identity.GetUserId();
67 var model = new IndexViewModel
69 HasPassword = HasPassword(),
70 PhoneNumber = await UserManager.GetPhoneNumberAsync(userId),
71 TwoFactor = await UserManager.GetTwoFactorEnabledAsync(userId),
72 Logins = await UserManager.GetLoginsAsync(userId),
73 BrowserRemembered = await AuthenticationManager.TwoFactorBrowserRememberedAsync(userId)
79 // POST: /Manage/RemoveLogin
81 [ValidateAntiForgeryToken]
82 public async Task<ActionResult> RemoveLogin(string loginProvider, string providerKey)
84 ManageMessageId? message;
85 var result = await UserManager.RemoveLoginAsync(User.Identity.GetUserId(), new UserLoginInfo(loginProvider, providerKey));
88 var user = await UserManager.FindByIdAsync(User.Identity.GetUserId());
91 await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);
93 message = ManageMessageId.RemoveLoginSuccess;
97 message = ManageMessageId.Error;
99 return RedirectToAction("ManageLogins", new { Message = message });
103 // GET: /Manage/AddPhoneNumber
104 public ActionResult AddPhoneNumber()
110 // POST: /Manage/AddPhoneNumber
112 [ValidateAntiForgeryToken]
113 public async Task<ActionResult> AddPhoneNumber(AddPhoneNumberViewModel model)
115 if (!ModelState.IsValid)
119 // Generate the token and send it
120 var code = await UserManager.GenerateChangePhoneNumberTokenAsync(User.Identity.GetUserId(), model.Number);
121 if (UserManager.SmsService != null)
123 var message = new IdentityMessage
125 Destination = model.Number,
126 Body = "Your security code is: " + code
128 await UserManager.SmsService.SendAsync(message);
130 return RedirectToAction("VerifyPhoneNumber", new { PhoneNumber = model.Number });
134 // POST: /Manage/EnableTwoFactorAuthentication
136 [ValidateAntiForgeryToken]
137 public async Task<ActionResult> EnableTwoFactorAuthentication()
139 await UserManager.SetTwoFactorEnabledAsync(User.Identity.GetUserId(), true);
140 var user = await UserManager.FindByIdAsync(User.Identity.GetUserId());
143 await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);
145 return RedirectToAction("Index", "Manage");
149 // POST: /Manage/DisableTwoFactorAuthentication
151 [ValidateAntiForgeryToken]
152 public async Task<ActionResult> DisableTwoFactorAuthentication()
154 await UserManager.SetTwoFactorEnabledAsync(User.Identity.GetUserId(), false);
155 var user = await UserManager.FindByIdAsync(User.Identity.GetUserId());
158 await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);
160 return RedirectToAction("Index", "Manage");
164 // GET: /Manage/VerifyPhoneNumber
165 public async Task<ActionResult> VerifyPhoneNumber(string phoneNumber)
167 var code = await UserManager.GenerateChangePhoneNumberTokenAsync(User.Identity.GetUserId(), phoneNumber);
168 // Send an SMS through the SMS provider to verify the phone number
169 return phoneNumber == null ? View("Error") : View(new VerifyPhoneNumberViewModel { PhoneNumber = phoneNumber });
173 // POST: /Manage/VerifyPhoneNumber
175 [ValidateAntiForgeryToken]
176 public async Task<ActionResult> VerifyPhoneNumber(VerifyPhoneNumberViewModel model)
178 if (!ModelState.IsValid)
182 var result = await UserManager.ChangePhoneNumberAsync(User.Identity.GetUserId(), model.PhoneNumber, model.Code);
183 if (result.Succeeded)
185 var user = await UserManager.FindByIdAsync(User.Identity.GetUserId());
188 await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);
190 return RedirectToAction("Index", new { Message = ManageMessageId.AddPhoneSuccess });
192 // If we got this far, something failed, redisplay form
193 ModelState.AddModelError("", "Failed to verify phone");
198 // GET: /Manage/RemovePhoneNumber
199 public async Task<ActionResult> RemovePhoneNumber()
201 var result = await UserManager.SetPhoneNumberAsync(User.Identity.GetUserId(), null);
202 if (!result.Succeeded)
204 return RedirectToAction("Index", new { Message = ManageMessageId.Error });
206 var user = await UserManager.FindByIdAsync(User.Identity.GetUserId());
209 await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);
211 return RedirectToAction("Index", new { Message = ManageMessageId.RemovePhoneSuccess });
215 // GET: /Manage/ChangePassword
216 public ActionResult ChangePassword()
222 // POST: /Manage/ChangePassword
224 [ValidateAntiForgeryToken]
225 public async Task<ActionResult> ChangePassword(ChangePasswordViewModel model)
227 if (!ModelState.IsValid)
231 var result = await UserManager.ChangePasswordAsync(User.Identity.GetUserId(), model.OldPassword, model.NewPassword);
232 if (result.Succeeded)
234 var user = await UserManager.FindByIdAsync(User.Identity.GetUserId());
237 await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);
239 return RedirectToAction("Index", new { Message = ManageMessageId.ChangePasswordSuccess });
246 // GET: /Manage/SetPassword
247 public ActionResult SetPassword()
253 // POST: /Manage/SetPassword
255 [ValidateAntiForgeryToken]
256 public async Task<ActionResult> SetPassword(SetPasswordViewModel model)
258 if (ModelState.IsValid)
260 var result = await UserManager.AddPasswordAsync(User.Identity.GetUserId(), model.NewPassword);
261 if (result.Succeeded)
263 var user = await UserManager.FindByIdAsync(User.Identity.GetUserId());
266 await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);
268 return RedirectToAction("Index", new { Message = ManageMessageId.SetPasswordSuccess });
273 // If we got this far, something failed, redisplay form
278 // GET: /Manage/ManageLogins
279 public async Task<ActionResult> ManageLogins(ManageMessageId? message)
281 ViewBag.StatusMessage =
282 message == ManageMessageId.RemoveLoginSuccess ? "The external login was removed."
283 : message == ManageMessageId.Error ? "An error has occurred."
285 var user = await UserManager.FindByIdAsync(User.Identity.GetUserId());
288 return View("Error");
290 var userLogins = await UserManager.GetLoginsAsync(User.Identity.GetUserId());
291 var otherLogins = AuthenticationManager.GetExternalAuthenticationTypes().Where(auth => userLogins.All(ul => auth.AuthenticationType != ul.LoginProvider)).ToList();
292 ViewBag.ShowRemoveButton = user.PasswordHash != null || userLogins.Count > 1;
293 return View(new ManageLoginsViewModel
295 CurrentLogins = userLogins,
296 OtherLogins = otherLogins
301 // POST: /Manage/LinkLogin
303 [ValidateAntiForgeryToken]
304 public ActionResult LinkLogin(string provider)
306 // Request a redirect to the external login provider to link a login for the current user
307 return new AccountController.ChallengeResult(provider, Url.Action("LinkLoginCallback", "Manage"), User.Identity.GetUserId());
311 // GET: /Manage/LinkLoginCallback
312 public async Task<ActionResult> LinkLoginCallback()
314 var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync(XsrfKey, User.Identity.GetUserId());
315 if (loginInfo == null)
317 return RedirectToAction("ManageLogins", new { Message = ManageMessageId.Error });
319 var result = await UserManager.AddLoginAsync(User.Identity.GetUserId(), loginInfo.Login);
320 return result.Succeeded ? RedirectToAction("ManageLogins") : RedirectToAction("ManageLogins", new { Message = ManageMessageId.Error });
323 protected override void Dispose(bool disposing)
325 if (disposing && _userManager != null)
327 _userManager.Dispose();
331 base.Dispose(disposing);
335 // Used for XSRF protection when adding external logins
336 private const string XsrfKey = "XsrfId";
338 private IAuthenticationManager AuthenticationManager
342 return HttpContext.GetOwinContext().Authentication;
346 private void AddErrors(IdentityResult result)
348 foreach (var error in result.Errors)
350 ModelState.AddModelError("", error);
354 private bool HasPassword()
356 var user = UserManager.FindById(User.Identity.GetUserId());
359 return user.PasswordHash != null;
364 private bool HasPhoneNumber()
366 var user = UserManager.FindById(User.Identity.GetUserId());
369 return user.PhoneNumber != null;
374 public enum ManageMessageId
377 ChangePasswordSuccess,