How to use Indy 10 to POST to a web app with IIS Windows Authentication?

Hello
I´m having a hard time to POST a form to a web application that is configured in IIS to use Windows Authentication. The component is *TIdHTTP*.
The client application is running under an already authenticated account. When I try to POST using a web browser (Chrome in my tests) it all works, but when I run my application (written with Delphi XE and Indy 10) I allways receive the standard page from IIS, stating I´m not authorized to access that URL.
I already provided my user credentials (user name and domain password) in the *TIdHTTP.OnAuthentication* event, but it seems to have no effect.
Thanks in advance.
Alex
0
Utf
6/5/2013 11:10:27 AM
📁 embarcadero.delphi.tools
📃 5366 articles.
⭐ 3 followers.

💬 7 Replies
👁️‍🗨️ 1670 Views


Am 05.06.2013 13:10, MPS Informática wrote:
 > I already provided my user credentials (user name and domain 
password) in the *TIdHTTP.OnAuthentication* event, but it seems to have 
no effect.
Try inspecting the HTTP response to find out which auth methods (Basic, 
NTLM, Digest, Kerberos) are supported.
For Basic, simply use
       IdHTTP.Request.BasicAuthentication := True;
       IdHTTP.Request.Username := 'user';
       IdHTTP.Request.Password := 'pass';
Hope this helps
-- 
Michael Justin
0
Michael
6/5/2013 1:48:40 PM
MPS wrote:
> I´m having a hard time to POST a form to a web application that is
> configured in IIS to use Windows Authentication. The component is
> *TIdHTTP*.
Add the IdAuthenticationNTLM or IdAuthenticationSSPI unit to your uses clause, 
if you have not already done so.  Those activate Indy's NTLM/SSPI support 
for TIdHTTP.
> The client application is running under an already authenticated
> account.
Irrelevant, since apps do not share HTTP credentials with each other.  TIdHTTP 
uses its own socket connection, so it has to authenticate itself with the 
server.
> I already provided my user credentials (user name and domain password)
> in the *TIdHTTP.OnAuthentication* event, but it seems to have no
> effect.
Set the TIdHTTP.Request.Username and TIdHTTP.Request.Password properties. 
 TIdHTTP will attempt them first, and then if the server keeps asking for 
credentials, the OnSelectAuthorization and OnAuthorization events will be 
fired so you can update the values as needed.
--
Remy Lebeau (TeamB)
0
Remy
6/5/2013 4:08:29 PM
Thank you for your help, I believe we are getting close to make it work. My experients are as follows:
> Add the IdAuthenticationNTLM or IdAuthenticationSSPI unit to your uses clause, 
> if you have not already done so.  Those activate Indy's NTLM/SSPI support 
> for TIdHTTP.
Done!
> Set the TIdHTTP.Request.Username and TIdHTTP.Request.Password properties. 
>  TIdHTTP will attempt them first, and then if the server keeps asking for 
> credentials, the OnSelectAuthorization and OnAuthorization events will be 
> fired so you can update the values as needed.
Done, however, only the *OnSelectAuthorization* was fired. In this event I provided the class *TIdSSPINTLMAuthentication*, because I inspected the reponse 
headers and found this:
{code}
Content-Length: 1656
Content-Type: text/html
Server: Microsoft-IIS/6.0
WWW-Authenticate: Negotiate
WWW-Authenticate: NTLM
WWW-Authenticate: Basic
realm="mps.interno"
X-Powered-By: ASP.NET
Date: Wed, 05 Jun 2013 18:35:45 GMT
{code}
So, it seemed to me that the correct class should be that one.
The *OnAuthorization* event was never fired what was a bit surprising to me. I decided to remove the Username and Password in the *Request* property, but it 
seemed to be with no effect.
The *TIdHTTP* component is configured as follows:
{code}
  object IdHTTP: TIdHTTP
    AllowCookies = True
    HandleRedirects = True
    ProxyParams.BasicAuthentication = False
    ProxyParams.ProxyPort = 0
    Request.ContentLength = -1
    Request.ContentRangeEnd = -1
    Request.ContentRangeStart = -1
    Request.ContentRangeInstanceLength = -1
    Request.Accept = 'text/html, */*'
    Request.BasicAuthentication = False
    Request.UserAgent = 'Mozilla/3.0 (compatible; Indy Library)'
    Request.Ranges.Units = 'bytes'
    Request.Ranges = <>
    HTTPOptions = [hoForceEncodeParams]
    OnSelectAuthorization = IdHTTPSelectAuthorization
    OnAuthorization = IdHTTPAuthorization
    CookieManager = IdCookieManager
    Left = 416
    Top = 8
  end
{code}
The HTTP status code returned is 401.2. The content returned by the web server was:
{code}
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<HTML><HEAD><TITLE>You are not authorized to view this page</title>
  <meta name="viewport" content="width=device-width">
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<STYLE type="text/css">
  BODY { font: 8pt/12pt verdana }
  H1 { font: 13pt/15pt verdana }
  H2 { font: 8pt/12pt verdana }
  A:link { color: red }
  A:visited { color: maroon }
</STYLE>
</HEAD><BODY><TABLE width=500 border=0 cellspacing=10><TR><TD>
<h1>You are not authorized to view this page</h1>
You do not have permission to view this directory or page using the credentials that you supplied because your Web browser is sending a WWW-Authenticate header 
field that the Web server is not configured to accept.
<hr>
<p>Please try the following:</p>
<ul>
<li>Contact the Web site administrator if you believe you should be able to view this directory or page.</li>
<li>Click the <a href="javascript:location.reload()">Refresh</a> button to try again with different credentials.</li>
</ul>
<h2>HTTP Error 401.2 - Unauthorized: Access is denied due to server configuration.

Internet Information Services (IIS)</h2> <hr> <p>Technical Information (for support personnel)</p> <ul> <li>Go to <a href="http://go.microsoft.com/fwlink/?linkid=8180">Microsoft Product Support Services</a> and perform a title search for the words HTTP and 401.</li> <li>Open IIS Help, which is accessible in IIS Manager (inetmgr), and search for topics titled About Security, Authentication, and About Custom Error Messages.</li> </ul> </TD></TR></TABLE></BODY></HTML> {code} Thanks in advance
0
Utf
6/5/2013 7:03:59 PM
Hello
I activated Basic Authentication in TIdHTTP and reconfigured some properties and it seems the authentication problem is solved. However, I now have the following exception when I call Post:
{code}
---------------------------
Debugger Exception Notification
---------------------------
Project TesteMumpsWeb.exe raised exception class EIdIOHandlerPropInvalid with message 'IOHandler value is not valid'.
---------------------------
Break   Continue   Help   
---------------------------
{code}
Any ideas what it means?
Thanks in advance.
Alex
0
Utf
6/5/2013 7:30:50 PM
MPS wrote:
> I activated Basic Authentication
Setting BasicAuthentication=true simply allows TIdHTTP to attempt "BASIC" 
authentication if no other authentications are enabled. But the server has 
to support "BASIC" in order for that to work.  The OnSelectAuthorization 
event provides a list of the authentications that the server actually supports 
for any given request.
> However, I now have the following exception when I call Post:
You are posting to an HTTPS url, but you did not first assign an SSL IOHandler, 
such as TIdSSLIOHandlerSocketOpenSSL, to the TIdHTTP.IOHandler property.
--
Remy Lebeau (TeamB)
0
Remy
6/5/2013 7:44:02 PM
MPS wrote:
> Done, however, only the *OnSelectAuthorization* was fired.
<snip>
> The *OnAuthorization* event was never fired what was a bit
> surprising to me. 
When the OnSelectAuthorization event is fired, its AuthenticationClass parameter 
is pre-initialized with TIdHTTP's first choice class type, based on the entries 
in the provided AuthInfo parameter and the list of enabled TIdAuthentication 
classes.  You can overwrite the AuthenticationClass parameter with a different 
value, but it must be a class that supports one of the values in the AuthInfo 
parameter.  So in your case, either TIdSSPINTLMAuthentication ("Negotiate"), 
TIdNTLMAuthentication ("NTLM"), or TIdBasicAuthentication ("Basic").
The only way the OnAuthorization event would not be triggered afterwards 
is if the specified AuthenticationClass failed to initialize itself.
> So, it seemed to me that the correct class should be that one.
It is one of several classes you can pick from in this situation.  Each "WWW-Authenticate" 
header indicates a different authentication that the server will accept.
> I decided to remove the Username and Password in the *Request* property
Why?  You should be assigning them if you have user/pass values to use.
> The HTTP status code returned is 401.2.
HTTP status codes are not allowed to use decimal values, per RFC 2616 Section 
6.1.1, and TIdHTTP does not support them anyway.  Decimals are an IIS-specific 
extension for use with .NET (see the ASP.NET HttpResponse.SubStatusCode property), 
but Microsoft's own documentation states (emphasis added): "When you set 
the SubStatusCode property, the status is logged on IIS 7.0 if failed-request 
tracing is configured. Independent of whether tracing is configured, **the 
code is never sent as part of the final response to the request.**".  If 
you are actually seeing a decimal status code arrive in TIdHTTP, then the 
IIS server is broken, and that will cause problems since TIdHTTP would not 
be able to extract the status code from the responses correctly.
--
Remy Lebeau (TeamB)
0
Remy
6/5/2013 8:12:27 PM
It seems my problem now is related to the particular process I´m dealing with, so I believe the question is answered. Thank you very much!
Alex
0
Utf
6/5/2013 8:36:09 PM
Reply: