Copy link to clipboard
Copied
Hi,
Since migrating from CFMX7 to CF11 we are experiencing some weird failure with cflogin (using session or cookie storage).
Basically when we log-in on the application after a session/client timeout the first login doesn't last for longer than the login submit request.
The second login however is OK
I made a very simple application.cfc/index.cfm with short timeouts to check this:
<cfcomponent
output="false"
hint="I define the application settings and event handlers.">
<!--- Define the application settings. --->
<cfset this.name = hash( getCurrentTemplatePath() ) />
<cfset this.applicationTimeout = createTimeSpan( 0, 0, 10, 0 ) />
<cfset this.sessionTimeout = createTimeSpan( 0, 0, 0, 10 ) />
<!--- Set up the application. --->
<cfset THIS.SessionManagement = true />
<cfset THIS.ClientManagement = true />
<cfset THIS.SetClientCookies = true />
<cfset THIS.loginStorage = "Session" />
<cfset THIS.clientStorage = "sidys" />
<!--- Define the request settings. --->
<cfsetting showdebugoutput="false" />
<cffunction
name="OnRequestStart"
access="public"
returntype="boolean"
output="true"
hint="Fires at first part of page processing.">
<!--- Define arguments. --->
<cfargument
name="TargetPage"
type="string"
required="true"
/>
<cfset SetLocale("fr_FR") />
<cfif IsDefined("Form.logout") or IsDefined("URL.logout")>
<cflogout />
</cfif>
<cflogin idletimeout="20">
<cfdump var="#Session#">
<cfinclude template="form.inc" />
<cfif not isDefined("cflogin") or (cflogin.name IS "" OR cflogin.password IS "")>
<cfoutput>
<form method="post">
<b>login :</b>
<input type="text" name="j_username" size="24" class="champ" />
<b>passwordnbsp;:</b>
<input type="password" name="j_password" size="15" class="champ" />
<input type="submit" value="Login" class="button" name="submit" />
</form>
</cfoutput>
<cfabort>
<cfelse>
<cflock timeout="10" scope="Session" type="exclusive">
<cfloginuser name="#cflogin.name#" Password="#cflogin.password#" roles="role">
<cfset Session.id=cflogin.name />
</cflock>
</cfif>
</cflogin>
<cfdump var="#Session#">
<cfif GetAuthUser() NEQ "">
<cfoutput>
<form method="Post">
<input type="submit" Name="Logout" value="Logout">
</form>
</cfoutput>
</cfif>
<cfreturn true />
</cffunction>
</cfcomponent>
Copy link to clipboard
Copied
Silmaril,
I am investigating this further. There seems to be more to it.
Copy link to clipboard
Copied
I have discovered the cause of the issue. When I examined the logs, I found that the tests I performed generated many errors in coldfusion-out.log and security.log. The error message was "An error occurred while fetching element from authcache".
Looking further, I found that what you and I observed was in fact the expected behaviour. It is all due to the new security enhancements since Coldfusion 10. If you follow this link, you will read:
"Now you can have only one active session open for one user for a given application that uses the cflogin tag."
This tells you that, from Coldfusion 10 onwards, cflogin can only store one username-password set per session. So, imagine that the session is still active, and the current login has just timed out. When you now attempt a second login, comprising a username-password pair distinct from the first, Coldfusion will log you out.
This gives me a clue as to why it was difficult for me to reproduce the issue. I kept using the same username-password pair, which is allowed by the security enhancements. According to this hypothesis, you could readily reproduce the issue because you tested with varying login credentials.
Copy link to clipboard
Copied
I do see the error fetching from authcache but i do use the same login/password on the tests sequences, and also on our production application we don't have any other choice that using the same login/password.
However i did one check, as i said before CF11 has added the tag "allowConcurrent" to tweak the multi-login problem, and if i switch to 'allowConcurrent="false"' which seem to be the previous comportement from CF10 then if the session timeout before the login there is no problem.
If i change it back to the default "allowConcurrent='true'" then it start failing again.
Also the authcache errors doesn't seem to be 100% related to the failure since the message doesn't happen all the time
Copy link to clipboard
Copied
I also used cflogin's default value of allowConcurrent=true, by omission. To synchronize with you, the rest of my test procedures and files were as follows.
I commented out the cfsetting tag, and switched on debugging in the Coldfusion Administrator. I also removed the cfabort tag after <cfinclude template="loginForm.cfm"> to enable onRequestStart to return.
index.cfm
We are in index.cfm<br>
getAuthUser(): <cfoutput>#getAuthUser()#</cfoutput><br>
<cfdump var="#session#">
Application.cfc
<cfcomponent>
<!--- Define the application settings. --->
<cfset this.name = hash(getCurrentTemplatePath()) />
<cfset this.applicationTimeout = createTimeSpan(1,0,0,0) />
<cfset this.sessionTimeout = createTimeSpan(0,0,0,30) /><!--- timeout = 30 seconds--->
<!--- Set up the application. --->
<cfset THIS.SessionManagement = true />
<cfset THIS.ClientManagement = false />
<cfset THIS.SetClientCookies = true />
<cfset THIS.loginStorage = "Session" />
<!--- <cfset THIS.clientStorage = "sidys" /> --->
<!--- Define the request settings. --->
<!--- <cfsetting showdebugoutput="false" /> --->
<cffunction
name="OnRequestStart"
access="public"
returntype="boolean"
output="true"
hint="Fires at first part of page processing.">
<!--- Define arguments. --->
<cfargument
name="TargetPage"
type="string"
required="true"
/>
<cfset SetLocale("fr_FR") />
<cfif IsDefined("Form.logout") or IsDefined("URL.logout")>
<cflogout />
</cfif>
<cflogin idletimeout="20"><!--- timeout = 20 seconds--->
<!--- <cfinclude template="form.inc" /> --->
<cfif isDefined("cflogin.name") AND cflogin.name IS NOT "" AND cflogin.password IS NOT "">
<!--- login form submitted, with username and password filled in --->
<cfloginuser name="#cflogin.name#" Password="#cflogin.password#" roles="role">
<cfset Session.id=cflogin.name />
<cfelseif getAuthUser() IS "">
<!--- User not yet logged in --->
<cfinclude template="loginForm.cfm">
</cfif>
</cflogin>
<cfif getAuthUser() NEQ "">
<cfinclude template="logoutForm.cfm">
</cfif>
<cfreturn true />
</cffunction>
</cfcomponent>
loginForm.cfm
<div>
<form method="post">
<b>login :</b>
<input type="text" name="j_username" size="24" class="champ" />
<b>password :</b>
<input type="password" name="j_password" size="15" class="champ" />
<input type="submit" value="Login" class="button" name="submit" />
</form>
</div>
logoutForm.cfm
<div>
<form method="Post">
<input type="submit" Name="Logout" value="Logout">
</form>
</div>
Copy link to clipboard
Copied
Hi,
I think the main difference is that your cflogin.idleTimeout is less that the sessionTimeout, to make it really reproducable you need to have it greater than or equal to the sessionTimeout.
Well it also happens in this case (idleTimeout < sessionTimeout) for me but ...
In this case i also regularly see another weird comportement: If i got back on the back after the idleTimeout but before the sessionTimeout the <cflogin> part is triggered again and the previous login+password are automatically injected into the cflogin Structure. (i putted <cfif isDefined("cflogin")><cfdump var="#cflogin#" label="cflogin"></cfif> into the <cflogin> block.
Copy link to clipboard
Copied
silmaril wrote:
I think the main difference is that your cflogin.idleTimeout is less that the sessionTimeout, to make it really reproducable you need to have it greater than or equal to the sessionTimeout.
I deliberately chose to test with cflogin.idleTimeout <= sessionTimeout. I consider the alternative unrealistic. A use case which requires a login to still be active, while the session storing it has already timed out, is improbable.
Well it also happens in this case (idleTimeout < sessionTimeout) for me but ...
In this case i also regularly see another weird comportement: If i got back on the back after the idleTimeout but before the sessionTimeout the <cflogin> part is triggered again and the previous login+password are automatically injected into the cflogin Structure.
Oh dear. I will look into that, too.
Copy link to clipboard
Copied
I deliberately chose to test with cflogin.idleTimeout <= sessionTimeout. I consider the alternative unrealistic. A use case which requires a login to still be active, while the session storing it has already timed out, is improbable.
I concur, having idleTimeout > sessionTimeout isn't really usefull, having it equal (which is my usecase) however seems more likely
Copy link to clipboard
Copied
Well, apparently using loginStorage="Cookie" isn't really better, just less likely to trigger a bug apparently.
However it also trigger a new one, with very few details, just a stack trace and a context matching the <cflogin> tag (but named CFAUTHENTICATE)
java.lang.NullPointerException at java.util.Hashtable.put(Unknown Source) at coldfusion.runtime.SecurityScopeTracker.setSecurity(SecurityScopeTracker.java:277) at coldfusion.runtime.SecurityScopeTracker.getSecurity(SecurityScopeTracker.java:125) at coldfusion.tagext.security.AuthenticateTag.doStartTag(AuthenticateTag.java:192) at cfApplication2ecfc1163109273$funcONREQUESTSTART.runFunction(/var/www/sidysv2/Application.cfc:99) at coldfusion.runtime.UDFMethod.invoke(UDFMethod.java:487) at coldfusion.runtime.UDFMethod$ReturnTypeFilter.invoke(UDFMethod.java:420) at coldfusion.runtime.UDFMethod$ArgumentCollectionFilter.invoke(UDFMethod.java:383) at coldfusion.filter.FunctionAccessFilter.invoke(FunctionAccessFilter.java:95) at coldfusion.runtime.UDFMethod.runFilterChain(UDFMethod.java:334) at coldfusion.runtime.UDFMethod.invoke(UDFMethod.java:231) at coldfusion.runtime.TemplateProxy.invoke(TemplateProxy.java:643) at coldfusion.runtime.TemplateProxy.invoke(TemplateProxy.java:432) at coldfusion.runtime.TemplateProxy.invoke(TemplateProxy.java:402) at coldfusion.runtime.AppEventInvoker.invoke(AppEventInvoker.java:108) at coldfusion.runtime.AppEventInvoker.onRequestStart(AppEventInvoker.java:278) at coldfusion.filter.ApplicationFilter.invoke(ApplicationFilter.java:455) at coldfusion.filter.RequestMonitorFilter.invoke(RequestMonitorFilter.java:42) at coldfusion.filter.MonitoringFilter.invoke(MonitoringFilter.java:40) at coldfusion.filter.PathFilter.invoke(PathFilter.java:141) at coldfusion.filter.ExceptionFilter.invoke(ExceptionFilter.java:94) at coldfusion.filter.BrowserDebugFilter.invoke(BrowserDebugFilter.java:78) at coldfusion.filter.ClientScopePersistenceFilter.invoke(ClientScopePersistenceFilter.java:28) at coldfusion.filter.BrowserFilter.invoke(BrowserFilter.java:38) at coldfusion.filter.NoCacheFilter.invoke(NoCacheFilter.java:58) at coldfusion.filter.GlobalsFilter.invoke(GlobalsFilter.java:38) at coldfusion.filter.DatasourceFilter.invoke(DatasourceFilter.java:22) at coldfusion.filter.CachingFilter.invoke(CachingFilter.java:62) at coldfusion.CfmServlet.service(CfmServlet.java:219) at coldfusion.bootstrap.BootstrapServlet.service(BootstrapServlet.java:89) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) at coldfusion.monitor.event.MonitoringServletFilter.doFilter(MonitoringServletFilter.java:42) at coldfusion.bootstrap.BootstrapFilter.doFilter(BootstrapFilter.java:46) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:422) at org.apache.coyote.ajp.AjpProcessor.process(AjpProcessor.java:198) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607) at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:313) at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) at java.lang.Thread.run(Unknown Source)
Copy link to clipboard
Copied
silmaril wrote:
Well it also happens in this case (idleTimeout < sessionTimeout) for me but ...
In this case i also regularly see another weird comportement: If i got back on the back after the idleTimeout but before the sessionTimeout the <cflogin> part is triggered again and the previous login+password are automatically injected into the cflogin Structure.
I have been unable to reproduce that. The test code I use is the last set I posted on August 18.
Well, apparently using loginStorage="Cookie" isn't really better, just less likely to trigger a bug apparently.
However it also trigger a new one, with very few details, just a stack trace and a context matching the <cflogin> tag (but named CFAUTHENTICATE)
I was unable to reproduce that, too. Coldfusion says there is an error at line 99 of /var/www/sidysv2/Application. cfc. Could you show us that line?
Copy link to clipboard
Copied
Sorry, i missed your reply,
I haven't had the CFAUTHENTICATE error for a while, i think because of one of the recent patches and the Application.cfc has changed a bit since there ....
However the "double login" situation is still very "present", but less with Cookie storage than Session storage, still don't know why.
As for the "automatic relogin", i'm still able to capture this sometime, for example with loginStorage=Session and when i request a
page near the sessionTimeout, but it's not everytime.
Here is my test files:
Copy link to clipboard
Copied
See this Stackoverflow issue for the same issue:
ColdFusion User login fails after session timeout - Stack Overflow
Copy link to clipboard
Copied
Hi Benoit,
I believe 3732198 resolved the java.lang.NullPointerException in CF10 Update 14. I've added the following comment to 3839458:
-----------
Another workaround is duplicate the <cflogin>/cflogin(). Example:
<cflogin ..>
<cflogin ..>
When both have allowconcurrent=true (the default), then both will run. isUserLoggedIn() returns YES after the 1st, but the 1st login actually fails. The 2nd runs and logs in correctly.
Repro attached as Application.cfc
When THIS.loginStorage="cookie", then the issue does not reoccur if an old cfauthorization cookie is still present.
-----------
Thanks!,
-Aaron
Copy link to clipboard
Copied
I am having the same issue, but I noticed something very strange...
Here is my Application.cfc
<cfcomponent>
<cfset This.name = "WebsiteCMS">
<cfset This.applicationTimeout = "#createTimeSpan(5,0,0,0)#">
<cfset This.datasource = "CMS">
<cfset This.loginStorage = "session">
<cfset This.Sessionmanagement = true>
<cfset This.Sessiontimeout = "#createTimeSpan(0,0,0,10)#">
<cfset This.mappings["/www"] = getDirectoryFromPath(getCurrentTemplatePath())>
<!--- Application Starts --->
<cffunction name="onApplicationStart">
<cfset APPLICATION.DOMAIN = "http://localhost/website/">
<cfset APPLICATION.DIRECTORY = "C:\inetpub\wwwroot\website\">
</cffunction>
<!--- A Page Request is made --->
<cffunction name="onRequestStart" access="public">
<cfargument type="string" name="targetPage" required="true">
<cflogin idletimeout="#createTimeSpan(0,0,0,10)#">
<cfif IsDefined("CFLOGIN.name") and Len(Trim(CFLOGIN.name)) and Len(Trim(CFLOGIN.password))>
<!--- Check if User has Access --->
<cfif CFLOGIN.name is "USERWITHACCESS">
<!--- Check if User Exists --->
<cftry>
////////////////////////// LDAP Minified for obvious reasons //////////////////////////////
<cfldap action="query"
name="CheckIfUser"
>
<cfcatch type="any">
<cfset LoginMessage = "Username or Password Incorrect">
</cfcatch>
</cftry>
<cfif CheckIfUser.recordCount gt 0>
<!--- If User Exists and HAS Access --->
<!--- Authenticate user to check password --->
<cftry>
///////////////////////////// LDAP Minified for obvious reasons //////////////////////////////
<cfldap action="query"
name="AuthenticateUser"
>
<cfset LoginMessage = "Success">
<cfcatch type="any">
<cfset LoginMessage = "Username or Password Incorrect">
</cfcatch>
</cftry>
</cfif>
<!--- If User authentication succeeded --->
<cfif LoginMessage is "Success">
<cfloginuser name="#CFLOGIN.name##createUUID()#" password="password" roles="user">
<cfelse>
<cfinclude template="loginForm.cfm"><cfabort>
</cfif>
<cfelse>
<!--- User Does NOT have access --->
<cfset LoginMessage = "You do not have access to this System">
<cfinclude template="loginForm.cfm"><cfabort>
</cfif>
<cfelse>
<!---#### they didn't fill out form, return to the login form. ####--->
<cfinclude template="loginForm.cfm"><cfabort>
</cfif>
</cflogin>
</cffunction>
</cfcomponent>
Please take note of the <cfloginuser> line:
<cfloginuser name="#CFLOGIN.name##createUUID()#" password="password" roles="user">
I was attempting to force each login to be unique to see if it was a SESSION causing the issue.
I login and refresh the page a couple of times, but then something interesting happened.
I was greated with the login screen with the error message:
"You do not have access to this System"
What this means is that for some reason the CFLOGIN.name and CFLOGIN.password fields were resent to the server. However because this message came up that means the userID was NOT "USERWITHACCESS"
So to test my theory I modified the alert message:
<cfset LoginMessage = "You do not have access to this System " & CFLOGIN.name>
SURE ENOUGH this is what I got:
You do not have access to this System USERWITHACCESS17E0C4A160-EAEB-5C23-FDF8DB569F65D3C2
What this means is the <cfloginuser> tag is resubmitting the CFLOGIN variables.
So I logged in again, and started refeshing the page to keep the <cflogin> timeout from firing.
I Timed it. I get that error at Exactly 10 Seconds after I log in which is the Timeout I have set for the SESSION Variables.
It seems like when the SESSION variable times out but the <cflogin> has not coldfusion resubmits the Login information that was stored in the <cfloginuser> tag. However the User is retaining the OLD Session ID instead of being re-assigned to the new ID.
Can anyone else verify my logic?
Also the only reason I have the <cfif CFLOGIN.name is "USERWITHACCESS"> in there is because of a last minute "Hey we only want these people to have access!" And we have yet to create the Group on our AD server (to check with LDAP) So it was quickly thrown in there. Which luckily caused me to notice this!
Copy link to clipboard
Copied
Other than in my example above:
<cfloginuser name="#CFLOGIN.name##createUUID()#" password="#CFLOGIN.password#" roles="ROLES">
Should fix the Double Login Issue. Although I am not sure if it creates any other issues.
Copy link to clipboard
Copied
I hope this is resolved soon, I have several sites that started requiring you to log in twice at random due to upgrading to CF11. I have Update 7. I really don't want to have to go modify the code if it is just an update fix.
Copy link to clipboard
Copied
Just wanted to jump in as a developer experiencing the same issue.
In most of my applications I am handling authentication on my own, using CFID/CFTOKEN to access a session scope where I keep credentials, those are not affected. The ones where I decided to use isUserInRole()/isUserLoggedIn(), I am affected. So one work around is to manage your roles in the session scope instead of the roles attribute of cfloginuser. Create your own UDF to replace the two previous functions that instead accesses whatever you've placed in the session scope.
Found this in security.log also. Time matches when I attempted to sign in:
"Information","ajp-bio-8014-exec-7","02/18/16","10:31:15",,"An error occurred while fetching element from authcache."