I’m adding Windows Authentication to an existing app. There’s a complete test environment with AD setup on a Windows 2019 Server and a separate IIS 10 server connected to the windows domain. Windows Authentication is turned on in IIS.
I access the website (using Edge) and the browser correctly prompts the user to log on. I enter a valid (domain) username and password, which the browser accepts.
The only way I know of to get the username, which was entered into the browser prompt, is to use CFLOGIN. In Application.cfc, onRequestStart was modified. CFLOGIN is supposed to be defined at this point and CFLOGIN.Name should contain the username.
However, I'm getting an error that CFLOGIN is not defined.
What am I doing wrong? Has anyone gotten CFLOGIN to work using Windows Authentication on Windows 20019?
I couple of things I've tried are: i) Make CF run under a domain account and ii) Changing security on the web root so that all domain users have read access.
Have you tried doing a cfdump (tag or script) of the CGI scope? You may find what you seek there. Same with dumping the results of the CF function, gethttprequestdata().
Let us now if either present you what you seek. Those would be simpler than the alternatives you are proposing. (I can't recall, for sure, what is needed to get it to work as you want. It doesn't come up often enough for me to readily know. Perhaps someone else may.)
If it wasn't clear, I'm proposing my suggestions as ALTERNATIVES to using CFLOGIN, given that you'd said it was "the only way I know of" to get that username.
I think there are a couple of things going on here. First, have you tried setting usebasicauth="false" in your cflogin tag? Windows Authentication is either Kerberos or NTLM, so you can't use Basic. Second, what else is going on in that cflogin tag? You should be able to use cflogin.name but not cflogin.password, since the name comes from the web server and the password is typically not available for you to see.
Dave Watts, Eidolon LLC
The error is telling you that cflogin is not yet triggered. The cflogin documentation gives 3 conditions for triggering the existence of the cflogin structure, namely:
- Submission of a form that contains input fields with the names j_username and j_password.
- A request that uses HTTP Basic authentication and, therefore, includes an Authorization header with the user name and password.
- A request that uses NTLM or Digest authentication. In this case, the username and password are hashed using a one-way algorithm in the Authorization header; ColdFusion gets the username from the web server and sets the cflogin.password value to the empty string.
You can use these values in the cflogin tag body to authenticate the user, and, in the cfloginuser tag, to log the user in. The structure is only available in the cflogin tag body.
The error suggests that none of them is in effect. Windows authentication used to be done by means of cfauthenticate. But that has been deprecated.
In any case, you could just make sure the variables form.j_username and form.j_password exist when onRequestStart runs. You code would of course assign to these variables the values of the validated username and password. That is the simplest way I can think of to trigger the existence of cflogin.
<cfparam name="form.j_username" default="testUserName"> <cfparam name="form.j_password" default="testPassword"> <cflogin> <cfoutput> cflogin.name:#cflogin.name#<br> cflogin.password:#cflogin.password# </cfoutput> <cfdump var="#cflogin#" label="Cflogin"> </cflogin>
Thanks for the help.
I ended up using CGI.auth_user. If it exists, the application assumes windows authentication. Otherewise it falls back to form based authentication.
I like this because we don't need to use CFLOGIN.
Although I'm not quite sure how to manage the expiration of the session (and associated variables) with windows authentication.
That's fine. You don't need to use CFLOGIN, it's just a convenience. Windows authentication comes from the web server and won't expire, but the session probably will depending on how cookies and the Session scope have been configured. So, you should have something to deal with that once the Session stuff is no longer present. For example, if those values are gone, you'll need to repopulate them, but you won't have the user's password. So, you could store CGI.AUTH_USER as a separate variable in the Session scope, then use it to look up the user's data again when the Session data has been dumped so you can repopulate that user's session.
Dave Watts, Eidolon LLC
To be clear, Mike, that's what I was getting in the first reply above back on Nov 14. Glad it worked out.