Update on the Auto-Signon Broken Bug ...
-
Hey All,
Thought I'd provide an update of where I'm at with this.
So far, I have no idea why this isn't working. The auto-logon is handled via ASP.NET and should "just work." I've followed some recommendations on from the folks at cs.org but have gotten nowhere -- once the timeout hits, it won't "remember" me. I've spent a couple hours trying debug this to no avail.
I've decided to tackle it with a new approach -- use ASP.NET 1.1 instead of ASP.NET 2.0. This, by the way, is one of the more impressive things about CS2.0 -- it works very well in both platforms. Anyway, I've rebuilt it on my VS2003 machine and will be testing this out some more ... so hopefully soon this will be fixed.
-
Why don't you post some of the details here? I'm not the one to ask, but there's got to be at least one .net non-punk programmer here... well, probably.
-
Out of curiosity, are you using those newfangled asp:Login and asp:PasswordRecovery tags?
-
Well, as for the details ...
- I've stepped through the code to watch it set the authentication ticket cookie. The cookie has the appropriate expiration date/time on it (30 days).
- If I access the site within the authentication ticket expiration (60 minutes), it works fine
- outside the 60 minute window, it ignores the auth ticket cookie and doesn't recognize it.
- All this auth ticket stuff is handled internally by ASP.NET
- Here's the help from the cs.org guy: http://communityserver.org/forums/thread/530491.aspx
- I've made the changes he recommended
And AFAIK, this does not use the Membership Provider stuff in ASP.NET 2.0 -- they wanted CS2.0 to work fine in ASP.NET 1.1 and ASP.NET 2.0.
-
Just a wild guess after some googling...
in the fileweb.config
<authentication mode="Forms">
<forms name="login"
loginUrl="login.aspx" protection="All" timeout="60" />
</authentication>
-
I do suspect it's a web.config problem, but unfortunately not that simple of one. Here's the one it's using ...
<configuration>
<configSections>
<sectionGroup name="memberrolesprototype">
<section name="membership" type="Microsoft.ScalableHosting.Configuration.MembershipConfigHandler, MemberRole, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b7c773fb104e7562"/>
<section name="roleManager" type="Microsoft.ScalableHosting.Configuration.RolesConfigHandler, MemberRole, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b7c773fb104e7562"/>
<section name="profile" type="Microsoft.ScalableHosting.Configuration.ProfileConfigHandler, MemberRole, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b7c773fb104e7562"/>
<section name="anonymousIdentification" type="Microsoft.ScalableHosting.Configuration.AnonymousIdConfigHandler, MemberRole, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b7c773fb104e7562"/>
</sectionGroup>
</configSections>
<appSettings>
<add key="SiteSqlServer" value="--snip--" />
<add key="SiteSqlServerOwner" value="dbo" />
<add key="MachineValidationKey" value="F9D1A2D3E1D3E2F7B3D9F90FF3965ABDAC304902" />
<add key="MachineDecryptionKey" value="F9D1A2D3E1D3E2F7B3D9F90FF3965ABDAC304902F8D923AC" />
<add key="MachineValidationMode" value="SHA1" />
<add key = "ComponentArt.Web.UI.ClientScriptLocation" value = "~/Utility/componentart_webui_client" />
</appSettings><system.web>
<machineKey
validationKey="F9D1A2D3E1D3E2F7B3D9F90FF3965ABDAC304902"
decryptionKey="F9D1A2D3E1D3E2F7B3D9F90FF3965ABDAC304902F8D923AC"
validation="SHA1" /><!-- Standard Application Settings -->
<compilation defaultLanguage="c#" debug="false">
<assemblies>
<add assembly="MemberRole, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b7c773fb104e7562"/>
</assemblies>
</compilation>
<pages validateRequest="false" autoEventWireup="true" pageBaseType="CommunityServer.Components.CSPage, CommunityServer.Components"/>
<trace enabled="false" requestLimit="40" localOnly="true"/>
<sessionState mode="Off" />
<!-- Permit detailed errors to be displayed for remote clients -->
<customErrors mode="Off" defaultRedirect = "error.htm" />
<!-- START - CommunityServer specific application settings -->
<httpModules>
<add name="CommunityServer" type="CommunityServer.CSHttpModule, CommunityServer.Components" />
<add name="CSProfile" type="Microsoft.ScalableHosting.Profile.ProfileModule, MemberRole, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b7c773fb104e7562"/>
<add name="CSRoleManager" type="Microsoft.ScalableHosting.Security.RoleManagerModule, MemberRole, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b7c773fb104e7562" />
</httpModules><httpHandlers>
<add verb="GET" path="Utility/redirect.aspx" type="CommunityServer.Components.Redirect, CommunityServer.Components" />
<add verb="GET" path="aggbug.aspx" type="CommunityServer.Components.HttpHandler.AggBugHandler, CommunityServer.Components" />
<add verb="GET" path="avatar.aspx" type="CommunityServer.Components.HttpHandler.AvatarHttpHandler, CommunityServer.Components" />
<add verb="GET" path="vcard.aspx" type="CommunityServer.Components.HttpHandler.VCardHttpHandler, CommunityServer.Components" />
<add verb="POST" path = "rsscomments/*.aspx" type="CommunityServer.Blogs.Components.RssCommentHandler, CommunityServer.Blogs" />
<add verb="GET" path="r.ashx" type="CommunityServer.Components.HttpHandler.TinyUrlHttpHandler, CommunityServer.Components" />
<add verb="*" path="ImageHipChallenge.aspx" type="Msdn.Web.UI.WebControls.ImageHipChallengeHandler, Hip"/>
</httpHandlers><!--
authentication :
To use Windows Authentication, you must turn off Anonymous authentication in IIS
or IIS will never pass the user credentials to the forums.To enable Windows Authentication, simply comment out the forms authentication section
below and uncomment the Windows Authentication stuff.To use the CookieAuthentication add-on module, set the authentication mode to "None" and
comment out the forms element.
-->
<authentication mode="Forms">
<forms name=".CommunityServer" protection="All" timeout="60" loginUrl="login.aspx" slidingExpiration="true" />
</authentication>
</system.web><location path="EditPost.aspx">
<system.web>
<authorization>
<deny users="?" />
</authorization>
</system.web>
</location><location path="PrivateMessage.aspx">
<system.web>
<authorization>
<deny users="?" />
</authorization>
</system.web>
</location>
<location path="Download.aspx">
<system.web>
<authorization>
<deny users="?" />
</authorization>
</system.web>
</location><location path="License.aspx">
<system.web>
<authorization>
<deny users="?" />
</authorization>
</system.web>
</location>
<memberrolesprototype><!--
========================
Membership
========================
Attributes:
userIsOnlineTimeWindow="int" Time window (in minutes) to consider a User as being Online after since last activity
hashAlgorithmType="[SHA1|SHA512|MD5|...]" Any valid hash algorithm supported by .NET framework, default is SHA1
Child nodes:
<providers> Providers (class must inherit from MembershipProvider)
<add Add a provider
name="string" Name to identify this provider instance by
type="string" Class that implements MembershipProvider
provider-specific-configuration />
</providers>Configuration for SqlMembershipProvider and AccessMembershipProvider:
connectionStringName="string" Name corresponding to the entry in <connectionStrings> section where the connection string for the provider is specified
passwordAttemptThreshold="int" The number of failed password attempts, or failed password answer attempts that are allowed before locking out a user?s account
passwordAttemptWindow="int" The time window, in minutes, during which failed password attempts and failed password answer attempts are tracked
enablePasswordRetrieval="[true|false]" Should the provider support password retrievals
enablePasswordReset="[true|false]" Should the provider support password resets
requiresQuestionAndAnswer="[true|false]" Should the provider require Q & A
applicationName="string" Optional string to identity the application: defaults to Application Metabase path
requiresUniqueEmail="[true|false]" Should the provider require a unique email to be specified
passwordFormat="[Clear|Hashed|Encrypted]" Storage format for the password: Hashed (SHA1), Clear or Encrypted (Triple-DES)
description="string" Description of what the provider does
-->
<membership userIsOnlineTimeWindow="15" >
<providers>
<add
name="CommunityServerSqlProvider"
type="CommunityServer.MemberRole.CSMembershipProvider, CommunityServer.MemberRole"
connectionStringName="SiteSqlServer"
enablePasswordRetrieval="false"
enablePasswordReset="true"
requiresQuestionAndAnswer="false"
requiresUniqueEmail="true"
passwordFormat="Hashed"
applicationName="dev"
description="Stores and retrieves membership data from the local Microsoft SQL Server database"
maxInvalidPasswordAttempts = "999"
passwordAttemptWindow = "999"
minRequiredPasswordLength = "6"
minRequiredNonalphanumericCharacters = "0"
/>
</providers>
</membership>
<!--
========================
Role Manager
========================
enabled="[true|false]" Feature is enabled?
cacheRolesInCookie="[true|false]" Cache roles in cookie?
cookieName=".ASPXROLES" Cookie Name
createPersistentCookie="[true|false]" Creates a persistent cookie or session cookie?
cookieTimeout="30" Cookie Timeout
cookiePath="/" Cookie Path
cookieRequireSSL="[true|false]" Set Secure bit in Cookie
cookieSlidingExpiration="[true|false]" Reissue expiring cookies?
cookieProtection="[None|Validation|Encryption|All]" How to protect cookies from being read/tampered
defaultProvider="string" Name of provider to use by default
domain="[domain]" Enables output of the "domain" cookie attribute set to the specified value
maxCachedResults="int" Maximum number of roles to cache in cookieChild nodes:
<providers> Providers (class must inherit from RoleProvider)<add Add a provider
name="string" Name to identify this provider instance by
type="string" Class that implements RoleProvider
provider-specific-configuration /></providers>
<providers> type="TypeName" Class that inherits from System.Web.Security.RoleProvider
providerSpecificConfig Config for the provider
Configuration for SqlRoleProvider:
connectionStringName="string" Name corresponding to the entry in <connectionStrings> section where the connection string for the provider is specified
description="string" Description of what the provider does
commandTimeout="int" Command timeout value for SQL command
--><roleManager
cacheRolesInCookie="true" cookieName=".CSRoles" cookieTimeout="90"
cookiePath="/" cookieRequireSSL="false" cookieSlidingExpiration="true"
createPersistentCookie="true" cookieProtection="All" maxCachedResults="1000" >
<providers>
<add
name="CommunityServerSqlProvider"
type="CommunityServer.MemberRole.CSRoleProvider, CommunityServer.MemberRole"
connectionStringName="SiteSqlServer"
applicationName="dev"
description="Stores and retrieves roles data from the local Microsoft SQL Server database"
/>
</providers>
</roleManager>
<!--
========================
Profile
========================
Configuration for profile:
<profile>
enabled="[true|false]" Feature is enabled?
automaticSaveEnabled="[true|false]" Enable automatic save of profile
inherits="type-name" Class from which the profile type inherits from. This type must inherit from ProfileBase type.<providers> Providers (class must inherit from ProfileProvider)
<add Add a provider (only single entry supported)
name="string" Name to identify this provider instance by
type="string" Class that implements ProfileProvider
provider-specific-configuration />
<providers><properties> Optional element. List of properties in the Profile system
<add Add a property
name="string" Name of the property
type="string" Optional. Type of the property. Default: string.
readOnly="[true|false]" Optional. Is Value read-only. Default: false.
defaultValue="string" Optional. Default Value. Default: Empty string.
allowAnonymous="[true|false]" Optional. Allow storing values for anonymous users. Default: false.
serializeAs=["String|Xml|Binary|ProviderSpecific"] Optional. How to serialize the type. Default: ProviderSpecific.
/>
</properties>
</profile>
--><profile enabled="true" >
<providers>
<add
name="CommunityServerSqlProvider"
type="CommunityServer.MemberRole.CSProfileProvider, CommunityServer.MemberRole"
connectionStringName="SiteSqlServer"
applicationName="dev"
description="Stores and retrieves profile data from the local Microsoft SQL Server database"
/>
</providers><properties>
<add name = "commonName" type = "string" />
<add name = "birthdate" type = "DateTime" />
<add name = "gender" type = "int" defaultValue = "0" />
<add name = "dateFormat" type = "string" defaultValue="MM-dd-yyyy" />
<add name = "publicEmail" type = "string" />
<add name = "language" type = "string" />
<add name = "webAddress" type = "string" />
<add name = "webLog" type = "string" />
<add name = "webGallery" type = "string" />
<add name = "signature" type = "string" />
<add name = "signatureFormatted" type = "string" />
<add name = "location" type = "string" />
<add name = "occupation" type = "string" />
<add name = "interests" type = "string" />
<add name = "msnIM" type = "string" />
<add name = "yahooIM" type = "string" />
<add name = "aolIM" type = "string" />
<add name = "icqIM" type = "string" />
<add name = "enablePostPreviewPopup" type = "System.Boolean" defaultValue = "false" />
<add name = "enableEmoticons" type = "System.Boolean" defaultValue = "true" />
<add name = "timezone" type = "System.Double" defaultValue="0" />
<add name = "fontsize" type = "int" defaultValue = "0" />
<add name = "bio" type = "string" />
</properties>
</profile>
<!--
========================
Anonymous Identification
========================
anonymousIdentification configuration:
enabled="[true|false]" Feature is enabled?
cookieName=".ASPXANONYMOUS" Cookie Name
cookieTimeout="100000" Cookie Timeout in minutes
cookiePath="/" Cookie Path
cookieRequireSSL="[true|false]" Set Secure bit in Cookie
cookieSlidingExpiration="[true|false]" Reissue expiring cookies?
cookieProtection="[None|Validation|Encryption|All]" How to protect cookies from being read/tampered
domain="[domain]" Enables output of the "domain" cookie attribute set to the specified value
-->
<anonymousIdentification
enabled="false"
cookieName=".ASPXANONYMOUS"
cookieTimeout="100000"
cookiePath="/"
cookieRequireSSL="false"
cookieSlidingExpiration="true"
cookieProtection="None" domain="" />
</memberrolesprototype>
</configuration>
-
The following line looks suspicious:
<forms name=".CommunityServer" protection="All" timeout="60" loginUrl="login.aspx" slidingExpiration="true" />
Maybe you should try what happens if you change 60 to, say, 240. If auto-signon lasts for 4 hours then, you know this is the right place.
-
That line indeed is the auto-signon, but when creating the ticket an option is to create a persisitant one -- i.e., one that ignores the 60 minute timeout.
No matter, I've just now deployed the site using 1.1 framework, so let's see how this goes ...
-
@Alex Papadimoulis said:
That line indeed is the auto-signon, but when creating the ticket an option is to create a persisitant one -- i.e., one that ignores the 60 minute timeout.
I hope I'm not too much of a "know-it-all", but are you sure this persistance doesn't only affect the lifetime of the cookie (on the browser side) while the timeout on the server side (how long does the server accept it) stays the same?
-
@ammoQ said:
@Alex Papadimoulis said:
That line indeed is the auto-signon, but when creating the ticket an option is to create a persisitant one -- i.e., one that ignores the 60 minute timeout.
I hope I'm not too much of a "know-it-all", but are you sure this persistance doesn't only affect the lifetime of the cookie (on the browser side) while the timeout on the server side (how long does the server accept it) stays the same?
I agree with ammoQ. Seems that the option to create a persistent one, according to the thread in the cs.org forum you linked to, is to create a persitent cookie -- as opposed to a session cookie -- and perhaps does not override the server-side time-out. If this is the case, then the end result would be that the browser receives a persistent cookie for 30 days, as you configured it, yet the server expires the authentication session token after 60 minutes. Which sounds pretty close to what is actually occurring.
-dZ.
-
This is exactly what happened -- the server expired the token after XX minutes (60, or whatever I configured it for). However, it shouldn't have -- here's what happens when you logon:
HttpCookie formsAuthCookie;
formsAuthCookie = FormsAuthentication.GetAuthCookie(userToLogin.Username, autoLogin.Checked);
UserCookie userCookie = csContext.User.GetUserCookie();
userCookie.WriteCookie(formsAuthCookie, 30, autoLogin.Checked);The WriteCookie method writes it out to the Response.Cookies collection as expected. The FormsAuthentication class is built into ASP.NET, so I have no idea why ASP.NET expired the cookie even though the "createPersistent" flag (2nd param to GetAuthCookie) was set to true.
But no matter, switching the compilation to ASP.NET 1.1 seemed to do the trick. I have no intention of making any other significant changes (maybe when they do CS3.0) anytime soon, so I can worry about this later :-)
-
@Alex Papadimoulis said:
This is exactly what happened -- the server expired the token after XX minutes (60, or whatever I configured it for). However, it shouldn't have -- here's what happens when you logon:
HttpCookie formsAuthCookie;
formsAuthCookie = FormsAuthentication.GetAuthCookie(userToLogin.Username, autoLogin.Checked);
UserCookie userCookie = csContext.User.GetUserCookie();
userCookie.WriteCookie(formsAuthCookie, 30, autoLogin.Checked);The WriteCookie method writes it out to the Response.Cookies collection as expected. The FormsAuthentication class is built into ASP.NET, so I have no idea why ASP.NET expired the cookie even though the "createPersistent" flag (2nd param to GetAuthCookie) was set to true.
But no matter, switching the compilation to ASP.NET 1.1 seemed to do the trick. I have no intention of making any other significant changes (maybe when they do CS3.0) anytime soon, so I can worry about this later :-)
A quick Google of "ASP.NET persistent cookie timeout" suggests that, while in ASP.NET 1.1 an auth token created with GetAuthCookie and createPersistent set to true essentially never expires, on ASP.NET 2.0 it expires just as soon as one created with createPersistent set to false. Don't ask me why... apparently ASP.NET is the real WTF.
-
Hooked on Auto Sign-on worked for me!
-
Totally works for me also and has worked for the past few days.