ColdFusion Muse

Maintaining Your Session Across Sub Domains

Mark Kruger July 28, 2006 7:33 PM Coldfusion Tips and Techniques Comments (25)

One of the clever things you can do to personalize your site is to give individuals or clients or affiliates (or your dog) a custom URL. For example, if I wanted to give my dog his own url on my "coldfusionmuse.com" domain I could create "Nicholos.coldfusionmuse.com". Now, unless you want to spend most of your time entering CNAME or A records into your DNS server I suggest the following:

  • Add a wildcard "A" record DNS entry for any unspecified sub domain to point to your main IP address.
  • Make sure your web server for that domain is not set up for host headers only. In other words, it should be set up to handle "any" http traffic to the IP address.
  • Use Coldfusion to tease out the beginning part of the domain (in my case "Nicholas") and use it to personalize or otherwise redirect the user.
Uh oh... there's a problem. If I switch between sub domains I can't seem to see my session. In fact, CF seems to set up a new session. Why?

You may already know that your session is tied to a cookie. While it's possible to use URL parameters it's pretty much a given that session aware sites use cookies. In the case of a Coldfusion server it uses either a "CFID" and "CFTOKEN" cookie or a "JSESSIONID" cookie. When a cookie is set it is specific to the domain. There is a domain string that specifies the domain to which a cookie belongs. For example, a cookie set for "www.coldfusionmuse.com" is different from a cookie set for "coldfusionmuse.com". Wait a minute! You can enable a cookie to be seen by sub domains using the CFCOOKIE tag - right? Like so:

<cfcookie    name="myDog"
         value="Nicky"
            domain=".coldfusionmuse.com"/>
A cookie set this way can be "seen" by "coldfusionmuse.com", "www.coldfusionmuse.com" and "Nicholous.coldfusionmuse.com". That's good news. The domain attribute should allow us to create a session that can be shared between sub domains - right? Well... not easily. Remember that CFTOKEN and CFID (and JSESSIONID) are set automatically as a part of the application. Unfortunately there is no attribute of the cfapplication tag that is analogous to the "domain" attribute of cfcookie. That means that even though the application names are the same and share the same application variables (that happens on the server - not the client) the client itself will look brand new when it moves between sub domains. Is there a way around this? Can we "make" the sessions visible across sub-domains? Fortunately we can.

The Fix

While we cannot alter the automatic process that sets the CFID and CFTOKEN variables - we can manipulate these cookies to make them visible across sub domains. Here are the steps:

  • Make sure that session management is ON but turn OFF the "setClientCookies" option in the cfapplication tag.
    <cfapplication name="mydog" setclientcookies="No".../>
    Why? because we don't want the process to interfere with our manipulation of said cookies.
  • Set the CFID and CFTOKEN variables manually using code like this:
    <cfcookie name="cfid"
             domain=".coldfusionmuse.com"
             value="#session.cfid#">

             
          <cfcookie    name="cftoken"
             domain=".coldfusionmuse.com"
             value="#session.cftoken#">

             
          <cfcookie name="jsessionid"
             domain=".coldfusionmuse.com"
             value="#session.sessionid#">
    In effect this makes the CFID visible to other domains.

Under the Covers

How does it work? Well... when I first go to "www.coldfusionmuse.com" the server checks to see if I have a session. It does this by looking for the CFID and CFTOKEN (or JSESSIONID) in the url, form and cookie scopes. Finding none, it creates a CFID and CFTOKEN for me in the session scope. With clientcookies turned off, the application, in effect, says, "Ok, the rest is up to you fancy pants developers out there. Manage the session yourself if you like". Without cookie code or url parameters the site would actually treat each new request as a brand new session. That's the effect of both not allowing cookies and allowing session management.

When you copy the session keys into the cookie scope and make them visible to sub domains you cut into this process at the initial step - when the server is searching the scopes for a session. It sees your keys and says "aha! this is what I'm looking for." Then it uses them to check memory for that particular application to see if there is a match and Viola! ... your session is restored. It's a hack - but it's kind of nifty in a way.

  • Share:

25 Comments

  • Ben Nadel's Gravatar
    Posted By
    Ben Nadel | 9/8/06 7:58 AM
    That is very cool. Is the JSESSIONID required for standard session usage not spanning multiple servers? Or are you just putting it in there to cover all the bases?
  • Imre's Gravatar
    Posted By
    Imre | 10/19/06 6:53 AM
    or you can just set the SETDOMAINCOOKIES attribute in the CFAPPLICATION tag to "Yes"
  • david marc's Gravatar
    Posted By
    david marc | 10/30/06 7:55 PM
    Where do you put the cfcookie tags? I tried putting them in my applicaion.cfm, i kept getting cfid is undefined in session.
  • davidmarc's Gravatar
    Posted By
    davidmarc | 10/31/06 7:18 AM
    Hey,
    I solved my issue, you may want to state that if your using j2ee sessions that you dont have to set cfid, cftoken with cfcookie, it will say undefined.

    So basically do everything above except if you are using j2ee sessions leave out cfid & cftoken for the cfookie part.

    Works great your the champ for bringing this up man !

    -dave
  • mkruger's Gravatar
    Posted By
    mkruger | 10/31/06 7:19 AM
    They will have to come AFTER a call to cfapplication (if you are using application.cfm) and you must have sessionmanagement enabled.
  • david marc's Gravatar
    Posted By
    david marc | 10/31/06 9:06 PM
    I also noticed that this fix ends up creating 2 identical jsessionid cookie values. When i looked at the cookies, it will create a cookie for the host in which you originially access the page from, and then the wildcard .site.com domain. Am i doign somthign wrong or is this just a part of the fix. The values are identical.
  • Tomek's Gravatar
    Posted By
    Tomek | 3/8/07 7:38 AM
    I observer the same like David Marc. The jsessionid with Host is producing by the cf-server automaticaly. So even when you don't set the cookie like explained in this article, and set SetClientCookies to No, this cookie will be set.

    Bad, because this is still not working, if you change the subdomain names during the session.
  • Brian's Gravatar
    Posted By
    Brian | 5/6/08 4:50 PM
    Can you do something similar across different domains?
  • Lyle's Gravatar
    Posted By
    Lyle | 7/2/08 8:55 AM
    I'm also curious if it is possible to share this information across different domains.

    I have a library website that has specific collections at different domains (all hosted on the same server and using the same application name). I'd like it so that if a user logs in at one domain, and when to a different collection, their login could pass with them.

    Is there anything preventing me from passing the cfid/cftoken/jsessionid in the url (and a one use token for security) that would transfer the login without the need for domain based cookie access?

    Does that make sense?
  • Durai's Gravatar
    Posted By
    Durai | 7/11/08 4:56 AM
    Hi,

    how we transfer the Cookie value from Main Domain to sub Domain?
  • Aaron S.'s Gravatar
    Posted By
    Aaron S. | 10/28/09 7:10 PM
    I've tried everything listed in this blog entry with no luck. I am using CF8 and no matter what I do, I still get different CFID and CFTOKEN variables on sub-domains. I've turned on the SetDomainCookies application option but to no avail. Any help with this would be greatly appreciated.
  • Sergey S's Gravatar
    Posted By
    Sergey S | 1/8/12 4:44 AM
    Or we can simply pass encrypted password and login with cookies or url. On new subdomain in application.cfm check if cookies exist and if it is, just decrypt the data with preset key
  • chris hough's Gravatar
    Posted By
    chris hough | 2/28/12 11:57 AM
    thank you so much for posting this, it ended up helping me fix my cookie problem across 2 applications using sub domains
  • Paolo Groppo's Gravatar
    Posted By
    Paolo Groppo | 9/5/14 5:27 AM
    I'M using Coldfusion 11 and I need to mantain session across subdomains. I've always used <cfset THIS.setDomainCookies = true> in my application.cfc.
    It works in subdomains like "http://www.example.com"; or "http://something.example.com";.
    It does NOT WORK in sites like "http://example.com"; (without hostname). In this case CFID and CFTOKEN cookies are not set as domain cookies. Someone can help me?
  • Paolo Groppo's Gravatar
    Posted By
    Paolo Groppo | 10/9/14 4:24 PM
    The bug has been submitted to bugbase and verified. I hope it will be fixed ASAP
    https://bugbase.adobe.com/index.cfm?event=bug&...
  • Phillip Senn's Gravatar
    Posted By
    Phillip Senn | 1/5/15 12:31 PM
    I found that myDomain.com and www.myDomain.com uses two separate sessions.
    this.setDomainCookies = 'yes'; doesn't seem to have any effect.

    http://stackoverflow.com/questions/27748146/one-do...
  • Charlie Arehart's Gravatar
    Posted By
    Charlie Arehart | 4/14/15 7:14 PM
    This is said to be fixed finally in update 5 of CF11. See the "bugs fixed" document linked to from https://helpx.adobe.com/coldfusion/kb/coldfusion-1..., which has a link to the bug report above and indicates it's resolved. (There's no mention of it in the CF10 bugs fixed though. That would be a shame if it was happening in 10 but not fixed in it.)
  • Don Coxe's Gravatar
    Posted By
    Don Coxe | 12/10/15 9:41 AM
    Try as I might, I simply can't get jsessionid to persist across subdomains. Even when SetDomainCookies is true, a second subdomain-specific jsessionid cookie is created and appears to be the ruling instance, because when I switch to the other subdomain, I'm not logged in and another subdomain-specific jsessionid cookie is created. I just can't make it work with J2EE session variables turn on. Any ideas?
  • Charlie Arehart's Gravatar
    Posted By
    Charlie Arehart | 12/14/15 4:05 PM
    Don, are you manipulating the jsessionid cookie at all in your code? I've seen people have problems when they do, when either app- or admin-level settings can affect characteristics of how the cookies are created. And if you are, are you doing it with cfcookie, or perhaps just cfset or a cfscript means? The former has more control of aspects of the cookie creation, which can override the app- or admin-level settings.

    Also, the default values for various cfcookie attributes have changed in recent releases of CF, depending on some other security settings (at install or done via Admin tweaks).

    Indeed, you don't say if you're on CF11, 10, or earlier (if indeed CF at all, or perhaps Railo or Lucee). All that may help others help you.

    Finally, you refer to observing the cookies created. Can you clarify if you're judging that by looking at the cookies as variables within CFML? Or are you looking at the cgi.http_cookies?

    Or (better) might you be watching the network communications between your browser and server, using any of many available browser dev tools? With those you can also see the cookies that ARE set on your machine, which can be helpful sometimes (in case two may exist but only one is being sent by the browser to the server).

    And have you tried things in an "incognito window" or "private window", where the browser will NOT send along any previously-existing cookies? Sometimes you may find different results that way, which could be diagnostically useful.

    There are sadly a number of things that could explain what you're seeing, and until you get to the bottom of what is being sent back and forth, you may be chasing your tail.

    Let us know what you can find (and the details of your CFML server: version, updates applied, etc.) and perhaps we can share more thoughts. Hope that's helpful.

    PS One more challenge often is that people who ARE on CF10 or 11 may have applied the "latest update", but then they may miss/forget/not realize the need to update their web server connector. Most updates require that. Can you confirm the date of your isapi_redirect.dll or mod_jk.so, found in the numbered folder(s) under cf's config\wsconfig in CF10 and 11?
  • Don Coxe's Gravatar
    Posted By
    Don Coxe | 12/14/15 4:56 PM
    Charlie -

    Thank you for your comprehensive reply. To take it from the top:

    I have tried manipulating the jsessionid cookies, both from <cfcookie> with domain specified (".xxxx.yyy") and from javascript itself. I've succeeded in creating a domain-only version of the cookie, but only alongside a subdomain-specific one, and that doesn't work, as it appears the subdomain-specific cookie always rules.

    I've tried this on CF10 update 18 with isapi_redirect dated 9/10/2015 and on CF11 update 7 with isapi_redirect dated 12/24/2014.

    I am inspecting cookies with Chrome Developer and Firefox Developer. Doing it any other way would be blind! I have cleared the cookies from the browsers many, many times. There's no risk of old cookies hanging around.

    I have not tried incognito or private browsing.

    When SetClientCookies = true, then the CFID and CFTOKEN cookies appear and are properly assigned without subdomain. Not so for jesessionid.

    This problem I've reported is very simple to test, but I've not heard anyone say that it is working for them. Do you know for a fact that this does and should work and is not a bug?

    Again, I appreciate your interest and assistance.

    - Don
  • Charlie Arehart's Gravatar
    Posted By
    Charlie Arehart | 12/14/15 5:20 PM
    Don, to be clear, if you're on CF11 Update 7 and have updated your connector, it should be dated 9/10/2015. Are you sure it's a 2014 date? If so, it's out of date. But I won't propose that's THE problem, if you're saying it happens with CF10 u18 (And I'm not sure the date of the latest, but you show it as the same 9/10/15 that I do for my CF11 u7 version.)

    As for your confirming that you are watching the cookies with those tools, great to hear. Yep, I agree working otherwise would be like "working blind", but I see people trying it all the time, so had to ask! :-)

    As for your having cleared cookies, well, beware: some tools and features will clear only persistent cookies and NOT those in memory only (or vice-versa). Since CF creates the jsessionid by default to be memory-only, it's an important distinction.

    And I can't stress how valuable it may be for you to try the incognito window feature (in Chrome) or private window (in FF). You may find something happens differently for you, which would be diagnostically significant.

    And no, I have not specifically tested for this recently. I'd really appreciate hearing first if any of the above helps before trying to recreate it. Typing like this doesn't take as long as setting up such tests (I know that may seem backwards, but it's true for me).

    And either way, sometimes what's shared here helps others who may be following the conversation.
  • Don Coxe's Gravatar
    Posted By
    Don Coxe | 12/15/15 11:39 AM
    Thanks for your comments, Charlie.

    I've tried them all and no still joy.

    I'll try some further cookie heroics, but may be headed for a dead end.

    I've reached out to a number of people and for all the suggestions I've received (a few) no one seems to have experience with this seemingly straightforward problem.

    The only other prospect - and it's frightening - would be a SAML solution.

    If you have the opportunity to take a closer look, don't let me hold you back!

    Thanks again,
  • Don Coxe's Gravatar
    Posted By
    Don Coxe | 12/15/15 1:17 PM
    Charlie -

    Let me run this past you - it works, but is it fully secure? I'm guessing it's pretty good:

    I've turned off J2EE sessions.
    I've turned off setClientCookies
    I've turned on setDomainCookies (but it's irrelevant)
    I've turned on use UUID for cftoken

    Then, in OnSessionStart, using <cfcookie> I write the CFID and CFTOKEN cookies to the domain without subdomain as HTTPOnly.

    So, the much-maligned CFID/CFTOKEN cookies are being created as *session* cookies with UUID.

    In your opinion, is this comparable - in security terms - to J2EE cookies? Note that in either case, I was not setting them as "Secure".

    This allows me to switch subdomains without losing session.

    Your opinion would be valuable. Thanks.
  • Charlie Arehart's Gravatar
    Posted By
    Charlie Arehart | 1/22/16 1:12 PM
    Hey, Don. Sorry I missed this last month. How has it turned out for you?

    As for whether your approach is comparable to J2EE sessions, in terms of security, I'd say it's close. Both are using a UUID, which is generally the key for security (hard for a bad guy to guess/spoof).

    I would note that whenever one chooses to set the CFID and CFTOKEN cookies manually, they open a risk of a problem, if they don't set them the way CF would. There are several attributes, some new in CF10 and above, which can influence how the cookies are written (whether secure, whether httponly, whether to encode, whether to preservecase.)

    I say that for others, but I know in your case you were trying to resolve problems that seemed related to seeming problems with the subdomain and httponly.

    Let us know how it went. And if you are still having the problem, you may want to restate briefly the problem and your setup, so that anyone perhaps reading this only recently doesn't need to go back and piece together the several recent comments.

    And hoping that Mark will feel that this discussion is indeed still relevant to the point of the original post. :-)
  • Charles Robertson's Gravatar
    Posted By
    Charles Robertson | 1/31/16 6:02 PM
    Charlie. Why can't we just setDomainCookies = yes? Doesn't this achieve the same thing, and seems much simpler...