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">
<!--- 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#))">
|
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 cfloginuserroles attribute.
Ends
the initial isDefined("cflogin")cfif block
.
Ends the cflogin tag body
|