Solved

ColdFusion and RETS

Posted on 2013-11-26
17
1,081 Views
Last Modified: 2016-02-26
Hi All,

I am trying to get into the RETS system using ColdFusion.

http://rets.mlxinnovia.com/help/index.php
www.reso.org

At this point I have been able to send a login request using the following code:

<cffunction name="getAuthenticated" access="public" returntype="any">
     
<cfargument name="userName" type="string" required="yes">
<cfargument name="password" type="string" required="yes">

<!--- First request to get Authenticate Information --->
<cfhttp url="http://rets.offutt-innovia.com:8080/nne/login?rets-version=rets/3.0" method="get" username="#ARGUMENTS.userName#" password="#ARGUMENTS.password#">

<cfhttpparam name="Accept" type="header" value="text/xml,text/plain;q=0.5">
<cfhttpparam name="User-Agent" type="header" value="wsdl">
<cfhttpparam name="RETS-Version" type="header" value="3.0">
</cfhttp>
			
<cfset tempCookie = cfhttp.Responseheader["Set-Cookie"]>
			
<cfreturn tempCookie>
			
</cffunction>

<cfcookie name="JSESSIONID" value="#getAuthenticated('myusername','mypassword')#" expires="never">

<cfdump var = "#JSESSIONID#">

Open in new window


When I run the file I get the following response:

JSESSIONID=D95AC85438EBBB3B8FC07375ED157AAE; Path=/nne/; HttpOnly


So I have the request authenticated, but being a SOAP based system - I have no clue how to continue passing the authentication back and forth to the site to make calls to their system.

I truly have no understanding of SOAP or using stateless requests like this.  I only got the code above to work because I found it on another support ticket.

My first attempt was to place the following after the initial code:

<cfhttp url="http://rets.offutt-innovia.com:8080/nne/getmetadata?Type=METADATA-TABLE&ID=Property:ResidentialProperty" method="get" >
</cfhttp>
<cfdump var="#cfhttp#" />

Open in new window


And I get back great big 401 Unauthorized response code.  If I dump the initial function cfhttp - I get a status code  200 OK

Can anyone help me get to the next step of being able to use the login authentication to start making requests on the system?  

I am looking for actual code help as well as theory and understanding.  However I learn the best from code samples.   I like to pull things apart and see how they work then put them together again :)

For reasons too long to go into - I am on a 15 day time crunch to get this done.  As always - help is greatly appreciated.

God Bless,
Chris
0
Comment
Question by:luksha
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 9
  • 8
17 Comments
 
LVL 52

Expert Comment

by:_agx_
ID: 39678656
(no points...just a brief comment)

Edit:   Sorry I'm working on a deadline myself and obviously I didn't fully read your question :/ Apologies I don't have time for a fuller response but ...

> <cfcookie name="JSESSIONID"
> value="#getAuthenticated('myusername','mypassword')#" expires="never">

Actually that just sets a cookie in your browser, it has no effect on the cfhttp call. Since cfhttp is sort of like a mini-browser, you need use <cfhttparam type="cookie"  ...> to set a cookie for the cfhttp request.
0
 

Author Comment

by:luksha
ID: 39678952
Thanks AGX.  I will did a little deeper for the response needed. I am trying to learn how to interpret the RETS documentation on how to send the credentials back.

Digest authentication is brand new to me after being away from CF coding for two years.  It whipping me like a post.
0
 
LVL 52

Expert Comment

by:_agx_
ID: 39679322
I know the feeling ;-)  Since I don't have the time to delve into it now, take this with a large grain of salt ... but the impression I got from the other thread was that the first http request (w/user and password) gets you the authentication cookie.

You then need to parse out the cookie value and include it as a header when making subsequent cfhttp requests.

           ...
          <cfhttpparam name="JSESSIONID" value="D95AC85438EBBB3B8FC07375ED157AAE">

You can find a more detailed explanation of maintaining sessions w/cfhttp here:
http://www.bennadel.com/blog/725-Maintaining-Sessions-Across-Multiple-ColdFusion-CFHttp-Requests.htm
0
Resolve Critical IT Incidents Fast

If your data, services or processes become compromised, your organization can suffer damage in just minutes and how fast you communicate during a major IT incident is everything. Learn how to immediately identify incidents & best practices to resolve them quickly and effectively.

 

Author Comment

by:luksha
ID: 39679462
Thanks for the link.  I have had been reading that article all this afternoon and finally got to pulling the JSESSIONID.  I am thinking now that my issue is with returning that value.  For whatever reason I cannot figure out how to send it back to the RETS system in such a way that it actually keeps me logged in.

Here is my new function: (only slightly modified)
<cffunction name="getAuthenticated" access="public" returntype="any">
<cfargument name="userName" type="string" required="yes">
<cfargument name="password" type="string" required="yes">

<!--- First request to get Authenticate Information --->
<cfhttp url="http://rets.offutt-innovia.com:8080/nne/login" method="get" username="#ARGUMENTS.userName#" password="#ARGUMENTS.password#">
<cfhttpparam name="Accept" type="header" value="text/xml,text/plain;q=0.5">
<cfhttpparam name="User-Agent" type="header" value="#CGI.HTTP_USER_AGENT#">
<cfhttpparam name="RETS-Version" type="header" value="RETS/1.8.0">
</cfhttp>
<cfreturn cfhttp>
</cffunction>

<cfset head = "#getAuthenticated('myuser','mypass')#">

<cfset list1 = head.Responseheader["Set-Cookie"]>

<cfset jsess = trim(replace(listgetat(list1,1,';'),"JSESSIONID=",''))>

JSESSIONID: <cfoutput>#jsess#</cfoutput> 

<cfhttp url="http://rets.offutt-innovia.com:8080/nne/getmetadata?Type=METADATA-TABLE&ID=Property:ResidentialProperty" method="get" >
<cfhttpparam name="JSESSIONID" type="header" value="#jsess#">
</cfhttp>

<cfdump var="#cfhttp#">

Open in new window

From that I get the following output:

JSESSIONID: FAB7959B2BB9239F2423F5276678A62E   

HTTP/1.1 401 Unauthorized Connection: close Date: Tue, 26 Nov 2013 23:16:04 GMT Server: Apache/2.2.3 (Red Hat) Content-Length: 951 RETS-Session-ID: FF71A2FF5AFD9BA964574FB771976369 Cache-Control: private Set-Cookie: JSESSIONID=FF71A2FF5AFD9BA964574FB771976369; Path=/nne/; HttpOnly WWW-Authenticate: Digest realm="rets.offutt-innovia.com",nonce="4ebfc80c52176b73d377fedc59134912",opaque="6d6819542f9bda84914a790a98d7ca03",qop="auth" Content-Type: text/html;charset=utf-8 RETS-Server: RETSInnoVia/3.0 

Open in new window

Note that the JSESSIONIDthat is output from the login is different from both the RETS-SESSION-ID and the JSESSIONIDshown in the error.

I have tried sending both:
<cfhttpparam name="RETS-Session-ID" type="header" value="#jsess#">
and 
<cfhttpparam name="JSESSIONID" type="header" value="#jsess#">

Open in new window


I can't figure out how come the session id is not persistent?

Thanks for your popping in AGX I am grateful for the direction.  I am SLOWLY learning a little more about this part of CF but for some reason it is not coming easy anymore ;)

I will keep plugging away and I hope you will keep thinking as well.
0
 
LVL 52

Expert Comment

by:_agx_
ID: 39679505
(Edit)

> <cfhttpparam name="JSESSIONID" type="header" value="#jsess#">

Try sending it as cfhttpparam type=cookie, rather than type="header". (Technically a cookie IS a sort of header, but there's definitely a distinction in how they're processed.)
0
 

Author Comment

by:luksha
ID: 39679559
Thanks for that heads up.   I completely forgot to send it as a cookie.  I had that earlier and then pasted some other code and missed it.  

Unfortunately it still did not work.   What I found while reading the docs some more is this wonky explanation that I haven't figured out yet that says to send the 'Authorization'

So if I send this:
<cfhttpparam name="Authorization" type="header" value="#jsess#">

in my second call, I get a status code 200 (ok) however I receive no data back in xml or otherwise.  Also the system seems to have set a new JSESSIONID.  

I have even tried just manually setting the JSESSIONID  (cfset cookie.JSESSIONID = jsess) to no avail.  The headache I woke up with is slowly growing :)

I think it is time for me to call it quits for an hour and get some caffeine!
0
 
LVL 52

Expert Comment

by:_agx_
ID: 39679768
After briefly looking at the "specifications" I can see why you have a headache. (Coincidentally I'm working on something completely different .. yet the documentation is equally cryptic. "Advil anyone?" ;-)

Anyway, are you including the user-agent, version, etc... headers in the 2nd request? I happened to notice section 3.3 Required Client Request Header Fields mentioned something about them being required.  I don't know if it'll make a difference, but it couldn't hurt to include them.
0
 

Author Comment

by:luksha
ID: 39679926
Ok so I had a little fun trying to get a couple pages for you to see what I have tried.  I have to admit that making these 4 pages was the most fun of this project so far - because I saw an end in sight :)

http://tiegerrealty.com/rets/ 

There are four index pages.  Each of them login via a cffunction, then attempt to pull metadata from the system.  The metadata they are pulling is using the following url format (which works directly in the browser once I enter in the username and password when prompted)

http://rets.offutt-innovia.com:8080/nne//getmetadata?Type=METADATA-TABLE&ID=Property:ResidentialProperty

Who knows - maybe you will say 'oh dummy you can't do that in one page, you need to first do this, then you can do that'  

Thanks again!
Chris
0
 
LVL 52

Expert Comment

by:_agx_
ID: 39681284
Nice! You know ... I see an error in the 1st response dump, suggesting there's a problem from the very beginning

  <RETS ReplyCode="20036" ReplyText="Missing or Invalid RETS Version" > </RETS>

> works directly in the browser

That's might be a good thing.  I suspect the cfhttp call is missing some headers or sending the wrong values.  If you use FireFox, there's a neat plugin that could help. It's called "Live HTTP Headers".  I'd recommend installing it, then loading the page(s) in your browser. The plugin will let you see what headers your browser passes to the RETS server and hopefully we can see what's different/missing from the cfhttp calls.

https://addons.mozilla.org/en-US/firefox/addon/live-http-headers/
0
 

Author Comment

by:luksha
ID: 39681402
Thank you for the plugin - I am installing now.  I have seen that error each time as well, which is the main reason I made that page allow you to change the RETS version.  I have tried all the version numbers they state on their website.  Everyone returns the same error.

I am excited for the plugin and will let you know asap!

Thanks so much,
Chris
0
 
LVL 52

Expert Comment

by:_agx_
ID: 39681474
Btw, just to be clear, I mean load the regular urls's in your browser ie

http://rets.offutt-innovia.com:8080/nne//getmetadata?Type=METADATA-TABLE&ID=Property:ResidentialProperty

... enter the credentials, and check the Live HTTP Headers results
0
 

Author Comment

by:luksha
ID: 39681522
Yeah, that's what I did,  I am more confused than ever.  Here is a shot of the headers from the working url call...

RETS Live url feed headers - working
I tried to hire someone on odesk to do this for me and they wanted $400 to work through this.  I am starting to wonder if I shouldn't have just let them. :)
0
 
LVL 52

Accepted Solution

by:
_agx_ earned 500 total points
ID: 39681726
(Edit)

First, is that the only request shown? Did you check "Show -> Redirects" on the Generator tab? I think there might be a request/response before the one above. ie From the login

Yeah, the RETS stuff is a little complicated .. made worse by the poor documentation.  Side note, I saw a very promising blog series about it yesterday. A little old but it looked like it covered everything you're trying to do.. unfortunately ALL the links to the code are broken and not even archived on waybackmachine.org :/

Anyway, it looks like you're back to the whole digest authentication stuff, which cfhttp doesn't support. Truthfully I haven't read through the specs fully (It seems like there's different ways to authenticate ... ?). But I saw something similar in 4.1.x Client Authentication.


The first time the client requests the document, no Authorization header is sent, so the server responds with:

       HTTP/1.1 401 Unauthorized
       WWW-Authenticate: Digest realm="Users@example.com",
       nonce="dcd98b7102dd2f0e8b11d0f600bfb0c0"
       opaque="5ccdef346870ab04ddfe0412367fccba"

The client may prompt the user for the username and password, after which it will respond with a new request, including the following he client may prompt the user for the username and password, after which it will respond with a new request, including the following Authorization header:

      Authorization: Digest username="joesmith",
      realm="Users@example.com",
      nonce="dcd98b7102dd2f0e8b11d0f600bfb0c0",
      opaque="5ccdef346870ab04ddfe0412367fccba",
      uri="/login",
      response="13258d9b0bc217c9502b47e32dff8ee9"


... which looks like the info in your screen shot.  The thing I'm not sure about is if you can use that to construct the necessary headers for cfhttp or if you have to use an external library to handle the whole digest authentication stuff. BUT ... I found this thread on Tek-Tips which seems like it generates the necessary Authentication header.  Can you give it a try?

http://www.tek-tips.com/viewthread.cfm?qid=1373438
0
 

Author Comment

by:luksha
ID: 39681804
Thank you AGX.

You are much quicker at finding those articles than I ma that's for sure.  I spent hours over the last couple days reading articles like the ones you listed above.  (including the one with all the missing code.) I wasn't sure about the whole CF doesn't do digest authentication thing though. I was hoping....

But my hopes are finally dashed.  As for the Show -> Redirects I had checked that in the beginning, but noticed that once I close the options - the settings are reset to default.  I was able to leave the console open and open a new FF window and see some of the response headers.  It is overwhelming.

After talking to the client, it looks like I am going to recode the website to the RETS system using a paid SaS for updates instead of a direct RETS connection from our own website.  I found this site yesterday http://retscloud.com/ that will do the transfer for $15 / month.

It looks very promising and I just need to stick with the code I am familiar with at this point and get the site running well.

AGX  You have been an amazing help and I hate to stop going down this road right now - but unfortunately I need to do what the client is willing to take on.  I will probably pursue this in the future but maybe when my server upgrades the CF server it will use Direct Authentication :)

Thank you so much for all your help!

God Bless and Happy Thanks giving (If you're here in the US and celebrate it)

Chris
0
 

Author Closing Comment

by:luksha
ID: 39681812
You were such a great help through this whole thing.  I am only sorry that in the end I had to give up the hunt for now.
0
 
LVL 52

Expert Comment

by:_agx_
ID: 39681892
I completely understand. If I had more time to devote to it, I'm sure we could figure it out .. but it sounds like that's a luxury neither one of us has right now :)

Sorry I couldn't be of more help on this one. Hope you have a great Thanksgiving too !
0
 
LVL 52

Expert Comment

by:_agx_
ID: 39682353
BTW, I appreciate the points, but since ultimately we didn't manage to find a solution to the original problem, it makes more sense to delete this thread.

Best of luck with the new service you found! Sounds like it'll make things a lot easier.
0

Featured Post

MIM Survival Guide for Service Desk Managers

Major incidents can send mastered service desk processes into disorder. Systems and tools produce the data needed to resolve these incidents, but your challenge is getting that information to the right people fast. Check out the Survival Guide and begin bringing order to chaos.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Hi, I will be creating today a basic tutorial on how we can create a Mail Custom Function and use it where ever we want. The main advantage about creating a custom function is that we can accommodate a range of arguments to pass to the Function and …
I spent nearly three days trying to figure out how incorporate OAuth in Coldfusion for the Eventful API. Hopefully, this article will allow Coldfusion Programmers to buzz through the API when they need to. Basically, what this script does is authori…
Finds all prime numbers in a range requested and places them in a public primes() array. I've demostrated a template size of 30 (2 * 3 * 5) but larger templates can be built such 210  (2 * 3 * 5 * 7) or 2310  (2 * 3 * 5 * 7 * 11). The larger templa…

710 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question