Adobe ColdFusion 8

Using an LDAP directory for security information

LDAP directories are often used to store security information. The following example of a cflogin tag checks an LDAP directory to authenticate the user and retrieve the user's roles.

For more information on using LDAP directories with ColdFusion, see Managing LDAP Directories.

<cfapplication name="Orders" sessionmanagement="Yes" loginstorage="Session">
<cflogin>
    <cfif isDefined("cflogin")>
        <!--- setting basic attributes --->
        <cfset LDAP_root = "o=mycompany.com">
        <cfset LDAP_server = "ldap.mycompany.com">
        <cfset LDAP_port = "389">
        
        <!--- Create the prefix and suffix parts of the user's DN. --->
        <cfset userPrefix = "cn=">
        <cfset userSuffix = ",ou=Users,o=mycompany.com">
        
        <!--- Concatenate the user's DN and use it to authenticate. --->
        <cfset LDAP_username = userPrefix&cflogin.name&userSuffix>

        <!--- This filter will look for groups for containing the user's ID. --->
        <cfset userfilter =
            "(&(objectClass=groupOfUniqueNames)(uniqueMember=#LDAP_username#))">

        <!--- Search for groups containing the user's dn. 
            The groups represent the user's roles.
            NOTE: Your LDAP permissions must allow authenticated users to search.
            groups. --->
        <cftry>
            <cfldap action="QUERY"
                name="auth"
                attributes="cn"
                referral="yes"
                start="#LDAP_root#"
                scope="SUBTREE"
                server="#LDAP_server#"
                port="#LDAP_port#"
                filter="#userfilter#"
                username="#LDAP_username#"
                password="#cflogin.password#"
            > 
             <cfcatch type="any">
                <cfif FindNoCase("Invalid credentials", cfcatch.detail)>
                    <cfoutput>
                        <script>alert("User ID or Password invalid for user:
                            #cflogin.name#")</script>
                    </cfoutput>
                    <cfabort>
                <cfelse>
                    <cfoutput>
                        <script>alert("Unknown error for user: #cflogin.name#
                            #cfcatch.detail#")</script>
                    </cfoutput>
                    <cfabort>
                </cfif>
            </cfcatch>
        </cftry>
    
<!--- If the LDAP query returned a record, the user is valid. --->
        <cfif auth.recordcount>
            <cfloginuser name="#cflogin.name#" password="#cflogin.password#"
                roles="#valueList(auth.cn)#">
        </cfif>
    </cfif>
</cflogin>

Reviewing the code

The following table describes the code and its function. Comments and some tab characters have been removed for brevity.

Code

Description

<cflogin> <cfif isDefined("cflogin")> <!--- setting basic attributes ---> <cfset LDAP_root = "o=mycompany.com"> <cfset LDAP_server = "ldap.mycompany.com"> <cfset LDAP_port = "389"> <cfset userPrefix = "cn="> <cfset userSuffix = ",ou=Users,o=mycompany.com"> <cfset LDAP_username = userPrefix&cflogin.name&userSuffix> <cfset userfilter = "(&(objectClass=groupOfUniqueNames) (uniqueMember=#LDAP_username#))">

Starts the cflogin tag body. Sets several variables to the values used as attributes in the cfldap tag.

 

 

 

Sets prefix and suffix values used to create a distinquished name (dn) for binding to the LDAP server.

 

Creates the user's bind dn by concatenating the prefix and suffix with cflogin.name. This variable is used for authenticating the user to the LDAP server.

Sets the filter used to search the directory and retrieve the user's group memberships. The group membership represents the user's roles within the organization.

<cftry> <cfldap action="QUERY" name="auth" attributes="cn" referral="yes" start="#LDAP_root#" scope="SUBTREE" server="#LDAP_server#" port="#LDAP_port#" filter="#userfilter#" username="#LDAP_username#" password="#cflogin.password#" >

In a cftry block, uses the user's concatenated dn to authenticate to the LDAP server and retrieve the common name (cn) attribute for groups to which the user is a member. If the authentication fails the LDAP server returns an error.

 

Note: The LDAP permissions must allow an authenticated user to read and search groups in order for the query to return results.

<cfcatch type="any"> <cfif FindNoCase("Invalid credentials", cfcatch.detail)> <cfoutput> <script>alert("User ID or Password invalid for user: #cflogin.name#")</script> </cfoutput> <cfabort> <cfelse> <cfoutput> <script>alert("Unknown error for user: #cflogin.name# #cfcatch.detail#")</script> </cfoutput> <cfabort> </cfif> </cfcatch> </cftry>

Catches any exceptions.

Tests to see if the error information includes the string "invalid credentials", which indicates that either the dn or password is invalid. If so, displays a dialog box with an error message indicating the problem.

 

 

Otherwise, displays a general error message.

 

 

 

If an error is caught, the cfabort tag ends processing of the request after displaying the error description.

End of cfcatch and cftry blocks.

<cfif auth.recordcount> <cfloginuser name="#cflogin.name#" password="#cflogin.password#" roles="#valueList(auth.cn)#"> </cfif> </cfif> </cflogin>

If the authorization query returns a valid record, logs in the user. Uses the valueList function to create a comma-separated list of the users retrieved group memberships, and passes them in the cfloginuser roles attribute.

Ends the initial isDefined("cflogin") cfif block .

Ends the cflogin tag body