#1 Re: mORMot 1 » How to use JWT token on the client side » 2018-03-05 18:20:25

ab, one last question, is this the correct way to read the payload?

var
  Payload: Variant;
  Data: TDocVariantData;
begin
  if TJWTAbstract.VerifyPayload(Token, '', 'mormot', '', nil, nil, @Payload) <> jwtValid then
    raise EError.Create('Invalid token');

  Data := TDocVariantData(Payload);

  Value := Data.S['key'];

#2 Re: mORMot 1 » How to use JWT token on the client side » 2018-03-03 14:33:14

ab, don't know if you already noticed but now the SynCrypto unit has a hint:

SynCrypto.pas(14221) Hint: H2443 Inline function '_Json' has not been expanded because unit 'System.Variants' is not specified in USES list

#3 Re: mORMot 1 » How to use JWT token on the client side » 2018-03-03 13:32:46

ab wrote:

So you want to decode the token payload on the client, without knowing the secret key?

The Verify() method can do this - even if since you don't know the secret, it will return "invalid".
Therefore, it is not the most convenient way...

I've just added a new Payload optional parameter to TJWTAbstract.VerifyPayload() so that you may be able to easily check the payload content as a TDocVariantData.
See https://synopse.info/fossil/info/3e0909f6e2

Exactly, I store some info which interests the client on the payload. The VerifyPayload() is now perfect. Thanks.

#4 Re: mORMot 1 » How to use JWT token on the client side » 2018-03-02 20:57:51

Figure how to send the token:

  FRestClient.SessionHttpHeader := HEADER_BEARER_UPPER + Token;

But I'm still not sure about the correct way to read the payload on the client.

#5 mORMot 1 » How to use JWT token on the client side » 2018-03-02 20:20:10

fabioxgn
Replies: 8

I'm implementing JWT authentication in my project, and previously I was using a third party JWT library and storing the token on a cookie so it was transparent on the client side as the cookie was sent on every request.

Now I've replaced the JWT implementation on the server side and everything is OK.

But I can't figure out how to send the token back to the server after I get it on the client side, right now what I have is:

- Client sends login/password to server
- Server authenticates and returns the token (string)

This is working just fine, but on the client I need to read the token payload, so what I did was something like this:

FToken := LoginService.Login(AUserName, APassword);

if TJWTAbstract.VerifyPayload(FToken, '', 'Monde', '') <> jwtValid then
    raise EValidationError.Create('Invalid Token.');

Token := TJWTHS256.Create('', 0, [], []);
try
  Token.Verify(FToken, JWT); // Is this the only way to read the payload values? 

  UserID := JWT.data.S['uid'];
finally
  Token.free;
end;

Is this the correct way to read the token's payload on the client side?

Now, how do I send the token on the Header now so the server can authenticate the client?

#6 mORMot 1 » Payload value in JWT token returns null if the value has a { character » 2018-03-02 17:22:45

fabioxgn
Replies: 1

This token for example:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiJ7MUNDQTMzNkQtQTc4Ri00RUI2LUI3MDEtMURCOEU3NDlCRDFGfSIsInNjbSI6InRlc3RzIiwiYWRtIjp0cnVlLCJpc3MiOiJNb25kZSIsImlhdCI6MTUyMDAxMDA5OSwiZXhwIjoxNTIwMDEzNjk5LCJqdGkiOiIxMTcyNjlCNDY3NjkyNUREMjE2NDNBODAifQ.HpBbP6Dk9TiHSd3ZZ3u9QZUr_dAAhsuf_qe3cuc8j8c

in the JWT debugger it is valid and returns:

{
  "uid": "{1CCA336D-A78F-4EB6-B701-1DB8E749BD1F}",
  "scm": "tests",
  "adm": true,
  "iss": "Monde",
  "iat": 1520010099,
  "exp": 1520013699,
  "jti": "117269B4676925DD21643A80"
}

But when I use the verify method, it returns null for the "uid" payload:

('uid', 'scm', 'adm'), ('null', 'tests', 1), 3))

I've tried to debug a little bit and looks like that the { is making the JSON parser skip the uid value.

#7 Re: mORMot 1 » TServiceCustomAnswer different behavior after update » 2017-10-20 10:51:11

ab wrote:

I'm not sure I understand exactly the behavior you are reporting...

Could you be more specific?

Do you need any more info? Thanks.

#8 Re: mORMot 1 » TServiceCustomAnswer different behavior after update » 2017-10-18 19:23:50

if you have 2 methods in an interface based service, like:

    function StringMethod: string;
    function CustomMethod: TServiceCustomAnswer;

If you raise an exception on both methods, the behavior on the client is different:

The method StringMethod will raise an exception on the client, and I can handle it like:

try
  Response := service.StringMethod;
except
  // If something goes wrong in the server, this code will be executed
end

But with a TServerCustomAnswer the exception isn't raised anymore (it was in previous versions) and now I have to handle it like this:

// This method will never raise an exception, even if the connection is down
Response := service.CustomMethod;
if Response.Status <> HTTP_SUCCESS then
  // handle the Response

#9 mORMot 1 » TServiceCustomAnswer different behavior after update » 2017-10-18 16:56:05

fabioxgn
Replies: 3

I was using an old version of mORMot and had 2 methods wich returned a TServiceCustomAnswer (for performance purposes, as they return a lot of data), now I've updated mORMot and the behavior changed for these methods.

When I return a Integer for example in an interface based method service, if something goes wrong on the server, an exception is raised on the client side.

I have a lot of handling for these exceptions, like handling disconnects, proxy errors, expired token, etc.

And now the 2 methodos which returns TServiceCustomAnswer doesn't raise exceptions anymore and I'll have to handle it differently from the other methods.

I agree that raising exceptions isn't REST friendly, but having 2 different behaviours based on the method return is very confusing (took me some time to figure it out) and in my case will result in some duplicated code to handle errors differently in these methods.

Is there some way to maintain the old behavior for theses methods?

#10 Re: mORMot 1 » Allow configuring Proxy Username/Password on WinINet » 2016-03-16 16:57:41

ab, yes but the credentials are not stored on the internet explorer config. If you have a proxy server with authentication you have to provide the username/password to WinINet.

#11 Re: mORMot 1 » Allow configuring Proxy Username/Password on WinINet » 2016-03-16 16:28:15

After doing some tests, I was able to get my application to asks for the credentials. InternetSetOption didn't work for me, possible because I was doing something wrong.

I think that this approach would be better for the user as it asks for the credentialls and stores it on Windows.

I overwrote the WinInet classes, something like this:

procedure TProxyWinInet.InternalSetClass;
begin
  inherited;
  fRequestClass := TWinINetProxyAuth;
end;

function TWinINetProxyAuth.InternalRetrieveAnswer(var Header, Encoding, AcceptEncoding, Data: SockString): Integer;
begin
  Result := inherited;
  if Result = HTML_PROXYAUTHREQUIRED then
  begin
    FRetry := InternetErrorDlg(Application.Handle, fRequest, ERROR_INTERNET_INCORRECT_PASSWORD,
      FLAGS_ERROR_UI_FILTER_FOR_ERRORS or
      FLAGS_ERROR_UI_FLAGS_GENERATE_DATA or
      FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS,
      Pointer(nil^)) = ERROR_INTERNET_FORCE_RETRY;
  end;
end;

function TWinINetProxyAuth.Request(const url, method: SockString; KeepAlive: Cardinal; const InHeader, InData,
  InDataType: SockString; out OutHeader, OutData: SockString): Integer;
begin
  repeat
    FRetry := False;
    Result := inherited;
  until not FRetry;
end;

This works and stores the credentials on Windows, but it would be nice if it was done automatically.

#12 mORMot 1 » Allow configuring Proxy Username/Password on WinINet » 2016-03-16 13:24:01

fabioxgn
Replies: 3

I'm using WinINet because I have several users which uses proxy and it "just works" if the user have the proxy configured on Internet Explorer.

But when the proxy server requires authentication, it is necessary to configure it on the WinINet connection and I didn't find out how to do it. Is it implemented?

If not, is it possible to add this option? The microsoft documentation says you have to call InternetSetOption to do this: https://msdn.microsoft.com/en-us/librar … s.85).aspx

Here is the Proxy section:

Proxy Authentication
When a client attempts to use a proxy that requires authentication, the proxy returns a 407 status code message to the client. In that message, the proxy should include one or more Proxy-Authenticate response headers. These headers include the authentication methods available from the proxy. WinINet chooses the first method it recognizes.

The InternetErrorDlg function can be used to obtain the user name and password data from the user, or a customized user interface can be designed.

A custom interface can use the InternetSetOption function to set the INTERNET_OPTION_PROXY_PASSWORD and INTERNET_OPTION_PROXY_USERNAME values and then resend the request to the proxy.

I noticed that TWinInet already sets some params on connect:

procedure TWinINet.InternalConnect(ConnectionTimeOut,SendTimeout,ReceiveTimeout: DWORD);
var OpenType: integer;
begin
  if fProxyName='' then
   OpenType := INTERNET_OPEN_TYPE_PRECONFIG else
   OpenType := INTERNET_OPEN_TYPE_PROXY;
  fSession := InternetOpenA(Pointer(fUserAgent), OpenType,
    pointer(fProxyName), pointer(fProxyByPass), 0);
  if fSession=nil then
    raise EWinINet.Create;
  InternetSetOption(fConnection,INTERNET_OPTION_CONNECT_TIMEOUT,
    @ConnectionTimeOut,SizeOf(ConnectionTimeOut));
  InternetSetOption(fConnection,INTERNET_OPTION_SEND_TIMEOUT,
    @SendTimeout,SizeOf(SendTimeout));
  InternetSetOption(fConnection,INTERNET_OPTION_RECEIVE_TIMEOUT,
    @ReceiveTimeout,SizeOf(ReceiveTimeout));
  fConnection := InternetConnectA(fSession, pointer(fServer), fPort, nil, nil,
    INTERNET_SERVICE_HTTP, 0, 0);
  if fConnection=nil then
    raise EWinINet.Create;
end;

It would be nice if it could set the Proxy Auth too.

#13 mORMot 1 » Rollback a transaction if client timeout » 2016-02-25 21:08:16

fabioxgn
Replies: 8

I'm implementing an interface based service and would like to run each request in a database transaction.

My first attempt was to use an interceptor, it worked, something like this:

procedure TRESTServer.TransactionInterceptor(Sender: TServiceMethodExecute; Step: TServiceMethodExecuteEventStep);
begin
  case Step of
    smsBefore: BeginTransaction;
    smsAfter: Commit;
    smsError: Rollback;
  end;
end;

The problem is that if the client timesout and is not able to process the result, the `smsAfter` is executed and the transaction is commited.

From what I've noticed in the code, when the timeout occurs the exception is handled in this code:

on E: Exception do
            // handle any exception raised during process: show must go on!
            if not E.InheritsFrom(EHttpApiServer) or // ensure still connected
               (EHttpApiServer(E).LastError<>HTTPAPI_ERROR_NONEXISTENTCONNECTION) then
              SendError(STATUS_SERVERERROR,E.Message,E);

The problem is that in the case of client disconnect, it just ignores the error and I can't rollback the transaction.

Is it possible to do this somehow?

#14 Re: mORMot 1 » CurrentServiceContext.Request.Redirect not working, gets overwritten » 2016-02-23 13:49:23

ab wrote:

This is not how it works.
You can't use CurrentServiceContext to change the execution at runtime, like this.

Interface-based services are NOT meant to support all HTTP details.
They are made to implement client/server SOA process.

If you use an interface-based service, and expect HTTP level customization of the returned content, define your method to return a TServiceCustomAnswer record.
Then just put the HTTP header redirection to the TServiceCustomAnswer.Header result of your method.
And it will work as expected.

If you want to have full control of the returned content, use a method-based service.
Then do not use CurrentServiceContext, but directly the Ctxt parameter of the implementation.

Didn't know that, thanks.

#15 mORMot 1 » CurrentServiceContext.Request.Redirect not working, gets overwritten » 2016-02-23 13:14:39

fabioxgn
Replies: 3

I'm trying to make a method which will redirect, and the result status and headers are overriden after checking if the Answer is TServiceCustomAnswer.

My method just returns a string (also tested with a procedure) and I'm redirecting using the following code:

CurrentServiceContext.Request.Redirect(URL);

But in this point, the Status code and OutHead are overriden:

        if exec.ExecuteJson([instancePtr],Ctxt.ServiceParameters,WR,Ctxt.ForceServiceResultAsJSONObject) then begin
          Ctxt.Call.OutHead := exec.ServiceCustomAnswerHead;
          Ctxt.Call.OutStatus := exec.ServiceCustomAnswerStatus;
        end else begin

At this point Ctxt.Call.OutHead and Ctxt.Call.OutStatus are correct but it gets set to empty string as the ServiceCustomAnswer stuff is blank.

Also, it would be nice to specify the HTTP Status code in the Redirect method, instead of Permanent True/False, I'd like to use 302 (Found).

Is this a bug or am I doing something wrong?

#16 Re: mORMot 1 » Disable logging of environment variables on server startup » 2016-02-16 11:32:44

ab wrote:

Putting sensitive information in environment variable is VERY unsecure.
Why not just run the application with another user?

Anyway, I have added the new TSynLogFamily.NoEnvironmentVariable property for you.
See http://synopse.info/fossil/info/df3a670d33

Thanks!

#17 mORMot 1 » Disable logging of environment variables on server startup » 2016-02-15 16:44:07

fabioxgn
Replies: 2

I'm forwarding the logs to papertrail and there are some sensitive information on environment variables.

By default mORMot is logging all env vars, is there a coniguration to disable it?

#18 Re: mORMot 1 » Stateless authentication using cookie » 2016-02-15 16:41:54

edwinsn wrote:

I'm not able to help, but I'm interested in this topic.

I've implemente this using jwt.io, please see: http://synopse.info/forum/viewtopic.php?id=3167

#19 mORMot 1 » Implement custom Auth without sessions » 2016-02-10 16:39:36

fabioxgn
Replies: 1

I'm trying to implement a custom authentication (based on the JWT standard http://jwt.io/) and looking at the mORMot code I think it's not possible to implement it without "touching" the mORMot sessions, which I will not have.

So far what I was able to do was:

- Create my custom authentication method
- Register it and set BypassAuthentication = true on the service
- The client calls this auth method first to get a token, then send this token on every request
- Then I override TSQLRestRoutingREST.Authenticate method to validate the token

It works, but it doesn't feel "right".

Also I can't call my interface IAuth because it conflicts with the one that mORMot registers. Looking at the code, it is implemented by TSQLRestServer.Auth (which is not virtual) and call the TSQLRestServerAuthentication.Auth which relies on session.

It would be nice if I could override TSQLRestServer.Auth or if there was a base class (simpler than TSQLRestServerAuthentication) which didn't rely on sessions that I could use to implement this kind of Auth without overriding a lot of stuff.

Does it make sense?

#20 Re: mORMot 1 » Fastest way to return data from dataset in interface based service » 2016-02-07 00:09:03

ab wrote:

Yes, the HTTP server check the "Content-Type:" header value.
If it is JSON or TEXT, it would compress the data.
If it is BINARY_CONTENT_TYPE_HEADER, it is not compressed.

Which kind of client do you use?
You could simply compress the result.content BEFORE sending it.
See in SynLZ.Pas and SynZip.pas: there are ready-to-use functions working with RawByteString variables.


In this case all the clients will be Delphi clients, as this particular method is a TClientDataSet specific method.

I guess that it wouldn't make a diffence if I just use the TEXT_CONTENT_TYPE_HEADER instead of compressing "by hand", as  the content would be converted To RawByteString on both options, is that correct?

Also we have 1500+ integration tests, which opens the datasets, save stuff on the database, etc. Not a single test failed using TEXT and the tests run 15s faster: 4m30s using text encoding instead of 4m45s using binary.

So if I'm not missing something and if in this case with a Delphi client only, my conclusion is that using a TServiceCustomAnswer with TEXT_CONTENT_TYPE_HEADER is the fastest option, right?

It would be even faster with a remote server as the content length is less than 30% (22% in this 5k records dataset) of the original (binary) length.

#21 Re: mORMot 1 » Stateless authentication using cookie » 2016-02-06 23:57:01

mpv wrote:

In fact your schema security level is the same as for already implemented Basic authentication. Even if you calculate HMAC, If I intercept any network package and got a session cookie I can do anything without knowledge of actual password. So the only way is to use HTTPS. Even in this case I can replace the SSL certificate (like a China Create Firewall or Kazakhstan do) and got your cookie.
In our productions we use mORMot secure RESTful authentication (modified a little) and either a load balancer what guaranty all packages from the same IP address go to the same server (almost all Cisco hardware LB can do this) or set up a DDNS  and resolve a server host name to the different IP address depending on caller IP.

My first option was to use http basic and save the user id in a cookie, but as I'm using a Delphi client, that meant storing the credencials on the client executable (as the user have a different login in the database), so I was thinking that this approach would be better, as if the user authenticate on the database once, which would be the the first thing that the Delphi client would do, before allowing the user in and then after that, any node would trust him.

We are using https, and we are using Amazon ELB autoscalling features, so at a give time there might be 1 or 10 servers (servers will start and terminate based on the current load), so I'm trying to avoid having any state at all on the server to avoid making the user login more than once.

I don't know anything about this kind of  SSL certificate replacement, can it be avoided or, even with https a MIM attack could happen?

#22 Re: mORMot 1 » Fastest way to return data from dataset in interface based service » 2016-02-05 20:37:29

ab wrote:

You may add the value within the headers, e.g.

  result.Header := FormatUTF8(BINARY_CONTENT_TYPE_HEADER+#13#10'RecsOut: %',[RecsOut]);
  SetString(result.Content, PAnsiChar(Buffer), Length(Buffer)); 

Or you may put the value at first place in the output binary:

  result.Header := BINARY_CONTENT_TYPE_HEADER;
  SetLength(result.Content, Length(Buffer)+4); 
  PInteger(result.Content)^ := RecsOut;
  move(Buffer[0],result.Content[5],length(Buffer));

Thanks.

I did some tests with it, and when using the binary encoding, the data isn't compressed.

I did some tests with a dataset with 5.5K records, and it the content was 1.6mb. Then I changed the encoding to TEXT and it got down to 350kb.

In this case with large datasets, I think that compressing would be better, but I'm not sure about small datasets, or if it's going to give me a problem of some kind.

Any thoughts?

#23 mORMot 1 » Stateless authentication using cookie » 2016-02-05 18:59:05

fabioxgn
Replies: 5

I'm trying to implement a stateless authetication, which by stateless I mean: no in memory session and nothing on server (apart from the first authentication) and I'd like to know if there is already something like this implemented.

What I need is a flow like this:

- User calls the login method
- Server auth him using the database
- Saves his ID and some other info in a cookie
- Then create a HMAC "hash" using a secret key + the data on the cookie and save this in the cookie
- After this, every other request he will send this cookie and the server will recompute the data in the cookie to match the "hash"

This is something like amazon does with pre-authenticated URLs, but I'm storing in a cookie.

Is there something like this already implemented in mORMot?

AFIAK all the authentication methods saves the session on server, so with a load balancer mixing requests between nodes the user would have to authenticate in all nodes, which I want to avoid.

#24 Re: mORMot 1 » Fastest way to return data from dataset in interface based service » 2016-02-05 12:43:56

ab wrote:

AFAIK:
- TBytes would return an array of bytes, e.g. (130,100,65,10,...)
- RawByteString would return a Base-64 encoded string  "pbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlci..."
So RawByteString would definitively use much less data.

About performance, we designed some base-64 encoding/decoding functions in SynCommons.pas, which are very efficient (much faster e.g. than Delphi RTL/Indy alternatives).
But the ratio of base-64 output bytes to raw input bytes is 4:3 (there is a 33% overhead).
As such, the best idea, in case of huge blob content, would be to use a TServiceCustomAnswer, since there won't be any Base-64 encoding.

Thanks, I'll try to use TServiceCustomAnswer.

Can you give me any tips about how can I send back that "RecsOut" along with the TBytes content in the TServiceCustomAnser?

It is an integer value, but I don't have much experience working with this kind of raw content. Is it possible to add a field to TServiceCustomAnswer? Or do I have to concatened this integer value with the content?

#25 mORMot 1 » Fastest way to return data from dataset in interface based service » 2016-02-05 10:13:37

fabioxgn
Replies: 6

I'm migrating a project from datasnap to mORMot and we override some datasnap funcionallity, but keeping it short, I'm overriding the GetRecords of the dataset on client and server side.

In my first implementation I was returning TBytes from the server, but I noticed that it was a little slow and was consuming a lot of time to marshall the JSON, then I did some tests and tried 2 new things:

1: return TServiceCustomAnswer, but I have a var parameter. So I'd have to write a custom "packet" to return it alongside the data.
2: return RawByteString instead of TBytes, noticed a big improvement on the content length maybe because of better compression.

Here is a sample code of what I'm doing right now (with RawByteString):

function TRESTServerMethods.GetRecords(const ProviderName: string; const Count: Integer; var RecsOut: Integer; const
    Options: Integer; const CommandText: string; const Params: TArray<TArray<Variant>>; const Where: string):
    RawByteString;
begin
    Buffer := VariantArrayToBytes(Provider.GetRecords(Count, RecsOut, Options, CommandText, OleParams, OwnerData));
    SetString(Result, PAnsiChar(Buffer), Length(Buffer));
end;

Also I noticed (using manual testing, did no benchmark) that between TServiceCustomAnswer and JSON with RawByteString there is no to little improvement, but from TBytes to RawByteString there's a big improvement, mainly in content length.

Here's a comparison:

TBytes:
Total time: 350ms
Length: 4211661
Server time: 246.371

RawByteString
Total time: 260ms
Length: 2197186
Server time: 227.480

Total time is measured on the Client Side running locally, it is the total time to open the dataset with 5K+ records. Server time is what mORMot prints on the log for the request.

Notice that the content length using RawByteString é almost 50% of TBytes.

So, my question is:

Is this the fastest way to return this kind of data? Any suggestions?

#26 Re: mORMot 1 » Use proxy with TSQLHttpClientWebsockets » 2015-12-14 19:02:07

Exactly, the problem is a corporate proxy not reverse proxy.

#27 Re: mORMot 1 » Use proxy with TSQLHttpClientWebsockets » 2015-12-14 14:33:22

ab, so there is no way to use Websockets with proxy at this time, right?

#28 Re: mORMot 1 » Use proxy with TSQLHttpClientWebsockets » 2015-12-14 13:03:20

ab, thanks, but in my tests the TCrtSocket is not even trying to use the proxy, it is trying to make a direct connection.

I opened a proxy server on my host and configured it on a VM, other http requests pass by the proxy server, but the TCrtSocket tries to open a direct connection, is it expected?

#29 mORMot 1 » Use proxy with TSQLHttpClientWebsockets » 2015-12-14 11:42:27

fabioxgn
Replies: 19

Is it possible?

I've implemented a callback method using TSQLHttpServer and Websockets but as I can tell from my tests and the code, the TSQLHttpClientWebsockets uses a TCrtSocket derived class which does not allow proxy configuration.

I tried to set the proxy in WinHTTP using

netsh winhttp import proxy source=ie

but this class is not using it.

Can I use a proxy server with the TSQLHttpClientWebsockets class?

#30 Re: mORMot 1 » Websocket server authentication » 2015-11-30 11:57:52

Force the service to be available only via websockets for me is enough, how can I do that?

#31 Re: mORMot 1 » Websocket server authentication » 2015-11-25 12:16:21

Any thoughts about this? Or any way to allow only my Delphi client to call the server methods?

#32 Re: mORMot 1 » Websocket server authentication » 2015-11-20 18:11:18

ab wrote:

Why not just use Websockets in our binary format, with encryption and compression enabled?

That's what I'm doing, but I can make requests using HTTP to urls like: root/NotificationService.Notify and it is executing the methods.

I might be doing something wrong, here's my current code based on the chat sample:

    Server := TSQLRestServerFullMemory.CreateWithOwnModel([]);
    Service := Server.ServiceDefine(TNotificationService, [ICallBackService], sicShared).SetOptions([], [optExecLockedPerInterface]);
   Service.ByPassAuthentication := true;


    HttpServer := TSQLHttpServer.Create('8888', [Server], '+', useBidirSocket);
    HttpServer.WebSocketsEnable(Server, 'my_key');
    writeln('Press [Enter] to quit'#13#10);
    readln;

I might be confusing things as I don't know exactly how websockets work, but as far as I understand this is exposing my interface methods using http on http://localhost:8888/root/ is it not? If I make a request in the browser it hits my code.

#33 mORMot 1 » Websocket server authentication » 2015-11-20 16:39:58

fabioxgn
Replies: 5

I'm trying to implement a websockets only notification server which will only receive new notifications and broadcast to all connected clients. I'm using the chat sample code as example: https://github.com/synopse/mORMot/blob/ … er.dpr#L55

But I'm not sure how to implement security on it, I tested with the example code and I can access the methods using http, ex: if I make a GET request on http://localhost:8888/root/NotificationService.Notify it returns result: [].

I was able to add http authentication with:

TSQLRestServerFullMemory.CreateWithOwnedAuthenticatedModel([], 'user', TSQLAuthUser.ComputeHashedPassword('pass'));

But can I run the websocket and https together? As using this method the username and hashed password are exposed on the URL.

What I'd like to do is allow websocket only connection to authenticated clients only (the clients will be all Delphi applications, both the application which notifies and the clients).

Which is the recommended way to implement that?

#34 mORMot 1 » TServiceCustomAnswer Status is not returned to Delphi client » 2015-11-06 17:35:29

fabioxgn
Replies: 1

I have a simple method, like:

  IServerMethods = interface(IInvokable)
    function MyMethod(const data: string): TServiceCustomAnswer;
  end;

The method implementation is like:

try
  SomeMethod();
except
  Result.Content := 'server error';
  Result.Status := HTML_SERVERERROR;
end;

When I use it with a TSQLHttpClient the Status value does not return to the client, the Content and Header is OK, but the Status isn't initialized.

I was expecting that the Status would be returned to the client, so I could use it like:

Response := DoRequest;
if Response.Status = HTML_SERVERERROR then
  ....

Is the Status not expected to be filled on the client? I think it makes sense for it to get to the client, looks like a bug to me.

Board footer

Powered by FluxBB