JWT Auth demo


I'm a novice with TMS XData and have several questions:

1. What I should change to use one server for Authentication and Data exchange?
2. How to prevent showing any data with internet browsers and use program only connections?
3. How to make this demo ready for TMS Echo usage? This should be 2 servers, one is global and the second is local and the client should connect to the local server only? And the local server should connect to the global server?

Hello Alex,

1. If you actually just add all units (except the main form of course) in the same project, it should work already. For example, in your ApiServer.project add units from AuthServer: AuthServerModule.pas, LoginService.pas, LoginServiceImpl.pas.

2. You can't prevent that. Your server will be accessible through HTTP, any client that can connect via HTTP will be able to reach your server. Of course, by using authentication you can prevent users from unauthorized access. Can you explain what is your concern in this specific case?

3. You can have different logins and secrets for local and global server. This way, a token issued for the local server will only be accepted by the local server and the same applies for global server. What makes one server accepts a token or not is the secret.
1. Yes, this is will work in a single project, but there is will be 2 servers inside one exe file. My question was about the possibility to create one server for auth and data exchange

2. Currently, I'm mORMot customer and all that I need that communicate my server and client parts of my software with authorization and data exchange and not allow any third party software to connect to the server. And also this communication must be encrypted. In mORMot I can do than using one command by including my own secret key

3. My question is not about different logins for local and global servers. My question about the ability to work offline. I need to make my client works offline (data reading and creation) and services (authorization) should work offline too. Sure not all data can be available in offline mode, this is not critical, but the client should work offline and created data must be integrated into the global server when it will be online
  1. Isn't it then exactly what the demo shows? Two exe files with two different servers? I don't understand then what you want to achieve?

    2. What I mean is, the browser is just like any other client. If some JS code in your browser get access to authentication data, it can access your server, like in any rest server. Of course you can protect XData servers from unauthorized access, by adding the JWT middleware and protecting it. We don't do custom encryption, if that's what you're asking. We think it's best to rely on HTTPS for that.

    3. Isn't that what Echo is for? It's a data replication system, the idea is that you work with your local database (offline) and then at some point when you have connection, you replicate (send and receive) data. I also don't understand what you are asking, exactly, since the TMS Echo demo also shows exactly that?
My questions may be too simple, but it’s important for me to understand the basic principles and ideas on how to work with XData
1. No, this is not entirely true. My question is in other words: in the example, we have 2 servers that are available on "http://+:2001/tms/api" and "http://+:2001/tms/auth". But is it possible to create one server, which will be available at the address "http://+:2001/tms" and will perform both parts: work with the database and with services?
2. I'm understand about encryption and authorization. Another one question: Is it possible to add auth tokel for services like for data processing? Something like this:

  XClientAuth.Uri := 'http://localhost:2001/tms/api';
  XClientAuth.HttpClient.OnSendingRequest :=
    procedure(Req: THttpRequest)
      if Token <> '' then
        Req.Headers.SetValue('authorization', 'Bearer ' + Token);

and if yes, how to get IUserIdentity from service method to process auth token?
3. Ok, If I will have the global server only, without local server what can you tell about work with auth service in offline mode? What can you recommend to realize such functionality?
  1. Isn't it what you have? You have two "modules" answering on addresses /tms/api and /tms/auth. Isn't it the same as "one server" at /tms that does both? 

    2. Yes, that's how you send the token from client. And to get the user identity you use something like this:

procedure TMyService.DoSomething;
  User: IUserIdentity;
  User := TXDataOperationContext.Current.Request.User;
  // Here you have the IUserIdentity from the token sent by the client

More details are described here: http://www.tmssoftware.biz/business/xdata/doc/web/authentication_example_using_j.html

3. The offline client will save data in local database. When there is a connection, it will connect to the global server using the authentication credentials and send the modified data to it.

Thank you, 1 and 2 understand now, but about 3:

II'm don't get an answer to the question about authorization for the client in offline mode. Without a local server this is impossible, I think?

You will not need authentication when in offline mode, because your application will not connect to the server when in offline mode. It will save data directly to the database.

My software have authentication on the start, without authentication customer can't work

Ok, but what is he authentication to? Your software authentication doesn't necessarily need to be the same as the server API authentication. 

Based on the software authentication server part provide access to database operations (view, edit, delete, etc.) and in my situation is it the same. Currently, all functionality works based on Services of mORMot and now I'm trying to adapt it based on database authentication.

I don't know your software and how you use it with mormot. It's hard to give such broad advice without specific questions or specific details. 
Basically if you want to use TMS Echo, you save data offline in local database and then you later synchronize it with some server (either in local network or internet) via XData. You require authentication to the XData server of course. If you want to require authentication to your local database, it's up to your system, but that doesn't need to be the same authentication for the server. 

I'm need to restrict adding new entities to the database:

procedure TServerModule.XDataServerEntityInserting(Sender: TObject; Args: TEntityInsertingArgs);
  User: IUserIdentity;
  IsAdmin: Boolean;
  User := Args.Handler.Request.User;
  IsAdmin := (User <> nil) and User.Claims.Exists('admin') and User.Claims['admin'].AsBoolean;

  // How to allow inserting for Admin only here?

And if we have this above part of code on the server, how-to will be added data, which was added by the client (without admin rights) to the database, when the client part of the software was offline? 

An application that uses Echo has a different paradigm than an application that uses a "normal" XData REST Server. The code you pasted above is for a regular XData server that provides entity inserting capabilities via an endpoint (POST /customers/ , for example).

Echo doesn't work like that, it doesn't use those XData endpoints for replication.
Echo is "just" a way to replicate data between databases. You have database A and database B, and data is replicated between them. Note that "A" can be a local database in the user computer, or in the local network, or even also a database under a XData server that might be in the local network. All Echo does is replicate data from A to B.

So for example, you can have the following scenarios:
1. Client saves data directly in an SQLite database (A) in the same computer/mobile device
2. Client saves data directly in a Postgres database (A) in the same local network
3. Client saves data through endpoints of a XData server located in the local network, which in turn saves data in a database (A) in the same computer
4. Client saves data though endpoints of a XData server located in the cloud, which in turn saves data in a database (A) in the same computer.

In all four scenarios above, Echo can be used to replicate data from database "A" to another database "B". How you want to setup it and how you want to protect it is up to you.
When loading data in database "B", Echo uses Aurelius to do that, and you could still use Aurelius events like OnInserting, OnUpdating, OnDeleting to intercept such operations and prevent them to happening if the data is not consistent (like unauthorized). But in a Echo system I wouldn't recommend this, because in the end, your users will be saving data in the local database thinking they are doing ok, and then you will reject those changes when replicating to database B. You will end up with a lot of replication errors that you will have to handle, and if you want to notify your users about all those errors this will get really complex. The preferable approach for user point of view is that you reject invalid data when user is still entering them, in the User Interface.

I'm understand you now, and I think, for my software will be this scenario: customers works with Global DB. Switching to offline mode must be manual and during this switching Local DB will be created (replica of the Global DB with some restrictions)