Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.
I am the chief technical officer at InVision App, Inc - a prototyping and collaboration platform for designers, built by designers. I also rock out in JavaScript and ColdFusion 24x7.
Meanwhile on Twitter
Loading latest tweet...
Ben Nadel at the New York ColdFusion User Group (Jul. 2009) with: Sean Schroeder

Note About CFLogin, Application Name, And ApplicationToken

By Ben Nadel on
Tags: ColdFusion

I am not a huge fan of ColdFusion's built-in authentication framework; to be fair, I have never really given it a chance, so I'm not here to say if it's good or not. But, the other day, I was helping someone debug a CFLogin problem, so I figured I'd post it here as well. Below, I've set up a tiny example of what was happening.

Here is the Application.cfc:

  • <cfcomponent
  • output="false"
  • hint="I define application settings and event handlers.">
  •  
  • <cfset THIS.Name = "My Test App" />
  • <cfset THIS.ApplicationTimeout = CreateTimeSpan( 0, 0, 1, 0 ) />
  •  
  • </cfcomponent>

And here is the index.cfm page which makes use of ColdFusion's CFLogin tag:

  • <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  • <html>
  • <head>
  • <title>CFLogin Test</title>
  • </head>
  • <body>
  •  
  • <h1>
  • CFLogin Test
  • </h1>
  •  
  • <p>
  • Hello user!
  •  
  • <!--- Only display if user is not logged in. --->
  • <cflogin>
  •  
  • <a href="login.cfm">Please Log In</a>.
  •  
  • </cflogin>
  • </p>
  •  
  • </body>
  • </html>

Nothing much going on here; but, when we run the page, we get the following ColdFusion error:

The string COOKIE.CFAUTHORIZATION_My Test App is not a valid ColdFusion variable name.

If the problem is not immediately obvious, it's that ColdFusion uses the application name (THIS.Name in Application.cfc) to define the authorization cookie name (the default approach as stated by the ColdFusion documentation). The reason that we are getting the error is that our application name, "My Test App," has spaces in it and valid variable names can only contain letters, numbers, underscores, and dollar signs.

To get around this, we can change the name of our application to not have spaces or any other invalid characters. But that seems a little bit extreme, right? That's be like changing the shape of my foot to fit a particular shoe. Rather than bending the application to fit into CFLogin's default constraints, let's use the CFLogin tag in a way that fits into our application.

To do this, we are going to have to tell the CFLogin tag which application key to use such that it doesn't use our application name. That is what the ApplicationToken attribute is for. The ApplicationToken allows us to provide the CFLogin tag with a dynamic value that will override the application name. Make the changes are fairly straightforward:

  • <cfcomponent
  • output="false"
  • hint="I define application settings and event handlers.">
  •  
  • <cfset THIS.Name = "My Test App" />
  • <cfset THIS.ApplicationTimeout = CreateTimeSpan( 0, 0, 1, 0 ) />
  •  
  •  
  • <cffunction
  • name="OnRequestStart"
  • access="public"
  • returntype="boolean"
  • output="false"
  • hint="I fire before a template is executed.">
  •  
  • <!--- Store application key for CFLogin. --->
  • <cfset APPLICATION.LoginKey = "MyTestAppLogin" />
  •  
  • <!--- Return out. --->
  • <cfreturn true />
  • </cffunction>
  •  
  • </cfcomponent>

NOTE: I would usually initialize the APPLICATION scope in the OnApplicationStart() event method, but for ease of demo, I did it in the OnRequestStart() event method.

.... and the index.cfm page:

  • <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  • <html>
  • <head>
  • <title>CFLogin Test</title>
  • </head>
  • <body>
  •  
  • <h1>
  • CFLogin Test
  • </h1>
  •  
  • <p>
  • Hello user!
  •  
  • <cflogin applicationtoken="#APPLICATION.LoginKey#">
  •  
  • <a href="login.cfm">Please Log In</a>.
  •  
  • </cflogin>
  • </p>
  •  
  • </body>
  • </html>

Now, we are defining our CFLogin ApplicationToken in the APPLICATION scope and then using it in our CFLogin tags. This time, when the page runs, we get the rendered output, and when we check our cookies, we can see that ColdFusion has created the following cookie based on our ApplicationToken:

CFAUTHORIZATION_MyTestAppLogin

I'm not sure if this is a no brainer to those of you that generally use ColdFusion's CFLogin tag; but, since I had to help someone debug this problem, I figured it would be worth posting.




Reader Comments

Few comments here.

The applicationToken isn't just to override the default value. I believe the real use (or the intended use) was to allow you to share Authentication/Authorization info among multiple applications. So you can login once and work within multiple different apps (on the same server).

I'm going to ding you for using onRequestStart to set an Application variable. That really needs to be onApplicationStart. OOps, just saw your note. I don't see how using onRequestStart makes it easy. I guess I'm just worried people will see the code and NOT the note. I'd change it. ;)

Reply to this Comment

@Ray,

I believe you are correct regarding the cross-application login. When I was looking up the documentation, I think they made mention of this.

Yeah, I know I know :) The only reason I went with OnRequestStart() is because I ran the application once to get error and I didn't want to have to wait the whole minute for the application to timeout before it would even fire the OnApplicationStart() event handler :) I guess that's the epitome of laziness.

Ironically, it probably took me a minute just to write the OnRequestStart() event handler.

Reply to this Comment

That's why my typical onRequestStart will have a URL hook to rerun onApplicationStart. A minute -is- a long time when testing. ;)

Reply to this Comment

Word up! It is a long time when testing. That's a good idea - the direct call to OnApplicationStart(). Ok, I'll keep it cleaner next time.

Reply to this Comment

As long as that URL hook has appropriate security around it -- even if you are just checking the remote IP. Otherwise, it's a gaping security hole just asking for someone to DoS your site. (And to see what they can get away with by restarting your site and immediately performing secure stuff while the site is reloading.)

Reply to this Comment

Meh, security is overrated. ;) I'd take the simple ModelGlue approach. You can configure both a url key and a url value to allow for reload. Out of the box it is init=true, but you can change that to toosexy=forthisblog. That's probably more than enough.

Reply to this Comment

Ben - posts like these really make my day!

They open my eyes to little things that I never would have thought about on my own!

applicationToken - Fantastic!!! :)

Reply to this Comment

@Paolo,

Always glad to shed some light. Of course, I am not well versed in the CFLogin stuff. I believe Ray Camden has a good number of posts on the topic.

Reply to this Comment

I have quite a few posts on cflogin. Unfortunately most are not good ones. CFLOGIN has many warts. It has improved greatly in CF8, but in general, I'd probably not recommend using it.

Reply to this Comment

I would like to recommend everyone to use a valid variable name as application name. Use application.prettyName for the pretty name. Maybe all my "not a valid variable name" errors over the years can be traced to the transition from Application.cfm to .cfc (I often used name="myAppname_#version#" in the cfapplication tag and the dots in version made it illegal), but I am not 100% sure.

Unless one have a very good reason for using spaces or strange characters in the application name, I think it is best avoided.

Reply to this Comment

Thanks very much Ben. I have used yours and many other blogs to figure out problems over the years, but have never really bothered to leave comments. I figure I should get off my butt and start contributing more.

My first attempt at contribution then will be to thank you and everyone else whose comments and hard work have saved me countless hours. It is certainly appreciated.

Reply to this Comment

@Jim,

I'm happy that stuff you find here has been good; and, I'll take it as a compliment that it has even led to commenting :) Awesom!

Reply to this Comment

Hello and thank you Ben,
I know this is an old post but I had a problem with implementing the above method. my cflogout doesn't work when I use applicationtoken in cflogin. I end up using StructClear instead. Any suggestions?

Reply to this Comment

Post A Comment

?
You — Get Out Of My Dreams, Get Into My Comments
Live in the Now
Oops!
Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.