I used the Single Sign-on demo from: http://www.codeproject.com/KB/aspnet/SingleSignon.aspx
And I add a SignOut function for this demo, but found a problem:
when I set the cookie.Domain, FormsAuthentication.SignOut() is not working and the cookie can not be cleared.
If the cookie has not been set the cookie.Domain, FormsAuthentication.SignOut() works.
I used C# asp.net.
And could anybody tell me some simple and practical Single Sign-On and Single Sign-Off solutions using asp.net ?
In case you are using the authentication for the same domain and subdomain, try adding the domain name in the web.config instead of adding the domain through code. you will no have to code anything if you use this web.config entry
<authentication mode="Forms">
<forms loginUrl="~/Account/LogOn" timeout="2880" domain="abc.com"/>
</authentication>
This entry tells the asp.net engine that the authentication cookie will be used for all subdomains of abc.com . Try using this and see if it works.
This worked for me:
In the Logout event/ method of each site, use Cookies collection in Request object & delete the relevant cookies as below:
enter code hereHttpCookie cookie = Request.Cookies.Get(".CommonCookieName");
cookie.Expires = DateTime.Now.AddDays(-1);
HttpContext.Current.Response.Cookies.Add(cookie);
If all the sites in SSO use same cookie, then this is simple as described above.
If few or each site participating in SSO use their own cookie/ user name for same subject (person), then u need to remove all the cookies. (perhaps establish a central location with just the mapping of the usernames & cookie names in each site in SSO collection of sites.
This works for me
public virtual ActionResult LogOff()
{
FormsAuthentication.SignOut();
foreach (var cookie in Request.Cookies.AllKeys)
{
Request.Cookies.Remove(cookie);
}
foreach (var cookie in Response.Cookies.AllKeys)
{
Response.Cookies.Remove(cookie);
}
return RedirectToAction(MVC.Home.Index());
}
Related
I need to add Facebook (and later google etc.) authentication to an existing asp.net webforms application using forms authentication.
Im almost there but there seems to be a conflict between formsauthentication and the owin authentication. My solution is based on the standard VS 2015 template.
The relevant code to redirect to the the external authentication provider (facebook) is as follows:
string redirectUrl =
ResolveUrl(String.Format(CultureInfo.InvariantCulture,
"~/Account/RegisterExternalLogin?{0}={1}&returnUrl={2}", IdentityHelper.ProviderNameKey,
provider, ReturnUrl));
var properties = new AuthenticationProperties { RedirectUri = redirectUrl };
Context.GetOwinContext().Authentication.Challenge(properties, provider);
Response.StatusCode = 401;
Response.End();
This works if i turn off forms authentication. If I have forms authentication, the user gets redirected to the forms authentication url defined in the web.config:
<authentication mode="Forms">
<forms name=".ASPXAUTH_Test" loginUrl="~/start/login.aspx" timeout="60" >
</forms>
</authentication>
From my understandint the Http Status code (401) triggers the redirect to the Url in the web.config. I tried to set other status codes, but they don't work at all.
When I turn off forms authentication in the web.config, the actual login process still works (surprisingly) but if I access a protected page while not having logged in a get an ugly IIS error page, instead of being redirected.
It seems, that I can't get work forms authentication and owin external authentication to work together properly :-(
So far all alternatives don't seem enticing to me:
- switch to the identity framework (in our specific environment, this is absolutly NOT an option. I just mention it for the sake for completness)
- try to use web.api or something similar (which probably has the same problem)
- let go of owin external authentication and implement everything by hand
Has anyone been able to make this work? Any help is appreciated. Thanks in advance.
Halleluja, I found the solution:
From .Net 4.5 it is possible to prevent the forms redirect in the response:
Response.SuppressFormsAuthenticationRedirect = true;
so the working code would look like:
var owinContext = Context.GetOwinContext();
owinContext.Authentication.Challenge(properties, provider);
Response.SuppressFormsAuthenticationRedirect = true;
Response.StatusCode = 401;
Response.End();
I have some code where we create an authentication ticket. After creating the ticket, we call SetAuthCookie to set the cookie such as:
FormsAuthentication.SetAuthCookie(username, true);
Response.Redirect("/", true);
If I check on the root page to see if the user is authenticated, it returns false. However, if I hard code the username in and do:
FormsAuthentication.GetAuthCookie("jason", true).value);
I get the appropriate cookie value. So, the cookie exists. But the name and the flag are not modified. Any ideas as to what my issue could be? I'm using ASP.NET 4 and MVC.
Solved
I was missing the forms section in the web.config. It was removed for local testing as the login form resides on another server. So, adding the following to web.config solved my issue:
<authentication mode="Forms" />
I'm playing around with authentication and authorization to prepare for some task. I've created two pages: Login.aspx and Default.aspx. In config file i've set authentication to forms and denied unauthenticated users access:
<authentication mode="Forms">
<forms name="aaa" defaultUrl="~/Login.aspx" />
</authentication>
<authorization>
<deny users="?"/>
</authorization>
Then I've written some simple code to authenticate my user in Login.aspx:
protected void Page_Load(object sender, EventArgs e)
{
GenericIdentity identity = new GenericIdentity("aga", "bbb");
Context.User = new GenericPrincipal(identity, new String[] { "User" }); ;
Response.Redirect("~/Default.aspx");
}
When i run it, the redirection doesn't take place. Instead Login.aspx is called over and over because the user is not authenticated (Context.User.Identity.IsAuthenticated is false at every load). What am i doing wrong?
Context.User only sets the principal for the current request. Once the redirect takes place, the current request ends and a new one begins with the non-overridden principal again (which is apparently not authenticated). So, setting Context.User doesn't actually authenticate anything.
Using FormsAuthentication.SetAuthCookie() will set the user's cookie to a valid value accepted by the FormsAuthentication provider, or put the token in the URL. You can redirect to your heart's content because the cookie obviously sticks with the user for future requests.
From MSDN (em added):
With forms authentication, you can use the SetAuthCookie method when you want to authenticate a user but still retain control of the navigation with redirects.
As stated, this does not necessarily require cookies - the name is a little misleading, because it will still work via the URL if FormsAuthentication is in cookieless mode:
The SetAuthCookie method adds a forms-authentication ticket to either the cookies collection, or to the URL if CookiesSupported is false.
Use FormsAuthentication.SetAuthCookie(..). Or FormsAuthentication.RedirectFromLoginPage(..).
You need to actually set the user as authenticated. All of the following methods will work and let you actually get away from your login screen.
FormsAuthentication.Authenticate()
FormsAuthentication.RedirectFromLoginPage()
FormsAuthentication.SetAuthCookie()
Lots of ways to get to the same result.
You need to actually make a call to the formsAuthentication provider to set the login.
FormsAuthentication.RedirectFromLoginPage(txtUser.Text, chkPersistLogin.Checked)
is a simple example
After creating the dummy Context.User, you need to perform a FormsAuthentication.SetAuthCookie or RedirectFromLoginPage method.
I am building a site in asp.net and have multiple subdomains. For example,
one.cookies.com
two.cookies.com
I want my users to be able to login at either subdomain and be logged in for both websites. In addition, I'd like the sessions and cookies to be in sync. So far I haven't found a reliable way to do this.
If you want to sync the ASP.NET session and you aren't using forms authentication (for example, your site has no login), try adding the following code to your Globals.asax file. This worked like a champ for me and saved me some serious grief.
protected void Application_PreRequestHandlerExecute(Object sender, EventArgs e)
{
/// only apply session cookie persistence to requests requiring session information
#region session cookie
if (Context.Handler is IRequiresSessionState || Context.Handler is IReadOnlySessionState )
{
/// Ensure ASP.NET Session Cookies are accessible throughout the subdomains.
if (Request.Cookies["ASP.NET_SessionId"] != null && Session != null && Session.SessionID != null)
{
Response.Cookies["ASP.NET_SessionId"].Value = Session.SessionID;
Response.Cookies["ASP.NET_SessionId"].Domain = ".know24.net"; // the full stop prefix denotes all sub domains
Response.Cookies["ASP.NET_SessionId"].Path = "/"; //default session cookie path root
}
}
#endregion
}
I found this originally posted here:
http://www.know24.net/blog/ASPNET+Session+State+Cookies+And+Subdomains.aspx
When you create the cookie you can set the domain:
HttpCookie cookie = new HttpCookie("name", "value");
cookie.Domain = "cookies.com";
This will allow your cookie to be accessible from all subdomains of cookies.com.
If you are using FormsAuthentication then you can set the domain for the auth cookie in web.config:
<forms name=".ASPXAUTH"
loginUrl="login.aspx"
defaultUrl="default.aspx"
protection="All"
timeout="30"
path="/"
requireSSL="false"
domain="cookies.com">
</forms>
Remember that for the single sign-on to work on multiple subdomains your ASP.NET applications must share the same machine keys as explained in this CodeProject article.
Sharing sessions between different subdomains (different worker processes) is more difficult because sessions are constrained to an application and you will have to implement a custom session synchronization mechanism.
Yes, you need to use ".cookies.com" not "cookies.com"
I beleive make the cookie for http://cookies.com. (No subdomain or www listed)
I have a main asp.net app, which is written in asp.net 1.1. Runnning underneath the application are several 2.0 apps. To completely logout a user can I just logout of the 1.1 app with FormsAuthentication.SignOut or is it more complicated than that?
What you are looking to do is called Single Sign On and Single Sign Off. There are differences based on how you have the applications set up. I will try to clarify where those differences come into play.
To implement single sign on and single sign off you need to make the cookie name, protection, and path attributes the same between all the applications.
<authentication mode="Forms">
<forms name=".cookiename"
loginUrl="~/Login.aspx"
timeout="30"
path="/" />
</authentication>
Next you need to add the machine keys and they need to be the same between all your applications.
<machineKey validationKey="F9D1A2D3E1D3E2F7B3D9F90FF3965ABDAC304902"
encryptionKey="F9D1A2D3E1D3E2F7B3D9F90FF3965ABDAC304902F8D923AC"
validation="SHA1" />
Are you using second or third level domains for the applications? If so you will need to do a little bit more by adding the domain to the cookie:
protected void Login(string userName, string password)
{
System.Web.HttpCookie cookie = FormsAuthentication.GetAuthCookie(userName, False);
cookie.Domain = "domain1.com";
cookie.Expires = DateTime.Now.AddDays(30);
Response.AppendCookie(cookie);
}
Now to do single sign off, calling FormsAuthentication.SignOut may not be enough. The next best thing is to set the cookie expiration to a past date. This will ensure that the cookie will not be used again for authentication.
protected void Logout(string userName)
{
System.Web.HttpCookie cookie = FormsAuthentication.GetAuthCookie(userName, False);
cookie.Domain = "domain1.com";
cookie.Expires = DateTime.Now.AddDays(-1);
Response.AppendCookie(cookie);
}
I am taking into consideration you are using the same database for all the applications. If the applications use a separate database for registration and authentication, then we will need to do some more. Just let me know if this is the case. Otherwise this should work for you.
It could be easier if you are having a central session store for all your applications. You can then set the session to null in one place.
This worked for me:
In the Logout event, instead of FormsAuthentication.GetAuthCookie method use Cookies collection in Request object as below:
HttpCookie cookie = Request.Cookies.Get(otherSiteCookieName);
cookie.Expires = DateTime.Now.AddDays(-1);
HttpContext.Current.Response.Cookies.Add(cookie);
Ofcourse, this requires u know the Cookie name of the site(s) you want the user to be logged out - which however won't be a problem if you are using the same cookie across all the web apps.
I prefer to use web.config
<authentication mode="Forms">
<forms domain=".tv.loc" loginUrl="~/signin" timeout="2880" name="auth" />
</authentication>