Skip to main content
Known Participant
August 13, 2014
Question

CF11 : cflogin doesn't "stuck" after session/login timeout

  • August 13, 2014
  • 6 replies
  • 6918 views

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>

    This topic has been closed for replies.

    6 replies

    mvierow
    Inspiring
    February 18, 2016

    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."

    Known Participant
    January 28, 2016

    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.

    CCPSWebmaster
    Participant
    June 16, 2015

    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.

    CCPSWebmaster
    Participant
    June 16, 2015

    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!

    itisdesign
    Inspiring
    May 17, 2015

    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

    BKBK
    Community Expert
    Community Expert
    August 14, 2014

    <cfset this.name = hash( getCurrentTemplatePath() ) />

    Problematic, as the application's name changes per page request. Sessions are dependent on the application name. Therefore, the session will break whenever the template path changes.

    To verify this hypothesis, test it with

            <cfset this.name = hash("test string") />

    <cfset this.applicationTimeout = createTimeSpan(1,0,0,0) />

    <cfset this.sessionTimeout = createTimeSpan(0,0,20,0 ) />

    silmarilAuthor
    Known Participant
    August 14, 2014

    Well no, actually the TemplatePath() is the path to Application.cfc in this case. It's an example taken from bennadel.com blog, but i also did try a fixed application name, it doesn't change anything.

    Also: this exact same application behave correctly on a BlueDragon 7.1 server.

    Using loginStorage="Cookie" on CF11 however seem a bit better, but there are some weirdness occasionnaly.

    silmarilAuthor
    Known Participant
    August 18, 2014

    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>


    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.