I've just upgraded from Indy 8.# to 9.0.14 with Delphi 6. Everything seems to work fine.
I am new to authentication when using the idHTTP component. I presume that the process is as follows:
1. Detect authentication method required
2. Populate required fields such as ProxyPassword, ProxyUsername, etc
3. Perform idHTTP.Get command for required webpage.
I have seen much confusion, and bug reports on using and Authentication, SSPI, NTLM etc with Indy. Refence follows:
http://newsgroups.borland.com/cgi-bin/dnewsweb?cmd=article&group=borland.public.delphi.internet.winsock&item=54082&utag=
Does anyone have example code that goes through the above steps successfully? I'm not asking to be spoon fed, however, there seems to be many problems associated with authentication, especially relating to HTTP and proxy servers.
Thanks in advance,
Jason.
> 1. Detect authentication method required
What authorization are you referring to exactly? If just a username and
password, you can set those before you connect and make the request to the
server. Or you can wait until the OnAuthorization event to trigger.
> 2. Populate required fields such as ProxyPassword, ProxyUsername, etc
You need to fill those in before you connect and make the request to the
server.
Gambit
>> 1. Detect authentication method required
>
>What authorization are you referring to exactly? If just a username and password, you can set those before you connect and make the request to the server. Or you can wait until the OnAuthorization event to trigger.
I am getting "407 Proxy Authentication Required..." responses when executing a idHTTP.Get command. I don't know what type of authentication is needed (basic, digest, etc).
>> 2. Populate required fields such as ProxyPassword, ProxyUsername, etc
>
>You need to fill those in before you connect and make the request to the server.
I'd like my app to test, detect and populate these fields first before performing a idHTTP.Get command.
As my users are schools (I'm giving this software away for free!!) they know nothing about proxy servers and authentication schemes, so I'd like my app to take care of that for them.
Is this possible?
Thanks,
Jason.
> I am getting "407 Proxy Authentication Required..." responses
> when executing a idHTTP.Get command.
I assume that you have TIdHTTP configured to connect to a proxy in the first
place? If so, then just set the proxy's username and password before you
call Get(). If you are already doing that, and still getting an error, then
you are probably providing the wrong authentication info for the proxy. In
which case, you should talk to your proxy's admin (if you have one) to find
out what the proxy is actually expecting.
> I don't know what type of authentication is needed (basic, digest, etc).
Again, talk to your proxy admin about that.
> I'd like my app to test, detect and populate these fields first
> before performing a idHTTP.Get command.
If you are indeed behind a proxy, then you can't detect that ahead of time.
You must populate the values before you can use the TIdHTTP through the
proxy. You will just have to provide a configuration option to your program
that the user can use to specify the appropriate values ahead of time.
> As my users are schools ... they know nothing about proxy servers
> and authentication schemes
They have to have SOMEONE available to manage their networking across the
campus. That is the person you need to talk to.
Gambit
> They have to have SOMEONE available to manage their
> networking across the campus. That is the person you need
> to talk to.
Or, more accurately, that is the person that needs to install your program
on their network and then configure it with the correct proxy info as
needed.
Gambit
>You must populate the values before you can use the TIdHTTP through the proxy. You will just have to provide a configuration option to your program
>that the user can use to specify the appropriate values ahead of time.
You've nailed the crux of my problem. I don't know enough about authentication/proxy and the combinations of settings to code this.
I've looked at the IdHTTP component, and from what I can see it has the following properties that "could" be populated for authentication and navigation through a proxy server.
1. idHTTP.ProxyParams -> (BasicAuthentication, ProxyPassword, ProxyPort, ProxyServer, ProxyUsername)
2. idHTTP.Request.BasicAuthentication
3. idHTTP.Request.Password
4. idHTTP.Request.ProxyConnection
5. idHTTP.Request.Username
Not to mention the events such as OnAuthorisation, OnProxyAuthorisation, OnSelectAuthorisation and OnSelectProxyAuthorisation. I have RTFM but the Indy help doesn't have the "Examples" that the VCL help does that would explain/solve my issues.
Are you aware of any code examples around that could step me through this?? Please!!???
Much appreciated.
Jason.
> You've nailed the crux of my problem. I don't know enough about
> authentication/proxy and the combinations of settings to code this.
You don't have to know anything about it. Indy exposes various properties.
Simply provide input fields for those properties, and let the user decide
what to fill in.
> 2. idHTTP.Request.BasicAuthentication
> 3. idHTTP.Request.Password
> 5. idHTTP.Request.Username
Those have nothing to do with proxies. Those are handled by the end HTTP
server itself.
> Not to mention the events such as OnAuthorisation, OnProxyAuthorisation,
> OnSelectAuthorisation and OnSelectProxyAuthorisation.
You don't need to worry about any of those if you are using the properties.
The On...Authorization events are triggered if TIdHTTP does not provide
authorization values ahead of time and the server requires them. That would
allow the program to fill them in at that time, possible prompting the user
for any needed values.
> I have RTFM but the Indy help doesn't have the "Examples" that the
> VCL help does that would explain/solve my issues.
Have you tried looking at the examples at Indy's website?
Gambit
>You don't have to know anything about it. Indy exposes various properties.
>Simply provide input fields for those properties, and let the user decide what to fill in.
What happens in the case that I provide the user with the ability to enter the ProxyParams properties and the proxy is set to Digest Authentication. Is simply setting the ProxyParams.BasicAuthentication := false and populating the other ProxyParams enough? Sorry for the dumb questions...
>Have you tried looking at the examples at Indy's website?
Yes, but none go into detail regarding other forms of authentication other than basic (ie digest, integrated windows, etc). I presumed I would have to code for each form of Authentication required?
Thanks again for your help.
Cheers,
Jason.
> What happens in the case that I provide the user with the
> ability to enter the ProxyParams properties and the proxy is
> set to Digest Authentication.
That is perfectly fine. Digest vs. non-digest is just a means of encoding
the authorization info. It does not negate the need to support the
authentication info at all.
> Is simply setting the ProxyParams.BasicAuthentication := false and
> populating the other ProxyParams enough?
Internally, if the server asks for digest, then TIdHTTP will try to use
digest. If needed, it will trigger the OnSelectAuthorization and/or
OnSelectProxyAuthorization event for you to provide the class type for the
authorization scheme (TIdAuthorizationDigest, TIdAuthorizationNTLM, etc) and
the username and password and such for the scheme.
Gambit
>Internally, if the server asks for digest, then TIdHTTP will try to use
>digest. If needed, it will trigger the OnSelectAuthorization and/or
>OnSelectProxyAuthorization event for you to provide the class type for the
>authorization scheme (TIdAuthorizationDigest, TIdAuthorizationNTLM, etc) and
>the username and password and such for the scheme.
Am I correct in stating that if these events are fired that I will need to try the idHTTP.Get command again?
Thanks for your help.
Cheers,
Jason.
I must add it is not just Indy. I have tried several other component suites
and have had problems with all of them.
Theo Carr-Brion
"Remy Lebeau (TeamB)" <gambit47...@no.spam.yahoo.com> wrote in message
news:3ffa378c$1...@newsgroups.borland.com...
You may want to check out the following. It goes into some further detail regarding NTLM authentication (which I understand needs to be replaced with idSSPI.pas and/or idAuthenticationSSPI.pas) with an earlier version on Indy. Perhaps it may shed some further light on our problems!! Please post back here if it does.
I am sorry I do not have MS ISA Proxy Server (i am testing with a desktop proxy called Proxy+ that only provides BasicAuthentication), therefore I haven't encountered this (NTLM) yet. Although I am sure I soon will.
Gambit (and anyone else with the knowledge), regarding my earlier posts and Theo's similar problem are you able to post example source code using the Indy idHTTP component that would resolve this issue?
Cheers,
Jason.
In ordert to enable this type of authentication in your application add
IdAuthenticationSSPI to any of the uses caluses in your program.
This will enable this type of authentication and HTTP client will
automatically detect this. Digest is not supported.
Also you can specify custom type of auhtentication on the different events.
tehre is 2 events for Server and proxy authentication.
Also you can specify User name and password and also other authnetication
specific parameters by setting their values to Params property of
Authentication parameter you get.
Authentication.Params['Username']
Authentication.Params['Password']
Also for NTLM(SSPI) authorization you can specify domain parameter
Authentication.Params['Domain']
or if you typecast Authentication object to TIdSSPINTLMAuthentication you
can see it as property.
And don't forget to set HttpOptions.hoInProcessAuth becouse without this
authentication is not handled automatically.
Doychin
"jason" <jason@sportschanbara_removethis.com.au> wrote in message
news:3ffa1885$1...@newsgroups.borland.com...
I have tried all this and numerous other combinations and can not get it to
work. The example posting you give says the proxy must be set up a special
way (Authenticate using "Current User" security context) to work but I
cannot expect all our customers to set up their systems in this special way.
Theo Carr-Brion
"jason" <jason@sportschanbara_removethis.com.au> wrote in message
news:3ffa9f6f$1...@newsgroups.borland.com...
Thank you for posting so quickly, I really appreciate it.
Could you tell me whether the following approach is correct issuing an idHTTP.Get command through an MS ISA Proxy using Integrated Windows Authentication (is this the same as NTLM(SSPI))?
1. Set HttpOptions.hoInProcessAuth := true;
2. Ensure IdAuthenticationSSPI is in the uses clause of my app.
3. Populate idHTTP.ProxyParams values (do I populate ProxyUserName and ProxyPassword as well?)
4. Set idHTTP.ProxyParams.BasicAuthentication := false;
It would really help if you have an example of this in code.
Thanks in advance.
Cheers,
Jason.
Thanks,
Theo Carr-Brion
procedure tSslComObj.DoProxyAuthorization(Sender: TObject; Authentication:
TIdAuthentication; var Handled: boolean);
begin
Authentication.Username:='USERNAME';
Authentication.Password:='PASSWORD';
(Authentication as TIdSSPINTLMAuthentication).Domain:='DOMAIN';
end;
Procedure tSslComObj.Post;
begin
fHttpClient:=tIdHttp.Create(nil);
fSSLIoHandler:=tIdSslIoHandlerSocket.Create(nil);
fAntiFreeze:=tIdAntiFreeze.Create(nil);
fAntiFreeze.OnlyWhenIdle:=False;
with fHttpClient do
begin
ProtocolVersion:=pv1_1;
Port:=443;
IoHandler:=fSSLIoHandler;
HTTPOptions:=[hoKeepOrigProtocol, hoInProcessAuth];
HandleRedirects:=True;
OnProxyAuthorization:=DoProxyAuthorization;
with fSSLIoHandler do
begin
with SslOptions do
begin
Method:=sslvTLSv1;
Mode:=sslmClient;
RootCertFile:='d:\rootcert.cer';
VerifyMode:=[sslvrfPeer];
VerifyDepth:=1;
end;
end;
end;
fHttpClient.ProxyParams.ProxyServer:='192.168.1.7';
fHttpClient.ProxyParams.ProxyPort:=8080;
fHttpClient.Request.ContentType:='text/xml';
fHttpClient.Request.UserName:='';
fHttpClient.Request.Password:='';
fHttpClient.Request.CacheControl:='no-cache';
Result:=True;
try
fHttpClient.DoRequest(hmPost, fServerUrl, fMessageStream,
fResponseStream);
except
on E: Exception do
begin
fErrorMsg:=CleanErrorMsg(E.Message);
Result:=False;
end;
end;
fHttpClient.Free;
fSSLIoHandler.Free;
fAntiFreeze.Free;
end;
"Doychin Bondzhev" <doy...@atozedsoftware.com> wrote in message
news:3ffa...@newsgroups.borland.com...
In this case you display dialog box for example that will ask the user for
all necessary information.
Doychin
"jason" <jason@sportschanbara_removethis.com.au> wrote in message
news:3ffaaf7e$1...@newsgroups.borland.com...
If you are working with SSL/Proxy/idHTTP you may want to check out a previous post on this newsgroup. I haven't had the need for SSL so I can't verify it's correctness.
Cheers,
Jason.
Theo Carr-Brion
"jason" <jason@sportschanbara_removethis.com.au> wrote in message
news:3ffab5dd$1...@newsgroups.borland.com...
Doychin
"Theo Carr-Brion" <theo.ca...@mitrefinch.DELETEME.co.uk> wrote in
message news:3ffab31b$1...@newsgroups.borland.com...
As far as I can see you forgot to set the variable Handled = True;
That is in the DoProxyAuthorization procedure before the end;
You can see in the function TIdCustomHTTP.DoOnAuthorization (idHTTP.pas line
1129)
that the function breaks and returns false if you don't set it. It is
defaulted to False (line 1110).
I can tell you also that I have a working program with indy AND proxy
validation, both basic and NTLM authentication.
So, there is hope.
Greetings
Henk
"Theo Carr-Brion" <theo.ca...@mitrefinch.DELETEME.co.uk> wrote in
message news:3ffab31b$1...@newsgroups.borland.com...
> Am I correct in stating that if these events are fired that I
> will need to try the idHTTP.Get command again?
No. They are triggered inside of Get(), and it will update its internal
state and automatically retry the request as needed.
Gambit
> Digest is not supported.
Yes, the latest versions of Indy support Digest.
> Also you can specify User name and password and also other
> authnetication specific parameters by setting their values to Params
> property of Authentication parameter you get.
Better to use the dedicated Username and Password properties instead. The
Params will be updated internally for you accordingly to the actual
authentication scheme used
> Also for NTLM(SSPI) authorization you can specify domain
> parameter
>
> Authentication.Params['Domain']
If you use TIdNTLMAuthentication as the authentication scheme, it handled
the Domain for you based on the username provided.
Gambit
> (Authentication as TIdSSPINTLMAuthentication).Domain:='DOMAIN';
You are making an assumption that the Authentication is a
TIdSSPINTLMAuthentication instance without actually testing for that
condition first.
> fHttpClient.Request.ContentType:='text/xml';
Why are you setting the Request.ContentType to XML? You cannot perform
requests with XML, although you can recieve XML as a response.
> fHttpClient.DoRequest(hmPost, fServerUrl, fMessageStream,
> fResponseStream);
Why are you calling DoRequest() directly? You should be calling Post()
instead:
fHttpClient.Post(fServerUrl, fMessageStream, fResponseStream);
Gambit
> ... We have a Microsoft ISA proxy ... and I have never been able to get Indy to
> work with it. I have been forced to abandon the use of Indy for this one
> simple reason. I know how the proxy is configured - it calls it integrated
> authentication. ...
This are a general comments they won't solve your problem, but, I hope, will give you some ground to stand on ...
MS Proxy uses non-public "NTLM" protocol, if you check HTTP headers coming from the proxy, you can see that yourself. The protocol consists of 3 messages sent Server->Client, Client->Server and Server->Client that allows client to authenticate itself to the server.
There are two ways client can supply its security credentials to the server:
1) it can supply MSDomainName\UserName\Password;
2) it can supply "CurrentUser" security context, wich is a token (a number) that client can retrieve by Windows API that contains enough information about currently logged in user to the server to authenticate.
The second approach allows you as admin or developper setup your clients without specifying any username/password and it'll work just fine considering your client/server belong to the same (or related) MS Domain (which is normally the case with companies, schools and so on).
To implement NTLM protocol (to generate mentioned above 3 messages) you have two choices:
1) you can use Windows API (particulary known as SSPI);
2) there are some open source libs that "implement" NTLM (google for "NTLM open source", should find plenty).
Both approaches have some problems: 1) is not portable from Windows, while 2) won't let you use "CurrentUser" client credentials and some other nifty things you can do on a server, also 2) is reverse engeniered, so you can't be sure it works 100%.
Indy includes both implementations:
1) IdAuthenticationSSPI.pas;
2) IdAuthenticationNTLM.pas.
But, from what I've heard (I don't use Indy myself), none of them works out of the box. I've heard that some (google for co...@wilsonc.demon.co.uk SSPI Indy) did get it to work, they might be willing to share they dicoveries.
I've done it myself no problem and would be happy to share the knowledge, except considering I don't use Indy, I hardly know where to start.
Alex
Now I'm confused!
Doychin wrote ->> Digest is not supported.
Gambit wrote ->> Yes, the latest versions of Indy support Digest.
Isn't Doychin part of the Indy Core Team? I also noticed that Indy 9.0.14 comes with TidAuthenticationDigest.pas???
Jason.
> I also noticed that Indy 9.0.14 comes with TidAuthenticationDigest.pas???
As I said, Digest is supported, via that very unit.
Gambit
> Internally, if the server asks for digest, then TIdHTTP will
> try to use digest. If needed, it will trigger the
> OnSelectAuthorization and/or OnSelectProxyAuthorization event
> for you to provide the class type for the authorization
> scheme (TIdAuthorizationDigest, TIdAuthorizationNTLM, etc) and
> the username and password and such for the scheme.
How do you "provide the class type for the authorisation scheme" in the OnSelectProxyAuthorization event?
Thanks,
Jason.
The application I am writing must send an xml file with a HTTPS post command
to a secure government server and one of the requirements is that the
content type is set to 'text/xml'. What is wrong with this?
Theo Carr-Brion
"Remy Lebeau (TeamB)" <gambit47...@no.spam.yahoo.com> wrote in message
news:3ffb062b$1...@newsgroups.borland.com...
I had set Handled to True. I missed that line out by mistake when I copied
it. Could you please send samples of working code? I am having real problems
getting it to work. Have you got it to work with HTTPS? What sort of proxy
do you use?
Thanks,
Theo Carr-Brion
"Henk van Hoek" <henkREMOV...@REMOVECAPITALSexencia.com> wrote in
Ok. I did not use HTTPS. I tested it with a Microsoft Proxyserver.
I need HTTPS in the near future as well.
You already have the sample of the working code. I didn't do much more than
you already have done.
But to not disapoint you I show what I have. Check carefully the property
hoInPrecessAuth=True
The next procedure is in my case only called when I had set the protection
level on the proxyserver to basic authentication.
procedure TfrmInternet.HTTPProxyAuthorization(Sender: TObject;
Authentication: TIdAuthentication; var Handled: Boolean);
begin
if frmProxyUser.ShowModal = mrOK then begin
Authentication.Password := ProxyPassword;
Authentication.Username := ProxyUserID;
HTTP.ProxyParams.BasicAuthentication := True; // not really required,
but set here for clarity instead of in the control
Handled := True;
end else begin
Handled := False;
end;
end;
The frmProxyUser is only asking for the username and password and stores the
values in ProxyPassword and ProxyUsername.
Try get it to work in its most basic form without using SSL.
Henk
"Theo Carr-Brion" <theo.ca...@mitrefinch.DELETEME.co.uk> wrote in
message news:3ffbd5e7$1...@newsgroups.borland.com...
> How do you "provide the class type for the authorisation scheme" in the
OnSelectProxyAuthorization event?
Simply assign the desired class name to the AuthenticationClass parameter,
ie:
procedure TForm1.IdHTTP1SelectProxyAuthorization(Sender: TObject; var
AuthenticationClass: TIdAuthenticationClass; AuthInfo: TIdHeaderList);
begin
if (Some Condition) then
AuthenticationClass := TIdDigestAuthentication;
else if (Some Other Condition) then
AuthenticationClass := TIdNTLMAuthentication;
else
// etc ...
end;
Gambit
> The application I am writing must send an xml file with a HTTPS
> post command to a secure government server and one of the
> requirements is that the content type is set to 'text/xml'. What is
> wrong with this?
Nevermind.
Gambit
>Simply assign the desired class name to the AuthenticationClass parameter,
>ie:
>
> procedure TForm1.IdHTTP1SelectProxyAuthorization(Sender: TObject; var
>AuthenticationClass: TIdAuthenticationClass; AuthInfo: TIdHeaderList);
> begin
> if (Some Condition) then
> AuthenticationClass := TIdDigestAuthentication;
> else if (Some Other Condition) then
> AuthenticationClass := TIdNTLMAuthentication;
> else
> // etc ...
> end;
Thanks, that's exactly what I needed.
Does the proxy server pass back what type of Authentication is required when this event fires? ie if (Some Condition) would be
if (the proxy server is telling me it wants Digest authentication) then
AuthenticationClass := TidDigestAuthentication;
And if so where is this information provided??
Cheers,
Jason.
> Does the proxy server pass back what type of Authentication is
> required when this event fires?
Yes. That is what the AuthInfo parameter is for.
> if (the proxy server is telling me it wants Digest authentication) then
> AuthenticationClass := TidDigestAuthentication;
If you simply add TIdAuthenticateDigest to your 'uses' clause, then that is
handled automatically for you, as is the case for any of the other
Authentication scemes that Indy natively supports (NTLM, SSPI, etc).
Gambit
>> if (the proxy server is telling me it wants Digest authentication) then
>> AuthenticationClass := TidDigestAuthentication;
>
>If you simply add TIdAuthenticateDigest to your 'uses' clause, then that is
>handled automatically for you, as is the case for any of the other
>Authentication scemes that Indy natively supports (NTLM, SSPI, etc).
Sorry again to draw this out, but this (the way to set up authentication) isn't well documentented, and the latest examples from the Indy website do not include a HTTP Client demo that goes into this.
I guess this was the part that was troubling me having TidAuthenticationDigest/NTLM/SSPI, etc take care of it for me.
So finally, if I add all the TIdAuthentication"types" to my uses clause, the only thing I would have to concern myself with is BasicAuthentication as it requires the ProxyUserName & ProxyPassword passed with it as well as BasicAuthentication in the Proxyparams set to true?
Thanks for your help.
Jason.
Theo Carr-Brion
"Henk van Hoek" <henkREMOV...@REMOVECAPITALSexencia.com> wrote in
message news:3ffc...@newsgroups.borland.com...
> Thanks for the help. I have tried it on a non-secure site and it then
calls
> the SSPI code but gives a range check error.
Can you tell me where it occured.
Greetings
Henk
I noticed some time ago that you need to compile the indy stuff with
Complete Boolean Eval set to OFF. (Project Options/Compiler/Syntax options)
Maybe this can solve the problem of range check. It helped me once.
Greetings
Henk
>> if (the proxy server is telling me it wants Digest authentication) then
>> AuthenticationClass := TidDigestAuthentication;
>
>If you simply add TIdAuthenticateDigest to your 'uses' clause, then that is
>handled automatically for you, as is the case for any of the other
>Authentication scemes that Indy natively supports (NTLM, SSPI, etc).
Sorry again to draw this out, but this (the way to set up authentication) isn't well documentented, and the latest examples from the Indy website do not include a HTTP Client demo that goes into this.
exception class : ERangeError
exception message : Range check error.
main thread ($834):
005c0f3f IdAuthenticationSSPI 811
TCustomSSPIConnectionContext.UpdateAndGenerateReply
005c1281 IdAuthenticationSSPI 899
TSSPIClientConnectionContext.GenerateInitialChalenge
005c1417 IdAuthenticationSSPI 933
TIndySSPINTLMClient.InitAndBuildType1Message
005c169d IdAuthenticationSSPI 1003 TIdSSPINTLMAuthentication.Authentication
005b440b IdHTTPHeaderInfo 387 TIdProxyConnectionInfo.SetHeaders
005be8b9 IdHTTP 1412 TIdHTTPProtocol.BuildAndSendRequest
005bd684 IdHTTP 912 TIdCustomHTTP.ConnectToHost
005bd826 IdHTTP 942 TIdCustomHTTP.DoRequest
005bc82e IdHTTP 467 TIdCustomHTTP.Post
The length of aFromPeerToken is zero.
I do not have a lot of time to look at this myself now. I have used MSXML to
send the file in my project to get it going. In the long term I would much
rather use Indy as I would like more flexibility and I do not want it
dependent on browser version etc.
Theo Carr-Brion
"Henk van Hoek" <henkREMOV...@REMOVECAPITALSexencia.com> wrote in
message news:3ffd...@newsgroups.borland.com...