Search code examples
coldfusioncoldfusion-10

ColdFusion not maintaining session across cfhttp calls


I'm having an issue trying to use cfhttp. I'm using an API that requires me to send login credentials, then send subsequent commands. The reply on the subsequent commands is "login required". After looking at my requests, I think I've found the issue but I don't understand it.

Here's my login call:

<cfhttp url="#Target#"  result="LoginAttempt"  method="POST" REDIRECT="No" useragent="#strUserAgent#"> 
    <cfhttpparam type="FORMFIELD" name="action" value="Login"  />
    <cfhttpparam name="loginUsername" value="#Username#" type="FORMFIELD" />    
    <cfhttpparam name="loginPassword" value="#Password#" type="FORMFIELD" /> 
</cfhttp> 

When this returns 200 OK, I set the cookie to use for future calls:

<cfset ThisCookie = LoginAttempt.responseHeader["Set-Cookie"] />

Then, proceeding with the next call:

<cfhttp url="#Target#"  result="CreateTransactionAttempt" method="POST" REDIRECT="No" useragent="#strUserAgent#"> 
    <cfhttpparam type="header" name="Cookie" value="#ThisCookie#" />
    <cfhttpparam type="FORMFIELD" name="action" value="CreateTransaction" />
    <cfhttpparam type="FORMFIELD" name="transactionName" value="#TransactionName#" />
</cfhttp> 

The problem I think is this; when I look at the header of the second cfhttp call, it doesn't match the cookie provided by the first call. I'm not sure why this would be. On Ben Nadel's blog page here, he has a function that splits the returned cookie into a struct and passes that into the second call. I've tried that with the same result. Am I missing something?


Solution

  • You cannot take the Set-Cookie header from the response and just echo it as Cookie header in the request. Set-Cookie can contain directives like Domain, Path, Secure, HttpOnly, Expires, Max-Age etc. You need to strip them and reduce it to the cookie's key-value pair, because that's what the Cookie header in your request is supposed to contain.

    Example 1, single cookie

    Response:

    Set-Header: JSESSIONID=9335968036E8B5EE9F9D00032A5A665D; Path=/; HttpOnly
    

    Key-Value-Pair:

    Key: JSESSIONID
    Val: 9335968036E8B5EE9F9D00032A5A665D
    

    Request:

    Cookie: JSESSIONID=9335968036E8B5EE9F9D00032A5A665D
    

    Example 2, multiple cookies

    Response:

    Set-Header: JSESSIONID=9335968036E8B5EE9F9D00032A5A665D; Path=/; HttpOnly
    Set-Header: uid=d1b68f6fe0ca70e8d53bd3a2f32d06c1f1554317436; expires=Thu, 02-Apr-20 18:50:36 GMT; path=/; domain=.example.org; HttpOnly
    

    Key-Value-Pairs:

    Key: JSESSIONID
    Val: 9335968036E8B5EE9F9D00032A5A665D
    
    Key: uid
    Val: d1b68f6fe0ca70e8d53bd3a2f32d06c1f1554317436
    

    Request:

    Cookie: JSESSIONID=9335968036E8B5EE9F9D00032A5A665D; uid=d1b68f6fe0ca70e8d53bd3a2f32d06c1f1554317436
    

    For starters, something naive like:

    <cfset ThisCookie = getToken(LoginAttempt.responseHeader["Set-Cookie"], 1, ";") />
    

    could possibly already solve the problem for you.