Web forum is in read-only mode. Login as active registered customer for write access
  Forum Search   New Posts New Posts

RemoteDB middleware Basic Authentication

 Post Reply Post Reply
Author
Fare' Daniele View Drop Down
Senior Member
Senior Member
Avatar

Joined: 30 Dec 2015
Posts: 153
Post Options Post Options   Quote Fare' Daniele Quote  Post ReplyReply Direct Link To This Post Topic: RemoteDB middleware Basic Authentication
    Posted: 04 Sep 2019 at 3:03pm
Good afternoon,
where i need to declare the middleware Basic Authentication.
In your example, server side i have

procedure StartServer;
begin
if Assigned(SparkleServer) then
     Exit;

SparkleServer := THttpSysServer.Create;

Module := TRemoteDBModule.Create(
    'http://+:2001/tms/remotedb',     // original is 2001
    TFireDacFirebirdConnection.CreateFactory
);

Module.UserName:='UserName';
Module.Password:='UserPassword';

// Uncomment line below to enable CORS in the server
//Module.AddMiddleware(TCorsMiddleware.Create);

// Uncomment line below to allow compressed responses from server
//Module.AddMiddleware(TCompressMiddleware.Create);

SparkleServer.AddModule(Module);

SparkleServer.Start;
end;

This procedure is fired at mainform onshow event, so the server start.
I need to "customize" the login and this is possible via middleware Basic Authentication, but i do not understand where i need to declare it.
In you online doc i found

Module.AddMiddleware(TBasicAuthMiddleware.Create(
    procedure(const UserName, Password: string; var User: IUserIdentity)
    begin
      // Implement custom logic to authenticate user based on UserName and Password
      // For example, go to the database, check credentials and then create an user
      // identity with all permissions (claims) for this user
      User := TUserIdentity.Create;
      User.Claims.AddOrSet('roles').AsString := SomeUserPermission;
      User.Claims.AddOrSet('sub').AsString := UserName;
    end,
    'My Server Realm'
));

Do you have any example on how to use it ?

My need is when the client try to connect to the server, i check the credentials.

Thank's for all

Daniele
Back to Top
Wagner R. Landgraf View Drop Down
TMS Support
TMS Support
Avatar

Joined: 18 May 2010
Posts: 2389
Post Options Post Options   Quote Wagner R. Landgraf Quote  Post ReplyReply Direct Link To This Post Posted: 04 Sep 2019 at 3:37pm
Hello Daniele,
You can add that code just before the call to AddModule. Also be sure to set Module.UserName and Module.Password to empty strings, so it doesn't enforce the default basic authentication.
Back to Top
Fare' Daniele View Drop Down
Senior Member
Senior Member
Avatar

Joined: 30 Dec 2015
Posts: 153
Post Options Post Options   Quote Fare' Daniele Quote  Post ReplyReply Direct Link To This Post Posted: 05 Sep 2019 at 11:34am
Good morning Wagner,
excuse me ... but i have some problem with user autentication.
On server side i have a very simple server that is connected to a firebird db.
On client side i have a RemoteDb with XDataSet that send only one sql request.
What i need, and i'm not able to perform (it's my fault), is an user autentication.
when i click on connect button to the client the program runs

RDB1.ServerUri:=ServerUri;
RDB1.UserName:='pippo'
RDB1.Password:='pluto'
try
    RDB1.Connected:=True;
except on E: Exception do
     Begin
        // Some text here
     End;
end;

This user does not exist into userdb, server side.
Now, if the startserver procedure is

procedure StartServer;
var
Module : TRemoteDBModule;
aes    : TAESEncryption;
CrName : string;
CrPwd : string;
begin
if Assigned(SparkleServer) then
     Exit;

SparkleServer := THttpSysServer.Create;

Module := TRemoteDBModule.Create(
    'http://+:2001/tms/remotedb',
    TFireDacFirebirdConnection.CreateFactory
);
Module.AddMiddleware(TBasicAuthMiddleware.Create(
    procedure(const UserName, Password: string; var User: IUserIdentity)
    begin
       // Implement custom logic to authenticate user based on UserName and Password
      // For example, go to the database, check credentials and then create an user
      // identity with all permissions (claims) for this user
      User := TUserIdentity.Create;
      User.Claims.AddOrSet('UserName').AsString :=UserName;
      User.Claims.AddOrSet('UserPassword').AsString :=UserPassord;
    end,
    'My Server Realm'
));

Module.UserName:='';
Module.Password:='';

// Uncomment line below to enable CORS in the server
//Module.AddMiddleware(TCorsMiddleware.Create);

// Uncomment line below to allow compressed responses from server
//Module.AddMiddleware(TCompressMiddleware.Create);

SparkleServer.AddModule(Module);

SparkleServer.Start;
end;

How can i send back the string "User not found" ?
Also In documentation i found "Authorizing Requests" with procedure TProtectedHelloModule.ProcessRequest(const C: THttpServerContext);
but i did not understand how use it.
Now even if the username and/or userpassword are wrong RDB1.Connected always return true and the db is connected.

Excuse me for this "trivial" matter ...

Thank's for your patience
Regards
Daniele
Back to Top
Wagner R. Landgraf View Drop Down
TMS Support
TMS Support
Avatar

Joined: 18 May 2010
Posts: 2389
Post Options Post Options   Quote Wagner R. Landgraf Quote  Post ReplyReply Direct Link To This Post Posted: 05 Sep 2019 at 1:30pm
Here is more or less what you have to do:

  Module.AddMiddleware(TBasicAuthMiddleware.Create(
    procedure(const UserName, Password: string; var User: IUserIdentity)
    begin
      if GoToDatabaseAndCheckIfUserExists(UserName, Password) then
      begin
        User := TUserIdentity.Create;
        User.Claims.AddOrSet('UserName').AsString :=UserName;
      end
      else
        User := nil;
    end,
    'My Server Realm'
  ));

  Module.AddMiddleware(TAnonymousMiddleware.Create(
    procedure(Context: THttpServerContext; Next: THttpServerProc)
    begin
      if Context.Request.User = nil then
      begin
        // no user authenticated, return error 401
        Context.Response.StatusCode := 401;
        Context.Response.ContentType := 'text/plain';
        Context.Response.Close(TEncoding.UTF8.GetBytes('User not authenticated'));
      end
      else
        Next(Context);
    end
  ));

The only part you need to implement yourself is the
GoToDatabaseAndCheckIfUserExists
, that's up to your business logic to check if the user is valid or not based on your criteria. I hope it helps.
Back to Top
Fare' Daniele View Drop Down
Senior Member
Senior Member
Avatar

Joined: 30 Dec 2015
Posts: 153
Post Options Post Options   Quote Fare' Daniele Quote  Post ReplyReply Direct Link To This Post Posted: 06 Sep 2019 at 9:00am
Good morning Wagner,
yesterday evening i tried your suggested code .... and all works very good.
Studing your code i miss a lot of it (i.e. the second Module.AddMiddleware), now is a little clear and i can go ahead with the project.
Thank you, again, for your help and patience.

Regards
Daniele
Back to Top
 Post Reply Post Reply

Forum Jump Forum Permissions View Drop Down