I'm using LDAP Authentication in MVC Application.
My Login methods (both GET and POST) looks like as bellow:
[AllowAnonymous]
public ActionResult Login(string returnUrl)
{
//Check if User is Logged in Via Windows Authentication.
ViewBag.ReturnUrl = returnUrl;
return View();
}
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Login(LoginModel model, string returnUrl)
{
using (HostingEnvironment.Impersonate())
{
if (ModelState.IsValid)
{
// Check with AD
if (Membership.ValidateUser(model.UserName, model.Password))
{
FormsAuthentication.SetAuthCookie(model.UserName, true);
// Create a Profile Information Session on Server.
// Other logic goes here.....
}
}
// If we got this far, something failed, redisplay form
ModelState.AddModelError("", #"The user name or password provided is incorrect.");
return View(model);
}
}
Here, How to check if USER is already logged in via Windows Credentials? Say, If I logged in to my machine and when I access this application then I should directly land on Home page instead of Login page. How to achieve this?
Please help me on this.
Related
In my ASP.NET MVC 5 application, we have a bunch of user roles, such as Admin, ReportUser, ProjectManager and stuffs like these. I want the application to redirect the user to views immediately after login according to the following rules:
If user is Admin, redirect to /Admin/Index
If user is ReportUser, redirect to /Report/Index
If user is ProjectManager, redirect to /Project/Index
I've already set up a role manager using AspNetWindowsTokenRoleProvider in web.config, and I am setting user roles in MyMvcApplication_PostAuthenticateRequest of global.asax, which works well.
But, I am not clear where and what is the best way to do the redirect. In OnAuthorization method of a custom authorize attribute class? Or in MyMvcApplication_PostAuthenticateRequest method of global.asax?
If you're using the default Asp.net Identity Login and template logic you should have a login method that looks something like:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
if (ModelState.IsValid)
{
var user = await _userManager.FindAsync(model.Email, 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);
}
So create a new method:
public async Task<ActionResult> GoHome()
{
if (this.User.IsInRole("Admin"))
{
return Redirect("Action", "Controller");
}
// etc etc
}
Then just update the Login method by changing:
return RedirectToLocal(returnUrl);
to
return Redirect("GoHome");
The reason for the double redirect is that authentication takes place before the MVC pipeline, which means that await SignInAsync(user, model.RememberMe) will not change the current user context, it requires a redirect for MVC to see the change. Thus on the next page, it can read the roles and redirect correctly.
Some Controller-Actions in my page are decorated with the [Authorize] attribute. The forward to the Login page works perfect, but after successful login, I want to forward to the requested url. With Request.UrlReferrer, I get the url where I come from, but how can I get the requested action (which requires the login)?
The Login() action takes a string parameter called returnUrl which will be used when redirecting from the login.
You can add the returnUrl to the ViewBag and return a view.
For Eg:
public ActionResult Login(string returnUrl)
{
ViewBag.ReturnUrl = returnUrl;
return View();
}
The target action uses the posted data to authenticate the user and log in the user using FormsAuthentication. It then redirects the user back to the returnUrl.
[HttpPost]
public ActionResult Login(LoginModel model, string returnUrl)
{
if (//Validation Check)
{
FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
return Redirect(returnUrl); // Redirect to referer
}
ViewBag.ReturnUrl = returnUrl;
ModelState.AddModelError("", "The user name or password provided is incorrect.");
return View(model);
}
I am using the MVC5 login Identity authentication code below:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Login(LoginViewModel model, string returnUrl)
{
if (ModelState.IsValid)
{
// Validate the password
IdentityResult result = IdentityManager.Authentication.CheckPasswordAndSignIn(AuthenticationManager, model.UserName, model.Password, model.RememberMe);
if (result.Success)
{
return Redirect("~/home");
}
else
{
AddErrors(result);
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
The code gives a message if the password is not correct but if the username does not exist it gives the same message saying "Incorrect password."
Does anyone out there have a solution that also does a check for the username existing and gives a correct message if it does not exist ? Note that I am using ASP.Net Identity so it would need to be a solution for this and not for the Simple Membership authentication
If you update to the 1.0 RTM Identity packages, you can check if a user exists by:
UserManager.FindByName("username")
When implementing an MVC web app with FormsAuthentication, it would appear that the FormsAuthentication mechanism automagically appends ?ReturnUrl=/ to your mvc routes. I did notice, though, that the default web application which MVC 3 provides out of the box implements FormsAuthentication but does not appear to suffer from the appended ReturnUrl=/ problem. I've looked through the code and can't see where this is being handled. Anyone know?
In the LogOn action of the AccountController, you'll see that if a return url is present, the user will be redirected to it after a successful log on:
[HttpPost]
public ActionResult LogOn(LogOnModel model, string returnUrl)
{
if (ModelState.IsValid)
{
if (MembershipService.ValidateUser(model.UserName, model.Password))
{
FormsService.SignIn(model.UserName, model.RememberMe);
if (Url.IsLocalUrl(returnUrl))
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("Index", "Home");
}
}
else
{
ModelState.AddModelError("", "The user name or password provided is incorrect.");
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
Try adding the [Authorize] attribute to the Action or controller. This will generate the url needed to redirect after login.
I have two types of roles [Admin, HelpDeskAdmin].
I have a single logon view(both users go to same link to login) and I want to check their role once logged in and redirect to their respective admin pages once authenticated. The code below doesn't identify the logged in user as being in the role the first time and reloads the logon page, the second time they logon it redirects correctly.
Does this have something to do with the authentication cookie not being in place when it checks the first time? How could I accomplish this scenario?
[HttpPost]
public ActionResult LogOn(LogOnModel model, string returnUrl)
{
if (ModelState.IsValid)
{
if (MembershipService.ValidateUser(model.UserName, model.Password))
{
FormsService.SignIn(model.UserName, model.RememberMe);
if (!String.IsNullOrEmpty(returnUrl))
{
return Redirect(returnUrl);
}
else
{
if (Roles.IsUserInRole("Admin"))
{
//go to admin landing page
return RedirectToAction("Index", "Manage");
}
else if (Roles.IsUserInRole("HelpDesk"))
{
//go to helpdesk landing page
return RedirectToAction("Index", "Interview");
}
else /******FIRST TIME THROUGH IT ALWAYS GOES HERE *******/
return RedirectToAction("Index", "Home"); //not in any of those roles
}
}
else
{
ModelState.AddModelError("", "The user name or password provided is incorrect.");
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
The user is technically NOT logged in until the next request is handled and the Authenication Cookie is set....
Either do the redirection logic in another Action method or perhaps extract the user info using Roles.IsUserInRole(model.UserName, "Admin") [[Note specifying the username]] from within this Action.