Create a Forms Authentication site - c#

My site works great with the backend Umbraco stuff for a user to log in and change the content etc. What i am looking to do is create a login reg section for the front facing site so users can leave comments etc.
I have created my login reg page and tried using .NET Forms Authentication but nothing seems to work! When I add the cookie, I refresh and it's not there. This method works great in non Umbraco sites, so I am assuming that I need to do something different with Umbraco.
Here is my Forms Authentication code, which doesn't seem to add cookies or SetAuthCookie:
Users Users = new Users();
ENT_User User = Users.GetUser(this.txtLogin.Text, this.txtLoginPassword.Text);
if (User.ID != Guid.Empty)
{
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1,
User.Email,
DateTime.Now,
DateTime.Now.AddDays(12),
true,
User.ID.ToString(),
FormsAuthentication.FormsCookiePath);
// Encrypt the ticket.
string encTicket = FormsAuthentication.Encrypt(ticket);
// Create the cookie.
Response.Cookies.Add(new HttpCookie("LoginDetails", encTicket));
}
When I hover my mouse over the cookies in Debug the cookie is there, but when I refresh and come through the process again, the Cookie is not there.
Does anyone have any ideas as to what the problem is?
Thanks

You've set expiration for the ticket, but not for the cookie itself.
Try to change:
...
Response.Cookies.Add(new HttpCookie("LoginDetails", encTicket));
to:
...
var httpCookie = new HttpCookie("LoginDetails", encTicket);
httpCookie.Expires = DateTime.Now.AddDays(12);
Response.Cookies.Add(httpCookie);

Related

FormsAuthentication Cookie Not Saving

I have two login pages. One for admin users and one for customers.
They both execute the below code (after authorisation) to add a cookie to the Response. The two pages then redirect to the URL provided (I don't do the redirect here as I do some extra checks on admin)
public static string SetAuthCookie<T>
(this HttpResponse responseBase, string name, bool rememberMe, T userData)
{
/// In order to pickup the settings from config, we create a default cookie
/// and use its values to create a new one.
var cookie = FormsAuthentication.GetAuthCookie(name, true);
var ticket = FormsAuthentication.Decrypt(cookie.Value);
var newTicket = new FormsAuthenticationTicket(
ticket.Version,
ticket.Name,
ticket.IssueDate,
ticket.Expiration,
true,
Newtonsoft.Json.JsonConvert.SerializeObject(userData),
ticket.CookiePath
);
var encTicket = FormsAuthentication.Encrypt(newTicket);
/// Use existing cookie. Could create new one but would have to copy settings over...
cookie.Expires = (rememberMe ? DateTime.Now.AddDays(62) : DateTime.MinValue);
cookie.Value = encTicket;
responseBase.Cookies.Set(cookie);
return FormsAuthentication.GetRedirectUrl(name, true /*This Is Ignored*/);
}
Admin
Now the admin does as it's told. Adds the cookie and redirects to an admin welcome screen.
Customer
The customer login area just isn't doing the same (see below screengrab).
It posts (as you can see it receives the request to save the cookie)
It redirects
But, oh no, the next request has no cookie
The system can't see the user is authenticated
Back to the login screen we go
I thought that the problem may be a local browser.
Nope, tried: different browsers, using private/incognito.
I thought it might be the setting of the cookie.
How can it be? They both use the same code.
Maybe web.config (in their respected directories)?
Nope, just <authorization> rules
Maybe a problem with the cookie?
Nope, looks fine. Same domain, HTTPS. all fine
Something to do with RememberMe?
Nope, tried both with and without
Soooo.... Been silly.
I forgot to exclude ([JsonIgnore]) a property that fetches some extra data (not needed for setting the cookie). This was being included and, obviously, made my cookie too large to save.
Oops.

OWIN SignOut doesn't remove cookie

I am using the OWIN middleware in an external Authentication Server that my applications authenticate to using OAuth Authorisation Code Grant flow.
I can redirect to the Authentication Server, authenticate against an external provider (Google) and redirect back to my client application with a logged in user and Application Cookie set just fine, however when I try to sign out the cookie remains after I call the AuthenticationManager.SignOut method.
My cookie options in Startup.Auth.cs are:
var cookieOptions = new CookieAuthenticationOptions
{
Provider = cookieProvider,
AuthenticationType = "Application",
AuthenticationMode = AuthenticationMode.Passive,
LoginPath = new PathString("/Account/Index"),
LogoutPath = new PathString("/Account/Logout"),
SlidingExpiration = true,
ExpireTimeSpan = TimeSpan.FromMinutes(30),
};
app.UseCookieAuthentication(cookieOptions);
app.SetDefaultSignInAsAuthenticationType(DefaultAuthenticationTypes.ExternalCookie);
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
My login method:
var loginInfo = await AuthManager.GetExternalLoginInfoAsync();
SignInManager.ExternalSignInAsync(loginInfo, true);
var identity = AuthManager.AuthenticateAsync(DefaultAuthenticationTypes.ExternalCookie).Result.Identity;
if (identity != null)
{
AuthManager.SignIn(
new AuthenticationProperties {IsPersistent = true},
new ClaimsIdentity(identity.Claims, "Application", identity.NameClaimType, identity.RoleClaimType));
var ticket = AuthManager.AuthenticateAsync("Application").Result;
var identity = ticket != null ? ticket.Identity : null;
if (identity == null)
{
AuthManager.Challenge("Application");
return new HttpUnauthorizedResult();
}
identity = new ClaimsIdentity(identity.Claims, "Bearer", identity.NameClaimType, identity.RoleClaimType);
AuthManager.SignIn(identity);
}
return Redirect(Request.QueryString["ReturnUrl"]);
Sign Out method:
var authTypeNames = new List<string>();
authTypeNames.Add("Google");
authTypeNames.Add("Application");
authTypeNames.Add("Bearer");
authTypeNames.Add(DefaultAuthenticationTypes.ExternalCookie);
Request.GetOwinContext().Authentication.SignOut(authTypeNames.ToArray());
I have looked at other questions like:
OWIN authentication, expire current token and remove cookie
and
OWIN - Authentication.SignOut() doesn't remove cookies
with no luck. I'm aware I could manually delete the cookie by setting a negative expiry date, but I'd prefer to use in built method if possible.
How do I get the Application Cookie to be removed when I Sign Out?
In order for the SignOut method to flag the authentication ticket (cookie) for removal from the client, the AuthenticationType parameter you pass into the SignOut method and value on the cookie must match exactly. If you want to remove more than one authentication ticket from the client then you'll have to match ALL of those AuthenticationTypes and pass those as a string[] to the SignOut method.
The AuthenticationType of an authentication ticket usually prefixed with the name of the host web container (i.e. something like ".AspNet.") followed by whatever you bootstrapped your OWIN CookieAuthentication settings with.
It looks like you set your AuthenticationType string value to "Application" in Startup.Auth.cs. Try simply calling:
Request.GetOwinContext().Authentication.SignOut("Application");
If that's not working for you, I would debug your application and take a look at the specific AuthenticationType on the identity for each type of authenticated user your application allows, note the value of the AuthenticationType for each one and try including them all in a string[] in your SignOut call.
AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
FormsAuthentication.SignOut();
Session.Abandon();
From an other StackOverFlow answer which worked for me: OWIN - Authentication.SignOut() doesn't seem to remove the cookie
Use only one of these:
Request.GetOwinContext().Authentication.SignOut();
Request.GetOwinContext().Authentication.SignOut(Microsoft.AspNet.Identity.DefaultAuthenticationTypes.ApplicationCookie);
HttpContext.Current.GetOwinContext().Authentication.SignOut(Microsoft.AspNet.Identity.DefaultAuthenticationTypes.ApplicationCookie);
https://dzone.com/articles/catching-systemwebowin-cookie
I would assume the second one would work for you, but it looks like that's what you're doing. Can you test that on its own? Comment out your array and confirm that that works or doesn't.
To be honest, I don't know enough about OWIN to know about the Passive Authentication mode, however.
I worked on this for days. Here is what finally worked for me. First thing I do is clear the token cache. Next, I create an array of Auth Application Types. I added these 4. You can add more, if you are using them. To my knowledge, I'm only using Cookies and OpenIdConnect, but I added Bearer and Application to be safe. The final step is to clear all remaining Cookies, if any, and any remaining Sessions, if any. Again, I worked on this for days. It was so frustrating. I'm currently using 4.0.1 of these packages.
Install-Package Microsoft.Owin.Security.OpenIdConnect
Install-Package Microsoft.Owin.Security.Cookies
Install-Package Microsoft.Owin.Host.SystemWeb
public ActionResult SignOut()
{
if (Request.IsAuthenticated)
{
string userId = ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).Value;
if (!string.IsNullOrEmpty(userId))
{
// Get the user's token cache and clear it
SessionTokenCache tokenCache = new SessionTokenCache(userId, HttpContext);
string sessionID = HttpContext.Session.SessionID;
tokenCache.Clear(sessionID);
}
}
var authTypeNames = new List<string>();
authTypeNames.Add("Cookies");
authTypeNames.Add("Application");
authTypeNames.Add("Bearer");
authTypeNames.Add("OpenIdConnect");
// Send a sign-out request.
HttpContext.GetOwinContext().Authentication.SignOut(authTypeNames.ToArray());
Request.Cookies.Clear();
Session.RemoveAll();
return RedirectToAction("Index", "Home");
}
If you have any master page then please add the below tag. May be this would be helpful.
<meta http-equiv="Cache-control" content="no-cache" />

IsAuthenticated is always false when including HttpCookie subkeys or not encrypting

Okay, I've been assigned with authenticating used on a login page. I've been working on this for quite a while and decided to clean up it up. The problem that I faced is one of those problems where exceptions aren't thrown, no error is generated, and everything looks okay, but when you try to use a function, it gives back a result that you don't want.
The code I used looks very similar to code from this page:
http://msdn.microsoft.com/en-us/library/system.web.security.formsauthenticationticket.aspx
I've used the code from the demo in my project:
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1,
username,
DateTime.Now,
DateTime.Now.AddMinutes(30),
isPersistent,
userData,
FormsAuthentication.FormsCookiePath);
// Encrypt the ticket.
string encTicket = FormsAuthentication.Encrypt(ticket);
HttpCookie myCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket)
// Create the cookie.
Response.Cookies.Add(myCookie);
So if I logged in, everything works and the below code evaluates to true:
HttpContext.Current.User.Identity.IsAuthenticated;
However, if I wanted to include subkeys to myCookie using either versions:
myCookie.Values.Add("userName", "patrick"); //version 1
myCookie.Values["userName"] = "patrick"; //version 2
Then you add to the cookies collection:
Response.Cookies.Add(myCookie);
Then refresh the page after login:
//This always set to false even after successful log on
HttpContext.Current.User.Identity.IsAuthenticated;
No clue why!
I wanted to do something where I don't have to add the encryption value to the httpcookie immediately:
//IsAuthenticated doesn't work = false
HttpCookie cookie = new HttpCookie(FormsAuthentication.FormCookieName);
cookie.Values.Add("encryptTicket", encTicket);
It's just weird that adding subkeys don't work at all. And that I am forced to encypt a ticket in order to make it work. What I mean, is that IsAuthenticated is false all the time, logged in and authenticated or not. Can anyone try to explain what's going on with this? I have a working solution, but any insight would be helpful.
Okay, think I figured this out. It's because of how my web.config was set up for forms authentication. Using the forms tag.
The FormsAuthenticationTicket looks at that tag for specific information, and if I didn't create a cookie off of it, it wouldn't authenticate me. This was also defaulted to cookieless mode to UseCookies.
But anyways, after I create a cookie off of that, then I become authenticated and then a new session is created for me. After that, I can then provide any extra cookies I want and let the website use them as needed. But as long as that AuthCookie (in my case .ASPXAUTH) is valid, so is my authentication session.
In fact, when I tried to make a cookie session end when the browser closed, by setting the expiration date to MinValue for the cookie and the ticket, I wasn't able to authenticate either! I had to make the ticket last longer than the actual cookie so that the ticket doesn't expire before the cookie does.
The ticket information is really a configuration used to make the cookie, and after cookie creation, the browser is what defines how the cookies are used.

Cookie expiration datetime and different date in client and server

I am using the following code for a custom "remember me" implimentation:
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, member.UserName, DateTime.Now, DateTime.Now.AddHours(24), true, dataString);
string encTicket = FormsAuthentication.Encrypt(ticket);
HttpCookie faCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket);
faCookie.Expires = ticket.Expiration;
HttpContext.Current.Response.Cookies.Add(faCookie);
But some users cannot login (Login page appears even after sign in).
It seems the problem is caused by the client having a different (greater) date than the server.
So, what is the best and correct solution for a "remember me" implementation.
To solve this problem I must remove this line:
faCookie.Expires = ticket.Expiration;
After removing this line, when user closes the browser, he must sign in (cookie is not persist).
What is the solution?
What you could do is get the clients Date/Time and use that for the Cookie, rather than the server time.
There is a great answer here showing you a good way to do this; basically populate a hidden field with the clients date/time and get it on postback.
You could have this hidden field on your masterpage so the clients date/time is always available. doesn't need to just be on the login screen.

Automatically assign authentication token in .NET

I have implemented forms authentication with a .NET Membership Provider but I also want users to be able to login with Facebook. Once authenticated with Facebook, I want to automatically assign a .NET authentication token to the user. I have a HttpModule that is detecting the FB authentication but all my attempts to manually generate an authentication token have come up short.
I tried
FormsAuthentication.SetAuthCookie
FormsAuthentication.GetAuthCookie + Response.Cookies.Add
new FormsAuthenticationTicket(...) a la MSDN
In an HttpModule vs Page
Plus a few other desperate attempts. Nothing seems to work. How is this done?
Proposed way is using WIF
FormsAuthentication.Initialize();
// Create a new ticket used for authentication
FormsAuthentication.SetAuthCookie(UserName.Text, false);
// Create a new ticket used for authentication
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
1, // Ticket version
UserName.Text, // Username associated with ticket
DateTime.Now, // Date/time issued
DateTime.Now.AddMinutes(30), // Date/time to expire
false, // "true" for a persistent user cookie
"Admin", // User-data, in this case the roles
FormsAuthentication.FormsCookiePath);// Path cookie valid for
// Encrypt the cookie using the machine key for secure transport
string hash = FormsAuthentication.Encrypt(ticket);
HttpCookie cookie = new HttpCookie(
FormsAuthentication.FormsCookieName, // Name of auth cookie
hash); // Hashed ticket
// Set the cookie's expiration time to the tickets expiration time
if (ticket.IsPersistent) cookie.Expires = ticket.Expiration;
// Add the cookie to the list for outgoing response
Response.Cookies.Add(cookie);
After you SetCookieAuth you need to do a redirect to give the HttpModule a chance to fire and set the HttpContext.User property.
It turns out someone else had registered another module in the solution that was interfering with HttpRequest and the authentication pieces. After I got rid of that, FormsAuthentication.SetAuthCookie(...) worked fine.
Thanks everyone for the help.

Categories

Resources