Solved

What are cfauthentication and cflogin best practices?

Posted on 2004-10-14
6
662 Views
Last Modified: 2013-12-24
I am setting up user authentication and authorization using the cflogin tag within the application.cfm page.

Depending on the timeout settings for session timeout in the cfapplication tag and idletimeout in the cflogin tag, I have been able to produce situations where I login, then logout and I when I log back in, the cflogin tag does not get called, until it times out, even though the cflogout tag was called.  If I set the idletimeout to a very short timeout, then the cflogin tag will get called, but then if a user is frequently sent back to the login page, the idletimeout seems to kick in and they are sent back to the login page.  

I also have the cflogout in the applcation.cfm and within that, I have code that clears the session structure. I read somewhere that it was a good idea to clear the session vars just in case the user did not close the page.

I am sure I am missing something somewhere.  

Here is my code:   (please note that the LDAP code is not my own, it was derived from Rob Brooks-Bilson's O'Reilly Book "Programming ColdFusion MX"

Application.cfm
===============
<cfapplication name="PortalPrototype"  
          clientmanagement="yes"
          sessionmanagement="yes"
          setclientcookies="yes"
          loginstorage="session"
                                sessiontimeout="#CreateTimeSpan(0, 0, 30, 0)#"
                     applicationtimeout="#CreateTimeSpan(1, 0, 0, 0)#">

<!--- Check to see if the application has been initialized.  If not, set the
      necessary application variables and initialize the app --->
<cflock scope="Application" type="ReadOnly" timeout="5" throwontimeout="No" >
  <cfset IsInitialized = IsDefined('application.Initialized')>
</cflock>    

<cfif not IsInitialized>
   <!--- DEBUG FEEDBACK --->      
   <cfoutput>Application is not initialized.  Initializing now...</cfoutput>    
  <cflock type="Exclusive" scope="Application" timeout="10">
    <cfif not IsDefined('application.Initialized')>
      <cfset application.DSN = "">
      <cfset application.AdminEmail = "">
      <cfset application.Initialized = true>
    </cfif>
  </cflock>
<cfelse>
   <!--- DEBUG FEEDBACK --->      
   <cfoutput>Application is already initialized</cfoutput>
</cfif>


<!--- If the user clicked the logout button or link, log them out --->
<cfif isDefined("URL.Logout")>
                 <!--- DEBUG FEEDBACK --->
     <cfoutput>Logging out...</cfoutput>
     <cfdump var="#session#">
     <cfoutput>#GetAuthUser()#</cfoutput>
     <cflogout>
     <!--- Terminate the user's session by deleting all session variables --->
     <cflock scope="session" type="exclusive" timeout="60" throwontimeout="no">

          <cfset StructClear(session)>
                               <!--- DEBUG FEEDBACK --->
          <cfdump var="#session#">
          <cfoutput>#GetAuthUser()#</cfoutput>
     </cflock>
     
     <!--- added the following cookie code after reading about it at Experts Exchange. --->
     <cfif IsDefined("Cookie.CFID") AND IsDefined("Cookie.CFTOKEN")>
           <cfset cfid_local = Cookie.CFID>
           <cfset cftoken_local = Cookie.CFTOKEN>
           <cfcookie name="CFID" value="#cfid_local#">
           <cfcookie name="CFTOKEN" value="#cftoken_local#">
                 </cfif>

   <cfset URL.message="Thank you for logging out. Please visit again soon!">
   <cfinclude template="loginform.cfm">
     <cfabort>
</cfif>


<cflogin idletimeout="1800" applicationtoken="Portal" cookiedomain=".domain.com">
    <!--- DEBUG FEEDBACK --->
    <cfoutput>We are in the cflogin tag...</cfoutput>    
    <cfdump var="#session#">
     <cfif not isDefined("cflogin")>
          <cfset URL.message="Please log in...">
          <cfinclude template="loginform.cfm">
          <cfabort>
     <cfelse>
         
          <!--- Validate the user and assign roles --->
          <!--- If for some reason username or password is blank, send the user back
          to the login form. --->

          <cfif cflogin.name IS "" OR cflogin.password IS "">
               <cfset URL.message="Either User Name or Password is blank">
               <cfinclude template="loginform.cfm">
               <cfabort>
          <cfelse>
               <!--- Perform the user validation --->

               <!--- setting basic attributes --->
               <cfset LDAP_root = "cn=users,dc=asi,dc=com">
               <cfset LDAP_server = "server.domain.com">
               <cfset LDAP_port = "389">
               <!--- These attributes are used in the first search. --->
               <!--- This filter will look in the object class for the user's ID. --->
               <cfset userfilter = "(&(objectclass=*)(sAMAccountName=#cflogin.name#))">
               <!--- Need directory manager's cn and password to get the user's
               password from the directory --->
               <cfset LDAP_username = "Domain\Server">
               <cfset LDAP_password = "***********">
            <!--- Search for the users's dn information.  This is used later to
                     authenticate the user.
                  NOTE: do this as the Direcotry Manager to ensure access to the information --->
                 
                <cftry>
                    <cfldap name="userSearch"
                      action="query"
                      attributes="cn,dn,sAMAccountName,mail"
                      start="#LDAP_root#"
                      scope="subtree"
                      server="#LDAP_server#"
                      port="#LDAP_port#"
                      filter="#userfilter#"
                      username="#LDAP_username#"
                      password="#LDAP_password#"
                    >
                   
                    <cfcatch type="any">
                  <!--- DEBUG FEEDBACK --->          
                                        <cfoutput>Error: #cfcatch.Message#. Type: #cfcatch.Type#  Code:000100</cfoutput>
                         <cfset UserSearchFailed = true>
                    </cfcatch>
                </cftry>
                     
       <!--- If user search failed or returns 0 rows, abort --->
               <cfif  NOT userSearch.RecordCount OR isDefined("UserSearchFailed")>
                    <cfset URL.message="Login error">
                    <cfinclude template="loginform.cfm">
                    <cfabort>
               <cfelse>
               
               </cfif>
       <!--- Pass the user's DN and password to see if the user authenticates.
                 and get the user's roles --->
               <cftry>
                    <cfldap
                          action="query"
                          name="auth"
                          attributes="cn"
                          start="cn=users,dc=asi,dc=com"
                          scope="subtree"
                          server="#LDAP_server#"
                          port="#LDAP_port#"
                          filter="(&(objectclass=group)(member=#userSearch.dn#))"
                          sort="cn"
                          username="#userSearch.mail#"
                          password="#cflogin.password#"
                     >
                     <cfcatch type="any">
                          <cfif FindNoCase("Invalid credentials", cfcatch.Detail)>
                              <cfset URL.message="Error: #cfcatch.Message#. Type: #cfcatch.Type#  Code: 000101 Username or Password invalid for user: #cflogin.name#">
                              <cfinclude template="loginform.cfm">
                              <cfabort>
                         <cfelse>
                              <cfset URL.message="Unknown error for user: #cflogin.name# #cfcatch.Message# Try logging in again">
                              <cfinclude template="loginform.cfm">
                              <cfabort>
                         </cfif>
                     </cfcatch>
               </cftry>
                                                 <!--- DEBUG FEEDBACK --->
                <cfoutput> User lookup successful... </cfoutput>
      <!---  If the LDAP query reutrned a record, the user is valid. --->
               <cfif auth.recordcount>
                                                <!--- DEBUG FEEDBACK --->
               <cfoutput>LDAP user search OK: #auth.recordcount#</cfoutput>
                   
                                <cfloginuser name="#cflogin.name#" password="#cflogin.password#" roles="#valueList(auth.cn)#">
                                                                <!--- DEBUG FEEDBACK --->                    
                                                               <cfoutput>
                    We are in the cfloginuser tag
                    <br>cflogin.name:  #cflogin.name#
                    <br>cflogin.password: #cflogin.password#
                    <br>cflogin.roles: #valueList(auth.cn)#
                   
                    </cfoutput>
                    <!--- save some session variables --->
                    <cfoutput> setting up session variables... </cfoutput>
                    <cflock name="sLogin_Lock" timeout="30" type="exclusive">
                         <cfset session.Email = #userSearch.mail#>
                         <cfset session.cn = #userSearch.cn#>
                         <cfset session.dn = #userSearch.dn#>
                         <cfset session.userID = #cflogin.name#>
                         <cfset session.LogInTime = Now()>
                         <cfset session.NumberOfGroups = auth.recordcount>
                         <cfset session.RoleList = #valueList(auth.cn)#>
                         <cfset session.FullName = #session.cn#>
                         <cfset session.authenticated = true>
                    </cflock>
                   
                    <!--- If save username box is checked, set cookie --->
                    <cfif IsDefined('form.SaveUsername')>
                      <cfcookie name="Username" value="#cflogin.Name#">
                    </cfif>        
               <cfelse>
                                                               <!--- DEBUG FEEDBACK --->
                    <cfoutput> LDAP UserSearch query failed...</cfoutput>
                    <cfset URL.message="Unknown error for user: #cflogin.name# Contact a member of Infotech to resolve the problem.">
                    <cfinclude template="loginform.cfm">
                    <cfabort>
               </cfif>
          </cfif>
     </cfif>
</cflogin>

0
Comment
Question by:maplesoft
  • 3
6 Comments
 
LVL 35

Accepted Solution

by:
mrichmon earned 500 total points
ID: 12313325
Here is an authentication best practice doc:

http://www.macromedia.com/devnet/mx/coldfusion/articles/ntdomain.html

Basically things to watch out for/general login best practices

1. alwyas check both username and password
2. do not tell the user why the login failed - display a generic message like "Username or password is incorrect"  By telling them only the password was worng then they know the login is valid and can keep attempting t o hack your system.  Valid users will know if the username had a mistake or not.
3. Always encrypt password information - it is best to hash and then only compare hashes so you never are storing user passwords
0
 

Author Comment

by:maplesoft
ID: 12571724
I have seen the ntdomain article before and maybe I will use an alternate method instead of cfldap.

I was looking for some feedback on the code I posted and for information on the optimum idle timeouts for the cflogin and session timeout for the cfapplciation.

I guess I was hoping for responses from a few more experts by awarding a lot of points.  

Can we give this a couple more weeks, or renew it?  

Thanks.
0
 
LVL 35

Expert Comment

by:mrichmon
ID: 12584845
We can leave it open a bit longer, but chances are no one else will respond since it is an older question.

And any responses you get would most likely be very similar.  Best practices don't change very often and when they do it is usually only slightly unless the technology significantly changes.
0
 
LVL 35

Expert Comment

by:mrichmon
ID: 12879232
I am recommending that this question now be closed as originally recommended since there have been no further comments.
0

Featured Post

Create the perfect environment for any meeting

You might have a modern environment with all sorts of high-tech equipment, but what makes it worthwhile is how you seamlessly bring together the presentation with audio, video and lighting. The ATEN Control System provides integrated control and system automation.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

A web service (http://en.wikipedia.org/wiki/Web_service) is a software related technology that facilitates machine-to-machine interaction over a network. This article helps beginners in creating and consuming a web service using the ColdFusion Ma…
If you don't have the right permissions set for your WordPress location in IIS, you won't be able to perform automatic updates. Here's how to fix the problem.
Although Jacob Bernoulli (1654-1705) has been credited as the creator of "Binomial Distribution Table", Gottfried Leibniz (1646-1716) did his dissertation on the subject in 1666; Leibniz you may recall is the co-inventor of "Calculus" and beat Isaac…
A short tutorial showing how to set up an email signature in Outlook on the Web (previously known as OWA). For free email signatures designs, visit https://www.mail-signatures.com/articles/signature-templates/?sts=6651 If you want to manage em…

821 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question