MVC5 Forms authentication not working - asp.net-mvc

I'm very new to .NET and security. I've chosen to implement Forms authentication (correct me if I should use something else). From what I gathered on the internet, I did the following, but it's not working:
Web.config
<authentication mode="Forms">
<forms loginUrl="~/Home/Index" timeout="30" />
</authentication>
HTTPPost ajax Login method:
[HttpPost]
public ActionResult Login(LoginInputModel loginModel)
{
if (ModelState.IsValid)
{
var success = UserService.Login(loginModel.Password, loginModel.Email);
if (success)
{
return Json(new { Url = Url.Action("Index","Home") });
}
loginModel.ErrorMessages = "Failed to log in with these credentials. Please try again.";
return PartialView("Widgets/Login/_LoginInput", loginModel);
}
return PartialView("Widgets/Login/_LoginInput", loginModel);
}
With actual login code in UserService class:
public static bool Login(string password, string email)
{
var user = Connector.GetUserByCredentials(password, email);
if (user == null) return false;
FormsAuthentication.SetAuthCookie(email, false); // this line
SessionService.Delete(UserSessionKey);
SessionService.Store(UserSessionKey, UserMapper.DbUserToUser(user));
return SessionService.HasKey(UserSessionKey);
}
Whenever I hit login, it works okay (it refreshes the page and I see different content), but if I then navigate to another page, I get redirected to the login page again. What am I (not) doing wrong?
If you need more code, I'll be happy to post it.

When you say you're using MVC5, what version of Visual Studio are you using? Are you using an application that was originally created by a default wizard?
If the application was created by the default wizard, then by default it enables ASP.NET Identity, and it removes the FormsAuthentication module from processing. If you want to keep using FormsAuth then you have to remove the "remove" key from the web.config for the FormsAuthentication module.
You need to remove this line
<system.webServer>
<modules>
<remove name="FormsAuthentication" /> <----****
</modules>
</system.webServer>

Related

ASP.NET MVC Login Not Sticking

I'm having an issue with my ASP.NET MVC 5 simple membership provider login code. The code is as follows:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Login(LoginViewModel model, string returnUrl)
{
bool active = true;
if (ModelState.IsValid && WebSecurity.Login(model.Email, model.Password, persistCookie: model.RememberMe))
{
UserDetail userModel = UserDetail.Initialize(model.Email);
FormsAuthentication.SetAuthCookie(model.Email, true);
active = userModel.ActiveBit;
if (active)
{
return Redirect("~/");
}
else
{
WebSecurity.Logout();
ModelState.AddModelError("", "Account is inactive.");
}
}
else
{
ModelState.AddModelError("", "*Either the Username or Password provided is incorrect.");
}
return View(model);
}
The login processes successfully and I can see the authentication cookie (.ASPXAUTH) in the browser. The problem arises on the next page request. The authentication cookie is passed back to the server, but the server seems to have no record of the login any more. When I set a breakpoint and check after processing the login and requesting a new page (after completing the post-login redirect), User.Identity.IsAuthenticated is false as is WebSecurity.IsAuthenticated and WebSecurity.HasUserID. WebSecurity.CurrentUserId is -1 and WebSecurity.CurrentUserName is an empty string.
It's not a database connectivity issue since I do authenticate successfully. I do a roundtrip to the server and back and I am still not authenticated so the common answers I've seen for CurrentUser == -1 don't seem to apply.
I'm a relative newbie on MVC but I had a coworker who's got a decent amount experience on this look at my code and he couldn't find anything either. Thanks for your help.
By default asp.net MVC5 web.config not supporting FormsAuthentication, check below section of your web config file and remove "<remove name="FormsAuthentication" />" if you want to use FormsAuthentication.
<system.webServer>
<modules>
<remove name="FormsAuthentication" />
</modules>
</system.webServer>
Authentication timeout configuration
<system.web>
<authentication mode="Forms">
<forms loginUrl="~/Account/Login" timeout="2880" />
</authentication>
</system.web>
Hope this helps.

MVC: Redirecting to login screen

I am taking over an existing ASP.NET MVC 5 project in order to try to understand the MVC framework. I have noticed that when a user is not logged in, and he attempts to go to some of the webpages, then it automatically redirects him to the login screen. I believe that this has something to do with the following in the Web.config file:
<authentication mode="Forms">
<forms loginUrl="~/Account/Login" timeout="2880" />
</authentication>
However, some webpages allow access to them (and are not redirected as above) even when the user is not logged in.
So my question is: Where do I configure which web pages will be automatically redirected to the login screen, and which web pages can be accessed without authentication?
This article explains how to do this with forms authentication. A short snippet of the configuration looks like below. Where default1.aspx is given access to.
<configuration>
<system.web>
<authentication mode="Forms">
<forms loginUrl="~/Account/Login" timeout="2880" />
</authentication>
<!-- This section denies access to all files in this application except for those that you have not explicitly specified by using another setting. -->
<authorization>
<deny users="?" />
</authorization>
</system.web>
<!-- This section gives the unauthenticated user access to the Default1.aspx page only. It is located in the same folder as this configuration file. -->
<location path="default1.aspx">
<system.web>
<authorization>
<allow users ="*" />
</authorization>
</system.web>
</location>
</configuration>
You can set an [Authorize] attribute on the controller action that will require the user to be authorized, otherwise they will be redirected to the page specified in the config. You can also specify individual roles that are required to access an action or require authorization for all actions on a controller and explicitly turn off authorization for actions.
Authorize Individual Actions
public class HomeController: Controller
{
public string Index()
{
// Not authorized
}
[Authorize]
public string SecretAction()
{
// Authorized (redirects to login)
}
}
Authorize All Actions
[Authorize]
public class HomeController: Controller
{
public string Index()
{
// Authorized (redirects to login)
}
public string SecretAction()
{
// Authorized (redirects to login)
}
}
Authorize All Actions Except For One
[Authorize]
public class HomeController: Controller
{
public string Index()
{
// Authorized (redirects to login)
}
[AllowAnonymous]
public string PublicAction()
{
// Not authorized
}
}
More here: http://msdn.microsoft.com/en-us/library/system.web.mvc.authorizeattribute.aspx
And here: Authorize attribute in ASP.NET MVC
An easy workaround if you are doing something simple (like a page or two of public content) is just this:
Response.SuppressFormsAuthenticationRedirect = true;

View elmah logs without creating role/user authentication

I started using ELMAH and I think its great. I read some documentation online but right now my app doesn't have roles/user authorization setup.
I would like to be able to read the error logs on production by accessing /elmah.axd but I don't want to just open it up to everyone, does elmah have any functionality that would allow me to create a password (in web.config) and pass it via querystring? Mimicking a "secure" RSS feed. Or something similar ofcourse....
but right now my app doesn't have roles/user authorization setup
Actually it's not that hard to configure forms authentication:
<authentication mode="Forms">
<forms loginUrl="~/Account/LogOn" timeout="2880">
<credentials passwordFormat="Clear">
<user name="admin" password="secret" />
</credentials>
</forms>
</authentication>
and then protect elmah.axd:
<location path="elmah.axd">
<system.web>
<authorization>
<deny users="?"/>
</authorization>
</system.web>
</location>
and finally you could have an AccountController:
public class AccountController : Controller
{
public ActionResult LogOn()
{
return View();
}
[HttpPost]
public ActionResult LogOn(string username, string password)
{
if (FormsAuthentication.Authenticate(username, password))
{
FormsAuthentication.SetAuthCookie(username, false);
return Redirect("~/elmah.axd");
}
else
{
ModelState.AddModelError("", "The user name or password provided is incorrect.");
}
return View();
}
}
and a LogOn.cshtml view:
#Html.ValidationSummary(false)
#using (Html.BeginForm())
{
<div>
#Html.Label("username")
#Html.TextBox("username")
</div>
<div>
#Html.Label("password")
#Html.Password("password")
</div>
<p>
<input type="submit" value="Log On" />
</p>
}
Now when an anonymous user tries to access /elmah.axd he will be presented with the logon screen where he needs to authenticate in order to access it. The username/password combination is in web.config. I have used passwordFormat="Clear" in this example but you could also SHA1 or MD5 the password.
Of course if you don't want to configure authentication you could also configure elmah to store logging information in a XML file or SQL database and then completely disable the elmah.axd handler from your publicly facing website. Then create another ASP.NET site which only you would have access to with the same elmah configuration pointing to the same log source and simply navigate to the /elmah.axd handler of your private site to read the logs of your public site.

ASP.NET MVC - Authenticate users against Active Directory, but require username and password to be inputted

I'm developing a MVC3 application that will require a user to be authenticated against an AD. I know that there is the option in MVC3 to create an Intranet Application that automatically authenticates a user against an AD, but it uses Windows Authentication and automatically logs them on. This application may be accessed on 'Open' workstations where the user will need to enter their Domain Username and Password. Any examples or online tutorial would be great. An example project would be exceptional.
You can use the standard Internet application template with forms authentication and insert an ActiveDirectoryMembershipProvider into the web.config:
<connectionStrings>
<add name="ADConnectionString" connectionString="LDAP://YOUR_AD_CONN_STRING" />
</connectionStrings>
<system.web>
<authentication mode="Forms">
<forms name=".ADAuthCookie" loginUrl="~/Account/LogOn"
timeout="15" slidingExpiration="false" protection="All" />
</authentication>
<membership defaultProvider="MY_ADMembershipProvider">
<providers>
<clear />
<add name="MY_ADMembershipProvider"
type="System.Web.Security.ActiveDirectoryMembershipProvider"
connectionStringName="ADConnectionString"
attributeMapUsername="sAMAccountName" />
</providers>
</membership>
</system.web>
In this way you get the Internet application template login form, and it validates against AD for you.
Then it's just a matter of some AccountController cleanup to remove reset password/change password/register functionality leaving just Login.
As mentioned above, you can use the membership provider defined in the web.config file.
The code below is within the implementation of the 'AccountController' from the MVC 3 Template code and has been slightly modified to work with ActiveDirectory:
[HttpPost]
public ActionResult LogOn( LogOnModel model, string returnUrl )
{
if( ModelState.IsValid )
{
// Note: ValidateUser() performs the auth check against ActiveDirectory
// but make sure to not include the Domain Name in the User Name
// and make sure you don't have the option set to use Email Usernames.
if( MembershipService.ValidateUser( model.UserName, model.Password ) )
{
// Replace next line with logic to create FormsAuthenticationTicket
// to encrypt and return in an Http Auth Cookie or Session Cookie
// depending on the 'Remember Me' option.
//FormsService.SignIn( model.UserName, model.RememberMe );
// Fix this to also check for other combinations/possibilities
if (!String.IsNullOrEmpty(returnUrl))
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("Index", "Home");
}
}
else
{
ModelState.AddModelError("", "The user name or password provided is incorrect.");
}
}
If using .NET 3.5 -- then read this article for the alternative:

default login url on HttpUnauthorizedResult in asp.net mvc

I have written a custom AuthorizeAttribute which has the following condition in asp.net mvc3 application:
public override void OnAuthorization(AuthorizationContext filterContext)
{
//auth failed, redirect to Sign In
if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
{
filterContext.Result = new HttpUnauthorizedResult();
}
}
And in my web.config, i have:
<authentication mode="Forms">
<forms loginUrl="~/User/SignIn" timeout="2880" />
</authentication>
On authentication fail, it redirects to "/Account/Login" page by default.
How do i change this default redirect url and redirect it to "/User/SignIn"?
The screenshot shows the clear view of what i am trying to say..
Though i have set '/User/SignIn', it redirects to '/Account/Login'
I am not sure whether i can add this as an answer. But this may help others who were having this related issue.
I got the solution after a struggle. I have added WebMatrix.WebData reference recently, which seems to be the real culprit of this issue. This can be handled by adding the key to your config file:
<add key="loginUrl" value="~/User/SignIn" />
You should be modifying the root one for loginUrl.
i have created AuthorizationAttribute... it's redirecting properly
e.g.
<authentication mode="Forms">
<forms loginUrl="~/Authenticate/SignIn" timeout="2880"/>
</authentication>
and my attribute is:
public class AuthorizationAttribute : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
base.OnAuthorization(filterContext);
if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
{
filterContext.Result = new HttpUnauthorizedResult();
}
}
}
and apply attribute to any method of your controller as necessary...
[AuthorizationAttribute()]
public ActionResult Index()
{
return View();
}
I recently had this problem and found it was because I had the WebMatrix.dll referenced in my project.
Removing this DLL fixed the issue
see here
What is the PreserveLoginUrl appSetting key/value in an ASP.NET MVC application?

Resources