4
votes

I'm trying to call a web service hosted on IIS with Windows Authentication security applied.

I'm using Delphi XE with INDY 10 and the TIdHttp component.

I can successfully call the web service if I pass in a valid username and password but I would like to use Integrated Security so that it automatically uses the credentials from the calling thread and does not require the user to manually input their details.

I've included IdAuthenticationSSPI in the uses clause and call the http request as:

IdHttp1.Request.BasicAuthentication := False;
IdHttp1.HTTPOptions := [hoInProcessAuth];
// IdHttp1.Request.Username := '...'; // including this works
// IdHttp1.Request.Password := '...'; // including this works

IdHttp1.Get(myURL, myOutputStream);

My understanding is that with IdAuthenticationSSPI it will impersonate the user of the calling thread if no credentials are passed.

I've seen comments on the atozedsoftware.newsgroups website that suggest this is possible but unfortunately I get a "HTTP/1.1 401 Unauthorized".

Does anyone have any suggestions?

1
did you try the URL with a browser (IE, FF)? If they work, you can use Fiddler to compare their HTTP communication with Indy. - mjn
Yes. With fiddler I can see the 401 results that have Negotiate in the Authorization section. The Browser and the Delphi app (with the username//password) both change from Negotiate to NTLM and then return a 200. With the Username, Password commented out it never gets past the negotiate 401 entries. - Mattl
IdAuthenticationSSPI does not currently implement "Negotiate" authentication correctly. This is a known issue that has not been fixed yet. - Remy Lebeau

1 Answers

3
votes

Following on from Remy Lebeau's comment it appears this is not possible with INDY until a known issue is fixed.

I've solved my issue in another way and I'll post it here in case anyone else is interested.

First I imported the WinHTTP type library (C:\Windows\system32\winhttp.dll) and added WinHttp_TLB to the uses clause.

Then I used it like this:

var
    http: IWinHttpRequest;
    url: String;
begin
    url := 'my web service';
    http := CoWinHttpRequest.Create;
    try
        http.SetAutoLogonPolicy(0); // Enable SSO
        http.Open('GET', url, False);
        http.Send(EmptyParam);
        ShowMessage(http.ResponseText);
    finally
        http := nil;
    end;
end;