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
Hello Daniele,
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
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
));
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.
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