Call works in Postman, does not work with CFHTTP

I’m trying to make a cfhttp request to an API that requires a client certificate for authorization. My request works fine in Postman, but returns a 401 when called with CFHTTP. What possible difference(s) could there be that might explain different responses between the two?

The call is dead simple:

<cfhttp clientcert="#expandPath('./cert.p12')#" url="#API_URL#" port="443" method="POST" result="apiResult">
	<cfhttpparam type="header" name="Content-Type" value="application/json" />
	<cfhttpparam type="body" value="{}" />
</cfhttp>

Thanks

OS: Windows Server 2016
Java Version: 11.0.18 Eclipse Adoptium 64-bit
Tomcat Version: 9
Lucee Version: 5.4.5.23

Did you install the client certificate to the lucee server?

Install it how? I see I forgot to format my code sample properly, so it got stripped out, but if I used the clientcert attribute on the cfhttp call, isn’t that enough?
How would I install the client cert to try that? I know certs can be added in the admin, but that’s done via URL, right? This is a self-generated .p12 file.

Thanks

the pure java browser invoked by cfhttp needs the client cerificate installed into your java keystore for tomcat.

download the certificate with a browser for the site you are trying to use with cfhttp

save it someplace simple, like c:\importssl
open a commandline as administrator control shift enter
go to c:\importssl

keytool -importcert -file certificate.cer -keystore keystore.jks -alias "whateveryouwannacallit" 

restart tomcat

Perhaps I wasn’t clear. This is an x509 client certificate I’m talking about, not a server certificate. It is not installed on a server. I created it with openSSL. It is attached to the cfhttp request with the clientcert= attribute that points to the p12 file.

The cert is definitely being attached to the request, because if I add the clientcertpassword attribute with an incorrect password, it throws an exception.

Without your code, its at best a guess. I guessed, it was the most common issue, which is you did not install the certificate in the java keystore.

So lets say that is working, the next step is looking at the response headers between postman and cfhttp

dump the response headers and compare the differences between postman and what your code is sending.

Yes, I’ve done this, and I suspect you’re talking about request headers rather than response headers. The actual code is irrelevant. It’s a simple cfhttp call, like:

cfhttp(clientcert=“path/to/cert.p12”, url=“#api_url#”, method=“post”) {
cfhttpparam(name=“Content-Type”, type=“header”, value=“application/json”);
cfhttpparam(type=“body”, value=“{}”);
}

Postman adds more headers than that, but I’ve tried executing the request with all the same ones, to no avail. Postman yields the expected results with the same cert, cfhttp gives me a 401.

No, ill post as a gist. forum doesnt seem to like the code sample.

1 Like

thanks, but I don’t need help with the CF code. What I want to know is what – at a low level – might be the difference between the CFHTTP call and the call from Postman, which works.

headers are signifgantly different between postman and java.

the code in the gist saves the headers both request and response to a log file.

As much as one could say this is a lucee issue, you’re right its not.

Click the pre-formatted text icon or Ctrl+e or enclose it within two lines of ``` (three backticks).

1 Like

Have you debugged your headers as described in the following post using gethttprequestdata() ? The other question: have you tried postman from the very same machine? Don’t know the API you are calling, but if it destinated to “end users” clients, then there might be some type of geo-ip-blocking.

Also, please also make sure to send the accept headers like seen the following Post.

I’ve tried sending the post from Postman to my own script to output the headers, and the same with my own CFHTTP request. I don’t see any significant differences in the headers, but the client certificate specified in the clientcert attribute is not included in the headers, and that seems to be where the problem lies. Somehow.

Still have no idea why this works in Postman and not CFHTTP. Especially when it worked fine prior to creating a new certificate after the previous one expired.