User.Identity.IsAuthenticated is false after adding auth cookie - asp.net

I have the following code to add authentication cookie to the response and redirect to homepage
HttpCookie authCookie = FormsAuthentication.GetAuthCookie(username, true);
Response.Cookies.Add(authCookie);
Response.Redirect("~/Home/Home.aspx");
But in the Home.aspx, User.Identity.IsAuthenticated is still false. why?

Finally got it working. Here is it in nutshell
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1,
username,
DateTime.Now,
DateTime.Now.AddMinutes(30),
isPersistent,
userData,
FormsAuthentication.FormsCookiePath);
// Encrypt the ticket.
string encTicket = FormsAuthentication.Encrypt(ticket);
// Create the cookie.
Response.Cookies.Add(new HttpCookie(FormsAuthentication.FormsCookieName, encTicket));
I followed the code sample from this MSDN page:

You don't have to add the cookie to the response yourself.
You were doing this:
HttpCookie authCookie = FormsAuthentication.GetAuthCookie(username, true);
Response.Cookies.Add(authCookie);
Response.Redirect("~/Home/Home.aspx");
But instead of doing a GetAuthCookie and then adding it, you can just use SetAuthCookie:
HttpCookie authCookie = FormsAuthentication.SetAuthCookie(username, true);
Response.Redirect("~/Home/Home.aspx");
When you look at the MSDN page for SetAuthCookie, you see that it not only adds the cookie to the Response (or the URL), but it also creates and encrypts a ticket:
Creates an authentication ticket for the supplied user name and adds it to the cookies collection of the response, or to the URL if you are using cookieless authentication.
That's probably why it doesn't work when you just try to add the cookie yourself.

Related

Manually remove Auth Cookie from .Net MVC Application

One of my recent .Net MVC based web application i have a situation by which i need to use multiple auth cookie like
1 Forms Auth Cookie
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, userName, DateTime.Now, DateTime.Now.AddDays(30), RememberMe, 'data1', FormsAuthentication.FormsCookiePath);
string hash = FormsAuthentication.Encrypt(ticket);
HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, hash);
HttpContext.Current.Response.Cookies.Add(cookie);
2 Custom Auth Cookie
FormsAuthenticationTicket cstTicket = new FormsAuthenticationTicket(1, Username, DateTime.Now, DateTime.Now.AddDays(30), isPersistent, 'data 2', FormsAuthentication.FormsCookiePath);
string _encryptedTicket = FormsAuthentication.Encrypt(cstTicket);
HttpCookie cstCookie = new HttpCookie("iCstm", _encryptedTicket);
HttpContext.Current.Response.Cookies.Add(cstCookie);
I need to remove both the cookie when someone logout from the application. If i call FormsAuthentication.SignOut(); then it remove basic auth cookie. I tried to remove second cookie by setting Expires value like
HttpContext.Current.Request.Cookies["iCstm"].Expires = DateTime.UtcNow.AddYears(-1);
HttpContext.Current.Response.Cookies["iCstm"].Value = "";
HttpContext.Current.Response.Cookies.Add(HttpContext.Current.Request.Cookies["iCstm"]);
But this will not work in case of auth cookie. Is there ny way to handle this issue.
Thanks in advance.

remember me(isPersistent) dont work on Forms authentication

Here my cookie create code:
This is controller (model.RememberMe is a checkbox value)
int timeout = (model.RememberMe) ? (int) FormsAuthentication.Timeout.TotalMinutes : Session.Timeout;//4h
HttpCookie cookie = accountService.GetCookie(userId, model.RememberMe, timeout);
Response.Cookies.Add(cookie);
Logger.Debug("POST: AccountController LogOn end.");
result = returnUrl != null
? RedirectToLocal(returnUrl)
: RedirectToAction("Index", "Profile", new {id = userId});
Service method that's create cookie
public HttpCookie GetCookie(int userId, bool rememberMe, int timeout)
{
Logger.Trace("AccountService GetCookie start with arguments:" +
" userId = {0}, rememberMe = {1}.", userId, rememberMe);
var authTicket = new FormsAuthenticationTicket(
1,
Convert.ToString(userId),
DateTime.Now,
DateTime.Now.AddMinutes(timeout),
rememberMe,
string.Empty,
"/"
);
HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName,
FormsAuthentication.Encrypt(authTicket));
Logger.Debug("Cookie for user with userId = {0} has created", userId);
Logger.Trace("AccountService GetCookie end.");
return cookie;
}
But unfortunately RememberMe dont work and cookies expires at the end of the browser session.Why?
What is the purpose of FormsAuthenticationTicket isPersistent property? Here some kind of answer but i dont understand why it doesnt work?
The difference between your code and the SO answer that you linked is that they use:
FormsAuthentication.SetAuthCookie(model.UserName, true);
Which makes the cookie with proper expiration time based on the IsPersistent property. However, if you return the cookie with the constructor like in your code:
HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName,
FormsAuthentication.Encrypt(authTicket));
Then the expiration time will be set to browser-session because that is the default behavior of the HttpCookie class: what is the default expiration time of a cookie
So you probably have two options. Use the FormsAuthentication.SetAuthCookie method outlined in the answer you linked to, or add:
cookie.Expires = DateTime.Now.AddMinutes(10); // or whatever you want

Authenticating user with second login

asp.net I am using a second login control to verify a users email. They will get an Email that directs them to a confirm login window. Not the login that is used in the web.config file. So. I assumed that when they entered the loggedin event the would be authenticated, but it seems they are not. All I want to do here is set the profile property 'confirmed' = Y. So I added code:
protected void Login1_LoggedIn(object sender, EventArgs e)
{
TextBox userName = (TextBox)Login1.FindControl("UserName");
string uname = userName.Text;
TextBox Password = (TextBox)Login1.FindControl("Password");
if (Membership.ValidateUser(userName.Text, Password.Text) == true)
{
BDrider bd = new BDrider();
string UserData = bd.getRidFromUsername(uname).ToString();
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, uname, DateTime.Now, DateTime.Now.AddMonths(3), false, UserData, FormsAuthentication.FormsCookiePath);
string encryptedTicket = FormsAuthentication.Encrypt(ticket);
HttpCookie authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
Response.Cookies.Add(authCookie);
if (User.Identity.IsAuthenticated)
{
Profile.confirmed = "Y";
}
Response.Redirect("~/Main/Main.aspx");
}
}
But on the IsAuthenticated line it returns false ???
Seems that you are creating the cookie and trying to "consume it" in the very same request. Unfortunately, this won't work. The forms authentication module will pick up the cookie and maintain the session starting from just the next request.
A possible workaround would be to redirect to an auxiliary page and perform your operation there and then redirect to Main.aspx. Your code would be then
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, uname, DateTime.Now, DateTime.Now.AddMonths(3), false, UserData, FormsAuthentication.FormsCookiePath);
string encryptedTicket = FormsAuthentication.Encrypt(ticket);
HttpCookie authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
Response.Cookies.Add(authCookie);
Response.Redirect( "Auxiliary.aspx" );
and in the Auxiliary.aspx:
if (User.Identity.IsAuthenticated)
{
Profile.confirmed = "Y";
}
Response.Redirect("~/Main/Main.aspx");
However, I don't quite get the if. If you are just issuing the forms cookie, the user surely is authenticated. Why it would be otherwise?

MVC Update FormsAuthenticationTicket UserData at Runtime

I am writing an MVC 4 web application with custom authentication and authorisation. When a user logs into the site, I create a a FormsAuthenticationTicket and store it in a cookie
public void SignIn(string userName, bool createPersistentCookie, string UserData)
{
if (String.IsNullOrEmpty(userName)) throw new ArgumentException("Value cannot be null or empty.", "userName");
// Create and tuck away the cookie
FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(1, userName, DateTime.Now, DateTime.Now.AddDays(15), createPersistentCookie, UserData);
// Encrypt the ticket.
string encTicket = FormsAuthentication.Encrypt(authTicket);
//// Create the cookie.
HttpCookie faCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket);
HttpContext.Current.Response.Cookies.Add(faCookie);
}
The UserData string will be a pipe delimited string and it will always contain at least two items, UserID | UserRole. A user can be assigned to one or more roles, therefore, the UserData could look like this UserID | UserRole | UserRole | UserRole
I then have my own custom generic principal in Global.asax
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
// Get the authentication cookie
string cookieName = FormsAuthentication.FormsCookieName;
HttpCookie authCookie = Context.Request.Cookies[cookieName];
// If the cookie can't be found, don't issue the ticket
if (authCookie == null) return;
// Get the authentication ticket and rebuild the principal
// & identity
FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
string[] UserData = authTicket.UserData.Split(new Char[] { '|' });
GenericIdentity userIdentity = new GenericIdentity(authTicket.Name);
GenericPrincipal userPrincipal = new GenericPrincipal(userIdentity, UserData);
Context.User = userPrincipal;
}
This all works fine, however, within my application, if a user has multiple roles, when they log in, I need to list their roles, and then let them select only one role to go and perform functionality based on the selected role.
I was thinking, to do this, maybe I could pass the role the user selects to a method, get their FormsAuthenticationTicket and update the UserData to reflect the role they have choosen. For example, a UserData string is created with 1|Manager|Applicant, then I need to list both roles and ask the user which role they want to perform functionality under, they select Manager and I then update their UserData within their FormsAuthenticationTicket to 1|Manager.
Is this even possible, or maybe there is a better way of doing this?
Any help would be greatly appreciated.
Thanks everyone.
You could always change FormsAuthenticationTicket.
HttpCookie cookie = FormsAuthentication.GetAuthCookie(Username, true);
var ticket = FormsAuthentication.Decrypt(cookie.Value);
var newticket = new FormsAuthenticationTicket(ticket.Version,
ticket.Name,
ticket.IssueDate,
ticket.Expiration,
true,
"new user data",
ticket.CookiePath);
cookie.Value = FormsAuthentication.Encrypt(newticket);
cookie.Expires = newticket.Expiration.AddHours(24);
HttpContext.Current.Response.Cookies.Set(cookie);
As I said in my comment, I feel this is very poor usability. However, if you're determined to do this, then Dzenan's approach would work (you essentially just strip out all the other roles after the user has selected which role he wants).
Another approach would be to add an additional field to your userdata, which is SelectedRole. Then create a custom IPrincipal that includes this field.
Another approach would be to store it as your own cookie, although I would make sure that you validate that you aren't setting a role that the user is not authorized for (ie if you set SelectedRole=Admin make sure the user has an Admin role before you use it).

Asp.net form login Impossible when client date time differ from server

FormsAuthenticationUserData userData = new FormsAuthenticationUserData(member.Id, member.Role, member.Gender);
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, member.UserName, DateTime.Now, DateTime.Now.AddHours(24), true, userData.Serialize());
string encTicket = FormsAuthentication.Encrypt(ticket);
HttpCookie faCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket);
faCookie.Expires = DateTime.Now.AddHours(25);
Response.Cookies.Add(faCookie);
string redirectUrl = FormsAuthentication.GetRedirectUrl(member.UserName, false);
Response.Redirect(redirectUrl, true);
protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
HttpCookie authCookie = Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie != null)
{
FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
try
{
WebIdentity identity = new WebIdentity(authTicket.Name, authTicket.UserData);
WebPrincipal currentMember = new WebPrincipal(identity);
Context.User = currentMember;
}
catch
{
FormsAuthentication.SignOut();
FormsAuthentication.RedirectToLoginPage();
Response.End();
}
}
}
the user cannot login when client date time is greater than server date time (make cookie null and cannot login)
what is solution?
thanx a lot!
After reading your comment, this is expected behaviour that cannot be changed. The system is doing what it is meant to. You could set the cookie expire later or use a rolling timeout, however, I see no reason for the machine datetime to be out by so far.
This technique avoids using the browser's date/time completely.
Set the FormsAuthentication cookie to never expire, or to expire after 100 years.
Store the actual expiration based on server time in the authenticationTicket.Expiration property. See here.
After the server authenticates a request, it should check the authenticationTicket.Expiration to see if it has expired. I'm not 100% sure the system does this automatically, you may have to hook into the Application_AuthenticateRequest event and do it yourself.
If it has expired, the web server should deny the request; render an HTTP 403 status code and a set-cookie header to remove the cookie at that point.

Resources