LDAP Authentication for CF_WHeels Where to Start?

85 views
Skip to first unread message

siri...@gmail.com

unread,
Jun 3, 2021, 10:55:17 AM6/3/21
to CFWheels
I'm not 100% sure how authentication works in wheels in general but need to implement ldap authentication. I have that all set up in a coldfusion site. Is it as easy as moving my application.cfc code over to a different cfc in wheels or is there more to it?

Tom King

unread,
Jun 3, 2021, 11:11:39 AM6/3/21
to CFWheels

siri...@gmail.com

unread,
Jun 3, 2021, 11:14:38 AM6/3/21
to CFWheels
Thanks I did have a look through that. I tried to pull the pieces out and move them over. When I hit the login route I am getting the error: The required parameter [auth] was not provided. Not sure where that is happening or not happening at this point. Was looking for a stripped down guide or something if there was one that explained it.

Tom King

unread,
Jun 3, 2021, 11:22:39 AM6/3/21
to CFWheels
That particular app uses a tableless model for auth;
So in https://github.com/cfwheels/cfwheels-example-app/blob/master/views/sessions/new.cfm it's expecting an instance of the auth model to exist 
Which, if your application setting is set to LDAP, will attempt to load /models/auth/LDAP.cfc
Then the rest of the controller will try and use the authenticate() method in that model which is where you might put your external LDAP call.

It's really just one way of doing it; essentially all you need to do is the LDAP call using the params provided by your login form, and check the contents on return, then if all ok, permit access.
T

siri...@gmail.com

unread,
Jun 3, 2021, 11:50:27 AM6/3/21
to CFWheels
Thanks for the explanation. It seems pretty straight forward. When you say as the application is set to LDAP it will load the model, where is that set exactly?

Tom King

unread,
Jun 3, 2021, 11:53:43 AM6/3/21
to cfwh...@googlegroups.com
That's specific to the example app, it uses database settings, once of which is authentication_gateway


--
You received this message because you are subscribed to the Google Groups "CFWheels" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cfwheels+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/cfwheels/494b531b-91f6-47a6-a150-f681b89b0eaan%40googlegroups.com.


--


Tom King

Web Development Consultant

+44(0)7775 926480 | oxalto.co.uk | @neokoenig | linkedIn

siri...@gmail.com

unread,
Jun 3, 2021, 3:36:01 PM6/3/21
to CFWheels
Thanks for th info. I ended up getting the example app up and running. Configured LDAP. When I dump the qLDAPLookup call I do see my LDAP info coming back. So I know up until that point it is working. Once I take the abort out I get an error The function [authenticate] has an invalid return value , [Cannot cast null value to value of type [boolean]]. I tried adding return true inside the if (qLDAPLookup.recordCount) { section but nothing so far has worked. Is it looking for something else?

Tom King

unread,
Jun 3, 2021, 3:52:36 PM6/3/21
to CFWheels
Sorry, there's a return missing there:
The function authenticate() need to `return` something, so 

if (qLDAPLookup.recordCount) {
return userAuthenticated = true;

Tom King

unread,
Jun 3, 2021, 3:54:02 PM6/3/21
to CFWheels
Sorry, I mean just 

return qLDAPLookup.recordCount

siri...@gmail.com

unread,
Jun 3, 2021, 4:08:41 PM6/3/21
to CFWheels
Still getting the same error with this:

*/
function doLDAPCall(){

        cfldap( 
        server details ...
  
        );

return qLDAPLookup.recordCount;
}


Tom King

unread,
Jun 3, 2021, 4:30:31 PM6/3/21
to CFWheels
Right, yeah - sorry, that whole CFC was just a "proof of concept"  type thing, so not properly fleshed out.

The principle is, the result of the  authenticate() function should return a boolean; now , what you "do" in that function is up to you - it could a LDAP look up, it could be... just saying the user's IP is "x"; 
Ultimately, if the LPAP lookup is successful, make authenticate() return true. I pushed it out into a secondary function whilst I was writing it, not because it needed it, but in my head  you might want additional logic around it.

T

siri...@gmail.com

unread,
Jun 3, 2021, 4:44:04 PM6/3/21
to CFWheels
Gotcha. Thanks! I think I am almost there. After moving it into the authenticate function I am getting the error: key [USER] doesn't exist. I'm not sure how the tableless login is supposed to work. How should I set the user based on the LDAP info?

Tom King

unread,
Jun 3, 2021, 4:55:00 PM6/3/21
to CFWheels
The premise of the App was that you'd create a local user account which     would correspond to the LDAP user account;
i.,e LDAP would provide the "authentication" - that the user would be allowed to access the app, but in terms of managing the local account (i.e in the user table) it would be up to you.
Now, depending how you want the app to work, it might be you want to directly assign the result of the LDAP object -> User object, but it massively depends on what data you neeed/want, where, and how, and where you want to store it.
Should LDAP be the "source of truth"? or, is just auth'ing via LDAP enough, and that the data can persist locally in your user table?
etc.
T

siri...@gmail.com

unread,
Jun 3, 2021, 5:06:37 PM6/3/21
to CFWheels
So yeah that was how I was looking for it to work. The LDAP would just authenticate and the user would be in the DB from that point on. 

siri...@gmail.com

unread,
Jun 3, 2021, 6:48:19 PM6/3/21
to CFWheels
Ok! I got working. I went the other direction and used local login but added the LDAP call to the authentication function. One small issue. If I put in the wrong password, or wrong user it is throwing a 500 error with ldap 49 error. I am trying to catch any errors and write a flash message to the login page. It just keeps erroring out with the LDAP 49 code though. Any thoughts on what I am doing wrong?

boolean function authenticate(){
try {
cfldap( 
        server details ......
        );

}

catch ( any e ){
this.addErrorToBase(message="Sorry, there is an issue with the username or password");
}

if (qLDAPLookup.recordCount) {

local.user=model("user").findOne(where="email = '#this.email#'");
if(!isObject(local.user)){
this.addError(property="email", message="Sorry, we couldn't log you in");
return false;
}  else
{
return true;
postLogin(local.user);
}

}

Tom King

unread,
Jun 4, 2021, 4:37:38 AM6/4/21
to CFWheels
Afraid I've never actually used LDAP, so unable to help; A quick google suggests that you might be better off doing 2 LDAP calls, one to establish if the user exists, and one to do the actual authentication;
cut n paste from stack overflow:

<!--- make the LDAP query ---> 
<cfldap action="QUERY" server="my.server.com" port="636" username="cn=YOURSYSTEMIDGOESHERE,ou=systemids,dc=my,dc=server,dc=com" password="YOURPASSWORDGOESHERE" name="getldap" start="CN=Users,DC=my,DC=server,DC=com" attributes="dn" scope="subtree" filter="(&(objectclass=user)(sAMAccountName=#form.uid#))" secure="CFSSL_BASIC" maxrows="10"> 

<CFIF getldap.RecordCount GT 1> 
  <!--- Too many accounts exist in LDP, throw message to call the help desk ---> 
  <CFELSEIF getldap.RecordCount EQ 0> 
  <!--- User does not exist in directory, fail auth ---> 
  <CFELSE> 
<!--- Attempt Authentication using supplied credentials ---> 
  <cfldap action="QUERY" server="my.server.com" port="636" username="#getldap.dn#" password="#form.password#" name="attemptauth" secure="CFSSL_BASIC" start="CN=Users,DC=my,DC=server,DC=com" attributes="dn" > 
  <!--- Do something here to catch errors, on return code 0, auth is successful ---> 
  <!--- Error code 19, hex 0x13) is a locked out account and fail auth ---> 
  <!--- Error code 49, hex 0x31) is an invalid password error and fail auth --->
<!--- Other errors are system-type problems, throw try again / call help desk type error ---> 
  </CFIF>


Reply all
Reply to author
Forward
0 new messages