I want to use Fiddler as a proxy for debugging purpose. Without fiddler everything works perfectly fine.
I have to add a certificate to my HTTP request. My code looks like this:
constructor TSpecialHTTP.Create(adbconn: IDBConnection; ...);
var
ssl: TIdSSLIOHandlerSocketOpenSSL;
dbresult: Variant;
q: IDataset;
begin
... other unimportant database stuff
// http is a private variable of the TSpecialHTTP class
http := TIdHTTP.Create;
// fiddler debug
http.ProxyParams.ProxyServer := '127.0.0.1';
http.ProxyParams.ProxyPort := 8888;
ssl := TIdSSLIOHandlerSocketOpenSSL.Create(http);
ssl.SSLOptions.SSLVersions := [sslvTLSv1_2];
http.IOHandler := ssl;
http.Request.ContentType := 'application/json; charset=utf-8';
http.Request.UserAgent := 'MyApplication';
http.Request.CustomHeaders.Clear;
http.Request.CustomHeaders.FoldLines := false; // without it doesn't work, dunno why
http.Request.CustomHeaders.Values[c_version] := GetMyVersion;
http.Request.CustomHeaders.Values['Authorization'] := 'Bearer ' + token;
CreateGUID(guid);
http.Request.CustomHeaders.Values[c_message_id] := Copy(GUIDToString(guid), 2, 36);
http.Request.CustomHeaders.Values[c_generating_utc] := DateToISO8601(TTimeZone.Local.ToUniversalTime(now), true);
http.Request.CustomHeaders.Values[c_version] := cdhrecords[cdht].version;
http.HTTPOptions := [hoForceEncodeParams, hoNoProtocolErrorException, hoWantProtocolErrorContent];
certstream := TBytesStream.Create;
if not VarIsNull(dbresult[1]) then begin
SaveVariantToStream(certstream, dbresult[1]);
certstream.Position := 0;
certstream.SaveToFile(certfile);
ssl.SSLOptions.CertFile := certfile;
ssl.SSLOptions.KeyFile := certfile;
ssl.SSLOptions.Mode := sslmBoth;
ssl.OnGetPassword := GetPassword;
end;
... again unimportant stuff
end;
I tried to add following line to Fiddler script on static function OnBeforeRequest(oSession: Session) {
:
oSession["https-Client-Certificate"] = "C:\temp\cert.pfx";
This is what I get in Fiddler as a request:
POST https://api.example.com/cdh/v1.0/Message/Product HTTP/1.0 Content-Type: application/json; charset=utf-8 Content-Length: 56494190 version: 1.0 Ocp-Apim-Subscription-Key: <key> message-id: 18EE53A3-64D0-4B34-9527-2D92F15FD462 generating-utc: 2024-09-04T07:46:44.363Z signature: <signature> Host: api.example.com Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 User-Agent: MyApplication
And this is what I get as a response:
HTTP/1.1 401 Missing certificate or authorization header Keep-Alive: true Content-Length: 0 Request-Context: appId=cid-v1:1c288406-24f1-4c26-9015-e7bdd006594a Date: Wed, 04 Sep 2024 07:46:46 GMT Connection: close
What do I have to do to make it work with Fiddler as a proxy?
1
Your main problem you are trying to provide a pfx/PKCS#12 file that contains the HTTPS client certificate:
oSession["https-Client-Certificate"] = "C:\temp\cert.pfx";
However the documented way to use a HTTPS client certificate in Fiddler [Classic] is:
- Install the certificate in the Current User’s Personal Certificate Store.
- Right-click the certificate in Personal Certificates Store.
- Click All Tasks > Export… as .CER file
This exported certificate is then set via Fiddler script:
oSession["https-Client-Certificate"] = "C:\temp\cert.cer";
That means the private key and the certificate have to be present in the Windows personal certificate store and the file you set to oSession["https-Client-Certificate"]
is only a certificate without private key. This file/certificate is used by Fiddler to identify which certificate/private key it have to use from Windows personal certificate store.
A .CER file does not actually contain the private key for the certificate. The local CER merely acts as a pointer to a certificate in your Personal Certificates store– that certificate, installed the Windows Personal Certificate store (
certmgr.msc
) contains the private key. (Source)
3