I am using Membership provider but how do I get my username and password to login/signin? When I check to see with this code:
if (User.Identity.IsAuthenticated)
// this code always returns false
I have this before when the user uses asp:Login to login:
if (Membership.ValidateUser(email, password))
{
// this is true but what am I missing here to make above not be false?
The so called duplicate question/answer uses SetAuthCookie which according to this (System.Web.HttpContext.Current.User.Identity.IsAuthenticated fails sometimes) causes issues and I need to avoid it.
Use code like below to make it work. The method RedirectFromLoginPage will create the authentication cookie as well as redirect the user to the original page or the default URL (i.e. home page) defined in web config.
if (Membership.ValidateUser(email, password))
{
// Log the user into the site
FormsAuthentication.RedirectFromLoginPage(email, false);
}
Also, make sure that forms authentication is enabled in web config. At a minimum at least set mode="Forms" if not other settings under authentication.
<authentication mode="Forms">
<forms loginUrl="member_login.aspx"
defaultUrl="index.aspx" />
</authentication>
Related
I have a mature ASP.NET web application using FormsAuthentication (FA) to manage logins. Under certain situations, I would like to redirect the "just logged in" user to a different URL to the one that FA uses. As per standard functionality, FA will redirect to our normal homepage (specified in web.config) unless a redirectUrl was used when it hits a page that requires an authenticated user.
In my system, after the user's username/password is validated I typically use
FormsAuthentication.RedirectFromLoginPage(userName, createPersistentCookie: true); // Also calls SetAuthCookie()
which handles most situations. However, depending on certain conditions (primarily based on the newly logged in user's role) I want to redirect to a different destination. My thoughts for doing this are to call SetAuthCookie() myself and then use Response.Redirect(myUrl, false); and ApplicationInstance.CompleteRequest().
Despite doing this, the very next request comes in using for the URL defined in my tag of web.config.
<authentication mode="Forms">
<forms loginUrl="~/Login" timeout="120" cookieless="UseCookies" defaultUrl="~/?raspberry=true" />
</authentication>
Here is the actual code I am using (if a different url is required, it is specified by the overrideUrl parameter:
internal static void CreateTicket(string userName, string overrideUrl)
{
// Ref: http://support.microsoft.com/kb/301240
if (overrideUrl == null)
{
FormsAuthentication.RedirectFromLoginPage(userName, createPersistentCookie: true); // Includes call to SetAuthCookie()
}
else
{
FormsAuthentication.SetAuthCookie(userName, createPersistentCookie: true, strCookiePath:FormsAuthentication.FormsCookiePath);
HttpContext.Current.Response.Redirect(overrideUrl, false);
HttpContext.Current.ApplicationInstance.CompleteRequest();
}
}
If I pass in a value of /special/path for overrideUrl I would like the next request to come in to be '/special/path'. Instead I am seeing /?raspberry=true
Is something else forcing defaultUrl?
Is there a way to "snoop" into the Response object while debugging to see if a Redirect is already in place? or set a breakpoint whenever it gets set so I can look at the call stack?
EDIT: At the end of my method, the Response object is showing the following properties:
RedirectLocation: "/special/path"
Status: "302 Found"
StatusCode: 302
StatusDescription: "Found"
IsRequestBeingRedirected: true
HeadersWritten: false
which all looks absolutely correct.
Thanks for any advise.
Okay, I can see what is causing it. It is the fact that I am using the Login Web Control and running my code as part of the Authenticate event. Looking at the reference source for the Login Web Control, the Authenticate event is raised by its AttemptLogin method (search for it in ref source). After raising the event and seeing that Authentication was successful, it then goes on to:
Call SetAuthCookie itself (I've already done this myself but presumably the only thing I should be doing in my code is determining if authentication was successful or not, and not messing with AuthCookie or redirects)
Performing a Redirect (overwriting my carefully crafted Redirect)
I'm going to have to figure out a solution as there these methods are private (can't override by inheriting the usercontrol) and there appears to be no option for overring or suppressing the user of it's GetRedirectUrl().
I need to sign out a user when the user closed the tab or browser, how do I do that in ASP.NET MVC?
There are a few things you can do to make sure the user is signed out when the browser is closed, but it depends on how you're setting the FormsAuthentication cookie:
Use Cookieless=True.
Set a FormsAuthenticationTicket to not be persistent
Use FormsAuthentication.SetAuthCookie to set Persistence to false
Use a JavaScript approach to remove the cookie on window.unload.
Cookieless=True approach:
<system.web>
<authentication mode="Forms">
<forms loginUrl="/Account/Login"
protection="All"
cookieless="true" //set to true
</authentication>
</system.web>
This appends the cookie value to the querystring in each request. The problem with this approach is it's not very secure and it messes with SEO. If a user sends anyone the URL they're using, that person can log in as the original user (probably not what you want). As far as 'messing with SEO', it causes the same page to look different to a googlebot based on what URL is passed in. Each QueryString change makes it a new URL, and if anyone uses this for posting a link; it will dilute the search results for a given actual URL.
FormsAuthenticationTicket Approach
When you set an Authentication cookie for the user, set Persistent to False.
If you're doing this in the FormsAuthentication.SetAuthCookie, this is default. If you use the FormsAuthenticationTicket class, you have to specify the cookie expiration.
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
1, //version
"blah", //Cookie Name
);
FormsAuthentication.SetAuthCookie() Approach
By default, if you don't set persistent, the authentication cookie will expire at the end of the session (when the user closes the browser).
FormsAuthentication.SetAuthCookie("CookieValue", false); //second argument is persistent'
JavaScript approach:
There are no foolproof methods; all you can do is set the cookie expiration date to before now and hope the user's browser co-operates. If you really, really, really, want the cookie gone, you can always try a JavaScript approach, but that won't work if the user has JavaScript disabled.
window.addEventListener('unload', function(event) {
document.cookie = name + '=; expires=Thu, 01 Jan 1970 00:00:01 GMT;';
});
Other caveats
It also matters which browser you use. Chrome has the ability to run in the background, and that keeps Session Cookies around until their timeout is hit -- they are not dropped when the browser is closed (I found this out the hard way).
I have a strange issue.
I have a page with the following code.
if (!HttpContext.Current.User.Identity.IsAuthenticated)
{
Server.Transfer(#"~/Views/Public/Unauthorised.aspx");
return;
}
For some reason, with one user (and we've narrowed it down to his single machine and windows logon profile), IsAuthenticated always returns false. Even though he is logged into the website, and can navigate to other pages that require authenticated user. Except this one page.
We checked that the machine accepts all cookies and we still get the same issue. I'm not sure where to go from here... any suggestions?
There are at least two known cases that can make this behavior.
First case when you have set requireSSL="true" on the Authentication session on web.config and you call that function from a non secure page. So double check if the page is secure or not, if you use the requireSSL="true"
Debug.Assert(Request.IsSecureConnection, "The IsAuthenticated will fail.");
if (!HttpContext.Current.User.Identity.IsAuthenticated)
{
Server.Transfer(#"~/Views/Public/Unauthorised.aspx");
return;
}
Second case when you do not have set the domain="site.com" again on authentication session inside the web.config, and you try to request a cookie the one time from the www.yoursitename.com and the other from yoursitename.com. In that case the authentication cookies are different and it will fail. So set that parameter among others on web.config.
<authentication mode="Forms">
<forms domain="yoursitename.com" />
</authentication>
If I visit my site with out the www. prefix, login and then add the www., my user is not logged in any more, but if I remove the www., the user is logged in. It acts the same way if I do the Opposite. go to the web site with the www., login, and then remove the www. the user will not be logged in.
Here is the Login method and the authentication at the web.config.
public static void LogIn(userId)
{
Item user = Framework.Business.Item.Load(userId);
var _ticket = new FormsAuthenticationTicket(1, _usrItm.ID, DateTime.Now, DateTime.Now.AddDays(30), true, _usrItm.ID);
string encTicket = FormsAuthentication.Encrypt(_ticket);
HttpContext.Current.Response.Cookies.Add(new HttpCookie(FormsAuthentication.FormsCookieName, encTicket));
}
<authentication mode="Forms">
<forms name="k_Authentication" protection="All" timeout="120" cookieless="UseCookies" loginUrl="default.aspx" path="/" defaultUrl="/myweb.aspx"/>
</authentication>
I'll bet you a shilling to a guinea that the two answers about the domain setting of the cookies are correct +1s all around from me.
However. Most often the two sites are the same or they are not. If they're not, then you usually want the user to no longer be logged in, so don't change anything. If they are the same, then set one to permanently redirect to the other. As well as making this problem go away, you also gain some SEO benefits, benefits for people's history records being more consistent, and reduced pressure on shared caches. So I'd suggest that approach. I'd only deal with the matter of the domain set on the cookie if the two are separate-but-related, and sharing the log-in between them is appropriate.
There is probably a problem with the domain of your cookie. www.example.com and example.com are not the same domain.
You'll have to set the Domain property to www.yourdomain.com manually to share the cookies.
I've created a demo website for my boss and one of the requirements is I need to add some simple authentication to his 3 admin views/routes.
What is the simplest, quickest way I can do this without implementing a whole membership provider? I honestly don't even care if the user/pass is hardcoded on the server side, I just need it so they can't access those 3 views without having authenticated in some way.
I would go this route.
Add this to your web.config (could omit the SHA1 and use a plain text password if you want):
<authentication mode="Forms">
<forms loginUrl="~/admin" timeout="2880">
<credentials passwordFormat="SHA1">
<user name="admin" password="4f3fc98f8d95160377022c5011d781b9188c7d46"/>
</credentials>
</forms>
</authentication>
Create a simple view for username and password and in the action method that receives the username and password go with this...
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult LogOn(string username, string password)
{
if (FormsAuthentication.Authenticate(username, password))
{
FormsAuthentication.SetAuthCookie(username, false);
return RedirectToAction("Index", "Home");
}
else
{
ViewData["LastLoginFailed"] = true;
return View();
}
}
FormsAuthentication.Authenticate() automatically checks the username and password against the credentials node we created earlier. If it matches it creates your auth cookie with a "Remember Me" value of false and redirects you to the index view of your home controller. If it doesn't match it returns to the login page with ViewData["LastLoginFailed"] set to true so you can handle that in your view.
PS - Now that you have an easy way of authorizing don't forget to put the [Authorize] filter over the actions or controllers you want to protect.
easiest would be to select the menu [project] followed by [ASP.NET Configuration] in Visual Studio.
It'll set up a membership db for you. then add a couple of roles and users in the configuration manager that pops up.
that's it! Then simply decorate your actions/controllers with [Authorise] and check for some rights based on the user name. <= hard coded for the demo