#1 2012-04-06 12:30:27

array81
Member
From: Italy
Registered: 2010-07-23
Posts: 411

Check user timeout

Is there a way to check if an user is timeout?
I need prevent that the user use the database when is timeout. When the user is timeout my application should be ask the username and password again and then call setUser.
For example an event to know when the client user or server user is timeout so the application can know it.

Offline

#2 2012-04-06 13:06:45

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,242
Website

Re: Check user timeout

When one user is timed out, its authentication failed, and the command is rejected.

You can set the TSQLRestClientURI.OnAuthentificationFailed event to a method in which you can return a new username and password.
Then the client will try to set the user with these parameters and relaunch the command.
This is already implemented in TSQLRestClientURI.URI method.

  /// used by TSQLRestClientURI.URI() to let the client ask for an User name
  // and password, in order to retry authentication to the server
  // - should return TRUE if aUserName and aPassword both contain some entered
  // values to be sent for remote secure authentication
  // - should return FALSE if the user pressed cancel or the number of Retry
  // reached a defined limit 
  TOnAuthentificationFailed = function(Retry: integer;
    var aUserName, aPassword: string): boolean;

Offline

#3 2012-04-06 15:31:16

array81
Member
From: Italy
Registered: 2010-07-23
Posts: 411

Re: Check user timeout

Thanks.
A stupid question (for you but not for me:) ), I have try to use it:

Database.OnAuthentificationFailed := ClientFallisceAutenticazioneEvento;

function TMainForm.ClientFallisceAutenticazioneEvento(Retry: integer; var aUserName, aPassword: string): Boolean;
begin
  LoginForm := TLoginForm.Create(Self);
  try
    if LoginForm.ShowModal = mrOk then
      begin
        //DatabaseBlocked := False;
        aUserName := LoginForm.edtUsername.Text;
        aPassword := LoginForm.edtPassword.Text;
      end
    else
      begin
        if Retry >= 3 then
          ChiudiDatabase();
      end;
  finally
    LoginForm.Free;
  end;
end;

but I get this error:

[Pascal Error] MainUnit.pas(2042): E2009 Incompatible types: 'regular procedure and method pointer'

How can I assign OnAuthentificationFailed event?

Offline

#4 2012-04-06 16:09:13

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,242
Website

Re: Check user timeout

You are right, I made the event be a plain procedure - my mistake.

This is fixed by http://synopse.info/fossil/info/1bc71e61bc

Much more convenient to use a class method!

Thanks for the report.

Offline

#5 2012-04-06 19:27:06

array81
Member
From: Italy
Registered: 2010-07-23
Posts: 411

Re: Check user timeout

Now it works, but I don't understand how use the OnAuthentificationFailed event.

The client try a database connection. If there is an authentication problem the client OnAuthentificationFailed event is call. This is ok.
There is 3 parameters Retry, aUserName and aPassword. I thought they had the following meaning:
- Retry: number of attemps;
- aUserName, aPassword: the username and password to set by user to retry the authentication.

So I have try this code:

function TMainForm.ClientFallisceAutenticazioneEvento(Retry: integer; var aUserName, aPassword: string): Boolean;
begin
  LoginForm := TLoginForm.Create(Self);
  try
    if LoginForm.ShowModal = mrOk then
      begin
        aUserName := LoginForm.edtUsername.Text;
        aPassword := LoginForm.edtPassword.Text;
      end
    else
      begin
        if Retry >= 3 then
          CloseDatabase();
      end;
  finally
    LoginForm.Free;
  end;
end;

I want the user have 3 attemps for the authentication, after this the database is close and the user must be reopen it. However this code not works.

So I have try this code:

  LoginForm := TLoginForm.Create(Self);
  try
    Result := False;

    if LoginForm.ShowModal = mrOk then
      begin
        aUserName := LoginForm.edtUsername.Text;
        aPassword := LoginForm.edtPassword.Text;

        if Database.SetUser(aUserName, aPassword, False) then
          begin
            Result := True;
          end
        else
          begin
            if Retry >= 3 then
              CloseDatabase();
          end;
      end
    else
      begin  ;
        if Retry >= 3 then
          CloseDatabase();
      end;
  finally
    LoginForm.Free;
  end;

But also this code is not good, CloseDatabase is never call, I think because Retry is not increased.

Some questions:
1) What is the real mean of the parameter?
2) On AuthentificationFailed I need set aUserName, aPassword string as on my example or I need use SetUser() to try if the new user data are ok?
3) If I need set aUserName, aPassword string how can I get a real result? I cannot know the authentication result if I don't use setUser?
4) Can I know the number of attemps?

Offline

#6 2012-04-07 07:13:49

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,242
Website

Re: Check user timeout

The number of retries is set by TSQLRestClientURI.MaximumAuthentificationRetry property:

    /// maximum additional retry occurence
    // - defaut is 0, i.e. will retry once
    // - set OnAuthentificationFailed to nil in order to avoid any retry 
    property MaximumAuthentificationRetry: Integer
      read fMaximumAuthentificationRetry write fMaximumAuthentificationRetry;

1) If you set a value to this property, the Retry parameter of OnAuthentificationFailed  will increase.
2) You do not need to call SetUser(), as I already stated above.
3) If authentication fails, it will reenter the OnAuthentificationFailed event.
4) It is in the Retry parameter.

Just take a look at TSQLRestClientURI.URI source code, and you'll find out all this by yourself!

Offline

#7 2012-04-07 09:16:15

array81
Member
From: Italy
Registered: 2010-07-23
Posts: 411

Re: Check user timeout

Yes, this night I have found the solution for Retry (with MaximumAuthentificationRetry)

However I still do not understand, you said "You do not need to call SetUser()", but in alternative the OnAuthentificationFailed event doesn't work for me (see thye first code of post #5):
1) If I set right username and password I see the login form again...
2) How can I know (inside AuthentificationFailed event) if the username and password are correct to set the right event result?

Last edited by array81 (2012-04-09 12:35:43)

Offline

#8 2012-05-31 15:16:38

lele9
Member
Registered: 2011-10-28
Posts: 170

Re: Check user timeout

hi,
u have found solution for OnAuthentificationFailed?
thanks,
Emanuele

Offline

#9 2012-05-31 16:01:18

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,242
Website

Re: Check user timeout

Code involved is thread-forward and just looks OK:

  for Retry := -1 to MaximumAuthentificationRetry do begin
    result := InternalURI(SessionSign(url),method,Resp,Head,SendData);
    if (result.Lo<>HTML_FORBIDDEN) or not Assigned(OnAuthentificationFailed) then
      break;
    // "403 Forbidden" in case of authentication failure -> try relog
    if not OnAuthentificationFailed(Retry+2,aUserName,aPassword) or
       not SetUser(StringToUTF8(aUserName),StringToUTF8(aPassword)) then
      break;
  end;

So I suspect that your event implementation does not set right username and password as expected.

Could you trace using the debugger within the TSQLRestClientURI.URI method to guess what is happening for you?

Offline

#10 2012-05-31 16:22:48

lele9
Member
Registered: 2011-10-28
Posts: 170

Re: Check user timeout

ok, now i set aUsername e aPassword and all work ok.
thanks,
Emanuele.

Offline

#11 2017-02-28 20:21:07

jbroussia
Member
From: France
Registered: 2011-04-09
Posts: 74

Re: Check user timeout

Hi,

Sorry, I'm late to the party !
I'm trying to reconnect after authentication failed (after server restart) using the OnAuthentificationFailed event.
I set the MaximumAuthentificationRetry value to 3. Nothing fancy in my code:

function TfrmClient.evtAuthentificationFailed(Retry: Integer; var aUserName, aPassword: string; out aPasswordHashed: Boolean): Boolean;
begin
  Result := FALSE;

  with TfrmLogin.Create(Self) do begin
    Caption := IntToStr(Retry);  // TEST
    try
      if ShowModal = mrOk then begin
        aUserName := edtUsername.Text;
        aPassword := edtPassword.Text;
        aPasswordHashed := FALSE;
        Result := TRUE;
      end;
    finally
      Free;
    end;
  end;
end;

Yet the algorithm seems quite crazy:
- if I input the correct username/password on the *FIRST* try, authentification works and everything is fine.
- BUT if I first input a wrong username/password combination, then things go "crazy": even if I input the correct combination on following tries, the OnAuthentificationFailed event keeps firing
  * if I keep inserting wrong combinations, "Retry" won't increase ?
  * if I keep inserting the correct combination, "Retry" will increase (up to 5, though I set the max to 3 ?) but authentification will keep failing ? After the 5 try, the event is not fired anymore but authentification still fails ?
  * if I insert a wrong combination after I inserted the correct combination, "Retry" will be reset to 1 ?

Offline

#12 2017-03-01 11:35:51

jbroussia
Member
From: France
Registered: 2011-04-09
Posts: 74

Re: Check user timeout

I'm trying to learn how to walk, but each step I make, I fall :'-(

Has anyone had any experience in 5 years with OnAuthentificationFailed ? The documentation is sparse and outdated (https://synopse.info/files/html/Synopse … #TITLE_547), there is no example in Samples, and little reference on the forum (almost everything is in this current topic) :-\

Thanks !

Offline

Board footer

Powered by FluxBB