Watch, Follow, &
Connect with Us

For forums, blogs and more please visit our
Developer Tools Community.


Welcome, Guest
Guest Settings
Help

Thread: TidHttp::OnAuthorization does not authorize


This question is answered.


Permlink Replies: 2 - Last Post: May 17, 2017 12:41 AM Last Post By: koen Barbier
koen Barbier

Posts: 8
Registered: 6/12/00
TidHttp::OnAuthorization does not authorize  
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 16, 2017 2:09 AM
Hi,

I am testing basic http authentication using a TIdHTTPServer and a TIdHTTP Client. When I set the credentials before retrieving the url, everything goes well, but when I want to set the username and password using the OnAuthorziation event, then the authorization fails.
I am using Rad Studio 10.1 Update 2, with the indy version coming with this installation (indy 10.6.2.5341)

I have attached a sample project in the attachments forum : https://forums.embarcadero.com/thread.jspa?threadID=250458

Basically this is the code:

I have a server with this as CommandGet event:

void __fastcall TFrmSrvMain::IdHTTPServer1CommandGet(TIdContext *AContext, TIdHTTPRequestInfo *ARequestInfo,
          TIdHTTPResponseInfo *AResponseInfo)
{
if (ARequestInfo->AuthPassword != EditPass->Text || ARequestInfo->AuthUsername != EditUser->Text)
   {
   // setting the AuthRealm sets up everything else with default values
   AResponseInfo->AuthRealm = "mydomain";
   }
else
   {
   AResponseInfo->ContentText = "<html><body>succeeded in authorization</body></html>";
   }
}
//---------------------------------------------------------------------------


In the client, I have provided 2 ways for getting a url:

1) direct authentication. This function succesfully adds 'succeeded in authorization' to the memo

void __fastcall TFrmClntMain::BtnImmediateAuthClick(TObject *Sender)
{
TIdHTTP *IdHTTP = new TIdHTTP (this);
TStringStream *Stream = new TStringStream ();
 
Memo1->Lines->Clear ();
 
if (! EditUser->Text.IsEmpty () && ! EditPass->Text.IsEmpty ())
   {
   IdHTTP->Request->BasicAuthentication = true;
   IdHTTP->Request->Username = EditUser->Text;
   IdHTTP->Request->Password = EditPass->Text;
   }
 
IdHTTP->Get (EditUrl->Text, Stream);
 
Memo1->Lines->Add (Stream->DataString);
 
delete Stream;
delete IdHTTP;
}
//---------------------------------------------------------------------------


2) Authorization via the event: This function sets '401 Unauthorized' in the Memo although the credentials are the same

void __fastcall TFrmClntMain::BtnAuthEventClick(TObject *Sender)
{
TIdHTTP *IdHTTP = new TIdHTTP (this);
TStringStream *Stream = new TStringStream ();
 
Memo1->Lines->Clear ();
 
IdHTTP->Request->BasicAuthentication = true;
IdHTTP->OnAuthorization = IdHTTPAuthorization;
//IdHTTP->MaxAuthRetries = 5;
IdHTTP->Get (EditUrl->Text, Stream);
 
Memo1->Lines->Add (Stream->DataString);
 
delete Stream;
delete IdHTTP;
}
//---------------------------------------------------------------------------
void __fastcall TFrmClntMain::IdHTTPAuthorization(TObject *Sender, TIdAuthentication *Authentication,
          bool &Handled)
{
Authentication->Username = EditUser->Text;
Authentication->Password = EditPass->Text;
 
Handled = true;
}
//---------------------------------------------------------------------------


What am I doing wrong here?
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: TidHttp::OnAuthorization does not authorize
Correct
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 16, 2017 4:14 PM   in response to: koen Barbier in response to: koen Barbier
koen Barbier wrote:
void __fastcall TFrmSrvMain::IdHTTPServer1CommandGet(TIdContext *AContext, TIdHTTPRequestInfo *ARequestInfo,
          TIdHTTPResponseInfo *AResponseInfo)
{
if (ARequestInfo->AuthPassword != EditPass->Text || ARequestInfo->AuthUsername != EditUser->Text)
   {
   // setting the AuthRealm sets up everything else with default values
   AResponseInfo->AuthRealm = "mydomain";
   }
else
   {
   AResponseInfo->ContentText = "<html><body>succeeded in authorization</body></html>";
   }
}

That code is not thread-safe. The OnCommandGet event is triggered in the context of a worker thread, so you MUST synchronize with the main UI thread in order to access your TEdit controls safely.

1) direct authentication. This function succesfully adds 'succeeded in authorization' to the memo

You can simplify that code to the following:

void __fastcall TFrmClntMain::BtnImmediateAuthClick(TObject *Sender)
{
    Memo1->Clear();
 
    TIdHTTP *IdHTTP = new TIdHTTP(NULL);
    try
    {
        IdHTTP->Request->BasicAuthentication = true;
        IdHTTP->Request->Username = EditUser->Text;
        IdHTTP->Request->Password = EditPass->Text;
 
        Memo1->Text = IdHTTP->Get (EditUrl->Text);
    }
    __finally
    {
        delete IdHTTP;
    }
}


Or better:

#include <memory>
 
void __fastcall TFrmClntMain::BtnImmediateAuthClick(TObject *Sender)
{
    Memo1->Clear();
 
    std::unique_ptr<TIdHTTP> IdHTTP (new TIdHTTP(NULL)); // or std::auto_ptr if prior to C++11
 
    IdHTTP->Request->BasicAuthentication = true;
    IdHTTP->Request->Username = EditUser->Text;
    IdHTTP->Request->Password = EditPass->Text;
 
    Memo1->Text = IdHTTP->Get (EditUrl->Text);
}


2) Authorization via the event: This function sets '401 Unauthorized' in the Memo although the credentials are the same

That is because you are not enabling the hoInProcessAuth flag in the TIdHTTP::HTTPOptions property. It is disabled by default.

When TIdHTTP receives a 401 reply, if the AuthRetries property is less than the MaxAuthRetries property then TIdHTTP will trigger the OnAuthorization event (if appropriate to do so, which it is for "Basic" authentication), and then retry the request only if hoInProcessAuth is enabled, otherwise it exits. If AuthRetries reaches MaxAuthRetries, or OnAuthorization is not handled, an exception is raised (unless 401 is specified in the AIgnoreReplies parameter of the method you are using to retrieve a URL, in this case TIdHTTP::Get()).

For what you are attempting to do, you need to enable the hoInProcessAuth flag:

IdHTTP->HTTPOptions = IdHTTP->HTTPOptions << hoInProcessAuth;


--
Remy Lebeau (TeamB)
koen Barbier

Posts: 8
Registered: 6/12/00
Re: TidHttp::OnAuthorization does not authorize  
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 17, 2017 12:41 AM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Remy Lebeau (TeamB) wrote:
IdHTTP->HTTPOptions = IdHTTP->HTTPOptions << hoInProcessAuth;

Hi Remy,

Thanks, this was indeed what was missing, both ways now work correctly.

ps: I am aware that I normally should synchronize when writing to the UI thread, and I should use smart pointers. I just quickly created a simple test program, but thanks nevertheless for the hints
Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02