Apologies and Thanks in advance for this question! I am still new to SO.
I have been working on a web application using MVC5, EF6, and VS 2013.
I spent some time upgrading to the RC bits once released. Thanks to all the great posts out there: eg. Decoupling Microsoft.AspNet.Identity.* and Updating asp.net MVC from 5.0.0-beta2 to 5.0.0-rc1 !
In my infinite wisdom, I decided to move to the RTM bits that @Hao Kung posted about here: How can I get early access to upcoming Asp.Net Identity changes?. I figured I would save the trouble and not be too far behind when we finally receive the RTM build.
This has either been a nightmare, or I am just completely missing something (or both) as I can not figure out basic tasks that had been working with the RC1 stuff.
While it seems like I am logging the user in via the controller (Where is Microsoft.AspNet.Identity.Owin.AuthenticationManager in Asp.Net Identity RTM version?) ... my WindowsIdentity is always empty and not authenticated after I call SignIn. The user and claimsIdentity object are correctly populated.
Here is the action method I am calling (moved properties to local variables for completeness):
[HttpPost, AllowAnonymous, ValidateAntiForgeryToken] public virtual async Task<ActionResult> Login(LoginViewModel model, string returnUrl) { if (ModelState.IsValid) { var userManager = new UserManager<EtdsUser>(new UserStore<EtdsUser>(new EtdsContext())); var user = userManager.Find(model.UserName, model.Password); if (user != null) { var authenticationManager = HttpContext.GetOwinContext().Authentication; authenticationManager.SignOut(new[] {DefaultAuthenticationTypes.ApplicationCookie, DefaultAuthenticationTypes.ExternalCookie, DefaultAuthenticationTypes.ExternalBearer}); var claimsIdentity = await userManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie); authenticationManager.SignIn(new AuthenticationProperties { IsPersistent = model.RememberMe}, claimsIdentity); return RedirectToLocal(returnUrl); } } ModelState.AddModelError("", "The user name or password provided is incorrect."); return View(model); }
(On a side note: I do not need to log in external users at this time.)
Any suggestions? -or- Should I roll back all my changes and just wait until VS 2013 is RTMd?
Update, refactored code to make it closer to @Hao Kung's original reply. However I still do not end up with a valid user identity. I think my AuthenticationManager is not assigned correctly?
AuthenticationManger is now defined as:
public IAuthenticationManager AuthenticationManager { get { return HttpContext.GetOwinContext().Authentication; } }
SignInAsync is now a separate method:
private async Task SignInAsync(EtdsUser user, bool isPersistent) { AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie); var claimsIdentity = await _userManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie); AuthenticationManager.SignIn(new AuthenticationProperties { IsPersistent = isPersistent}, claimsIdentity); }
After "SignOut", the debugger shows:
AuthenticationManager.User.Identity {System.Security.Principal.WindowsIdentity} [System.Security.Principal.WindowsIdentity]: {System.Security.Principal.WindowsIdentity} AuthenticationType: "" IsAuthenticated: false Name: ""
The "claimsIdentity" is then:
claimsIdentity {System.Security.Claims.ClaimsIdentity} Actor: null AuthenticationType: "ApplicationCookie" BootstrapContext: null Claims: {System.Security.Claims.ClaimsIdentity.get_Claims} IsAuthenticated: true Label: null Name: "alon" NameClaimType: "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name" RoleClaimType: "http://schemas.microsoft.com/ws/2008/06/identity/claims/role"
"SignIn" does not change anything:
AuthenticationManager.User.Identity {System.Security.Principal.WindowsIdentity} [System.Security.Principal.WindowsIdentity]: {System.Security.Principal.WindowsIdentity} AuthenticationType: "" IsAuthenticated: false Name: ""
Still no Authentication, but seems that no errors are thrown.
As answered by @Hao Kung, changed StartUp.Auth.cs from:
var authOptions = new CookieAuthenticationOptions { ExpireTimeSpan = TimeSpan.FromHours(4.0)}; app.UseCookieAuthentication(authOptions);
To:
var authOptions = new CookieAuthenticationOptions { AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie, LoginPath = new PathString("/Account/Login"), ExpireTimeSpan = TimeSpan.FromHours(4.0) }; ...
It means ASP.NET Core Identity provides a separate storing concept for identity information (like username, password) and code for security implementations (like password hashing, password validation, etc.).
So here's what login will basically look like in RTM (code copied from the ASPNET Identity sample code):
// // POST: /Account/Login [HttpPost] [AllowAnonymous] [ValidateAntiForgeryToken] public async Task<ActionResult> Login(LoginViewModel model, string returnUrl) { if (ModelState.IsValid) { 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."); } } // If we got this far, something failed, redisplay form return View(model); } private async Task SignInAsync(ApplicationUser user, bool isPersistent) { AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie); var identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie); AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, identity); }
EDIT: And you need the follow changes in your Startup.Auth.cs:
app.UseCookieAuthentication(new CookieAuthenticationOptions { AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie, LoginPath = new PathString("/Account/Login") });
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With