"Single sign-on" using existing ASP.NET user store - asp.net

(Using inverted commas because I don't think this is strictly a single sign-on use case. Although it's the same concept.)
I have an existing ASP.NET Web Forms site (SiteA) using Membership...
Web.config:
<machineKey validationKey="etc"
decryptionKey="etc"
validation="SHA1"
decryption="AES" />
<authentication mode="Forms">
<forms name="goodcookie"
loginUrl="~/login"
timeout="2880"
defaultUrl="~/" />
</authentication>
<membership>
<providers>
<clear />
<add name="AspNetSqlMembershipProvider"
type="System.Web.Security.SqlMembershipProvider"
connectionStringName="etc"
applicationName="etc" />
</providers>
</membership>
<roleManager enabled="true">
<providers>
<clear />
<add connectionStringName="etc"
applicationName="etc"
name="AspNetSqlRoleProvider"
type="System.Web.Security.SqlRoleProvider" />
</providers>
</roleManager>
Login button's codebehind:
if (Membership.ValidateUser(txtUsername.Value, txtPassword.Value))
{
FormsAuthentication.SetAuthCookie(txtUsername.Value, true);
Response.RedirectToRoute("home");
}
Master page's codebehind for each page load:
if (!HttpContext.Current.User.Identity.IsAuthenticated)
{
Response.Clear();
Response.Redirect("/login", true);
}
There's a requirement to create a new site (SiteB) on a separate domain, however both SiteA and SiteB will use the same database.
Some users will only have access to SiteA, some only to SiteB, and some to both SiteA and SiteB. This will be determined by their role(s).
I've created SiteB with identical values in Web.config (same cookie name, same machine key, etc). Even the same application name just to test. Of course I'm able to log in to both sites with the same user credentials, but.. if I'm logged in to SiteA, and I load SiteB, it will behave like I'm not authenticated (ie. redirect me to the login page).
What could I be missing?
(Will edit if I think of any more relevant details)

Different domains cannot read coookies of each other and thus if you logged in to SiteA the authentication cookie isn't sent when you request SiteB. But different subdomains can share cookies so moving sites to single domain should be a solution. Also read this question and answers for more information.

Related

timeout setting inside the web.config's <authentication> tag

I am working on an asp.net mvc-4 web application hosted under IIS-8 and windows server 2008 R2.
now for the asp.net mvc i am using form authentication, which is integrated with our active directory.
here is the related entities inside our web.config :-
<membership>
<providers>
<add name="TestDomain1ADMembershipProvider" type="System.Web.Security.ActiveDirectoryMembershipProvider, System.Web, Version=4.0.0.0,
Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" connectionStringName="TestDomain1ConnectionString" connectionUsername="*********" connectionPassword="******" attributeMapUsername="sAMAccountName" />
</providers>
</membership>
<httpRuntime targetFramework="4.5" />
<authentication mode="Forms">
<forms loginUrl="~/Account/Login" timeout="40320" />
</authentication>
now my question is about the timeout parameter inside the <forms>. now i understand this setting as follow:-
When the user first login to the web application , he will enter a username & password. if his credentials are valid, a browser cookie will be generated to him, and saved inside the browser cache. now since i have specified a timeout="40320". this means that the browser cookie will expire after 40320 minute ?? is this correct ? so if the user try to access the system after 40320+ minute from his first login, then IIS will see that the passed cookie is expired and will logout the user .. is this correct ?
https://msdn.microsoft.com/en-IN/library/1d3t3c61(v=vs.85).aspx
Optional attribute.
Specifies the time, in integer minutes, after which the cookie expires. If the SlidingExpiration attribute is true, the timeout attribute is a sliding value, expiring at the specified number of minutes after the time that the last request was received. To prevent compromised performance, and to avoid multiple browser warnings for users who have cookie warnings turned on, the cookie is updated when more than half of the specified time has elapsed. This might cause a loss of precision. The default is "30" (30 minutes).

Session state server custom timeouts for users

I want to use a SessionStateServer Redis in Azure Cache. My problem is I want to set a custom timeouts for our users but it always takes the default value.
How do I specify custom timeout values for our users ?
<sessionState mode="Custom" customProvider="MySessionStateStore" timeout="20">
<providers>
<add type="Microsoft.Web.Redis.RedisSessionStateProvider" name="MySessionStateStore" host="host" port="6380" accessKey="pass" ssl="true" throwOnError="true" retryTimeoutInMilliseconds="0" databaseId="0" applicationName="xxxDev" connectionTimeoutInMilliseconds="5000" operationTimeoutInMilliseconds="5000" />
</providers>
</sessionState>
This same bug was reported here: http://blogs.msdn.com/b/webdev/archive/2014/05/12/announcing-asp-net-session-state-provider-for-redis-preview-release.aspx#comments
It is fixed in https://www.nuget.org/packages/Microsoft.Web.RedisSessionStateProvider/1.1.0

Why is ASP.NET FormsAuthentication cookie not authenticating user?

I have a site that uses the default SqlMembershipProvider and FormsAuthentication. I can use the built-in Login Controls and/or programmatically call all the methods to authenticate a user and get the same result - the user is authenticated and a cookie is created, but the cookie does not appear to be valid since I can't get into any page that requires authentication.
There is no real code to show for the default Login Control since it should just "work", but here is the custom code I tried:
protected void ctrlLogin_Authenticate(object sender, AuthenticateEventArgs e)
{
if (Membership.ValidateUser(ctrlLogin.UserName, ctrlLogin.Password))
{
FormsAuthentication.RedirectFromLoginPage(ctrlLogin.UserName, ctrlLogin.RememberMeSet);
/*
* I also tried this:
FormsAuthentication.SetAuthCookie(ctrlLogin.UserName, ctrlLogin.RememberMeSet);
if (!String.IsNullOrEmpty(Request.QueryString["ReturnUrl"]))
Response.Redirect(Request.QueryString["ReturnUrl"]);
Response.Redirect("/index.aspx");
*/
}
else
{
ctrlLogin.FailureText = "Invalid Username/Password Combination";
}
}
With this code, Membership.ValidateUser() succeeds, and both FormsAuthentication.RedirectFromLoginPage() and FormsAuthentication.RedirectFromLoginPage() successfully set a cookie - that cookie just doesn't work to verify my authentication. I have confirmed this by deleting all my cookies and watching them get created again with FireCookie. The cookie name matches what I have in my web.config, the domain is "/", and the expiration date is as expected (see below).
Here are the relevant sections of my web.config:
<authentication mode="Forms">
<forms loginUrl="~/login/index.aspx" name=".SoeAuth" protection="All"
slidingExpiration="true" timeout="525599" domain=""></forms>
</authentication>
<membership defaultProvider="SqlMembershipProvider">
<providers>
<add connectionStringName="[MY_CS]" applicationName="[MY_APPNAME]"
minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0"
enablePasswordReset="true" passwordFormat="Hashed" requiresUniqueEmail="true"
name="SqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider"
requiresQuestionAndAnswer="false"/>
</providers>
</membership>
It should be noted that I also added a machineKey entry in my web.config file based on a suggestion from a very similar question here (which didn't solve my problem). Also, for reference, the timeout=525599 above is 1 minute less than a year for my persistent cookies.
I found the problem:
Since I was able to create a simple working test project with the exact same source code, I determined that the problem was in the web.config file.
Going through each section, I discovered in the 'system.web / httpModules' section I had a <clear/> element. This removed the <add name="FormsAuthentication" type="System.Web.Security.FormsAuthenticationModule"/> module defined in machine-level web.config file. Adding it back in instantly fixed the problem.
It sure would have been nice to get an error message when I tried to use the FormsAuthentication methods and that module wasn't even loaded...

ASP.NET ChangePassword Control Stopped Working

We have a couple of ASP.NET WebForms applications that use the ADAM Membership provider, one of which includes the ChangePassword control. The control has started to fail every password change:
Password incorrect or New Password invalid.
New Password length minimum: 6.
Non-alphanumeric characters required: 0.
We can still successfully reset passwords on the ADAM instance, and the logins still authenticate in the applications. There are no exceptions thrown, and no errors in EventViewer.
Here is the provider section of the Web.config:
<membership defaultProvider="ADAMMembershipProvider">
<providers>
<clear/>
<add name="ADAMMembershipProvider"
type="System.Web.Security.ActiveDirectoryMembershipProvider"
connectionStringName="MembershipConnectionString"
connectionProtection="None"
connectionUsername="[the username]"
connectionPassword="[the password]"
enableSearchMethods="true"
minRequiredPasswordLength="6"
minRequiredNonalphanumericCharacters="0"
maxInvalidPasswordAttempts="3"
passwordAttemptWindow="5"
requiresQuestionAndAnswer="false"
requiresUniqueEmail="true"/>
</providers>
</membership>
The problem is that ADAM does not allow passwords to be changed over insecure connections by default. There are couple ways around this problem:
Setting your connectionProtection property to "Secure" and having the necessary SSL certificates in place.
or
Using dsmgmt and changing the "Ds Behavior" to "Allow passed op on unsecured connection".

ASP.NET SqlMembershipProvider Infinite Loop?

I am trying to configure authentication using a few tutorials I have found on the Membership Providers paradigm found in ASP.NET v2.0. I've followed the examples in the tutorial but can't seem to get the FormsAuthentication.RedirectFromPage method to work appropriately. When I attempt a login, the user credentials are validated via Membership.ValidateUser but the page is sent back to Login.aspx instead of Default.aspx. Here is the relevant snippet from my web.config:
...
<authentication mode="Forms">
<forms loginUrl="Login.aspx" protection="All" timeout="60" name="POTOKCookie" requireSSL="false" path="/FormsAuth"
slidingExpiration="true" cookieless="UseCookies" enableCrossAppRedirects="false" defaultUrl="~/Default.aspx"/>
</authentication>
<authorization>
<deny users="?" />
</authorization>
...
<membership defaultProvider="CustomizedProvider">
<providers>
<clear />
<add name="CustomizedProvider"
type="System.Web.Security.SqlMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
connectionStringName="LoginDB2"
applicationName="POTOK"
minRequiredPasswordLength="5"
minRequiredNonalphanumericCharacters="0" />
</providers>
</membership>
I've verified that my connection string is correct (since Membership.ValidateUser seems to be working just fine) and am using the ASP.NET Login control for the UI on my Login.aspx page. Here is the authenticate event handler code:
Protected Sub Login1_Authenticate(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.AuthenticateEventArgs) Handles Login1.Authenticate
If (Membership.ValidateUser(Login1.UserName, Login1.Password)) Then
FormsAuthentication.RedirectFromLoginPage(Login1.UserName, Login1.RememberMeSet)
End If
End Sub
When I visit the url (http://localhost/Project) I am taken to: http://localhost/Project/Login.aspx and after the "login" my url is: http://localhost/Project/Login.aspx?ReturnUrl=%2fProject%2fDefault.aspx
Did I miss a configuration step?
The problem is in path="/FormsAuth" parameter.
Remove this variable and try again
Read this post about why path can be wrong
From MSDN:
path - Optional attribute. Specifies the path for cookies that are issued by the application. The default is a slash (/), because most browsers are case-sensitive and will not send cookies back, if there is a path case mismatch.
NOTE: The path attribute is case sensitive. Therefore, if the you set the value of the path attribute to /application1, and if the application name is Application1, the authentication cookie path is /application1.
So if you want to use path property, you should set it to "/project" because Project is the name of your application (as far as I understood). But I don't think you need to have different paths when you use different cookies names (i.e. name="POTOKCookie" in this application, i hope will be different from other ASP.NET applications installed on the same host)
See PRB: Forms Authentication Requests Are Not Directed to loginUrl Page
If you use the Login control with ASP.NET membership, you do not need to write code to perform authentication. However, if you want to create your own authentication logic, you can handle the Login control's Authenticate event and add custom authentication code.
So, I suggest you simply delete Login1_Authenticate event as far as it does the double work, I think, because control itself is responsible for calling ValidateUser and redirection.
Also check DestinationPageUrl property of the Login control
If you do not specify a value for the DestinationPageUrl property, the user will be redirected to the original page the user requested after successfully logging in. So in your case this property should not be set.

Resources