#1 2025-08-18 08:52:43

squirrel
Member
Registered: 2015-08-13
Posts: 162

WSS Authentication

Is there currently a way to ensure that https can only be upgraded to wss connections for already authenticated/logged in  users and then to be able to link the wss requests/connectionids to the specific logged in user?

Offline

#2 2025-08-18 09:15:18

flydev
Member
From: France
Registered: 2020-11-27
Posts: 112
Website

Re: WSS Authentication

If it helps you find the way, on my side, I use TWebSocketProtocol.UpgradeBearerToken for that: read more there

Online

#3 2025-08-18 09:33:54

squirrel
Member
Registered: 2015-08-13
Posts: 162

Re: WSS Authentication

My initial thought was to define a protocol that is similar to the http uri signing, which would keep things standard for third parties.  Then wss commands can be sent using a signing format similar to this:

{
    "command": "/root/mycommand?session_signature=same as calculated as if command was a uri",
    "parameters": {}
}

But then I would need to somehow pass the command to the rest server for the authentication to be checked.  The advantage would be that, if a user logs out from the https server, the wss functions will also fail.  So no additional session management would have to be done.

Offline

#4 2025-08-18 12:45:41

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 15,159
Website

Re: WSS Authentication

You can set the OnBeforeBody event handler to check the URI and reject it.

But I may add something more integrated with the TRestServer instance.

Offline

#5 2025-08-18 12:49:02

flydev
Member
From: France
Registered: 2020-11-27
Posts: 112
Website

Re: WSS Authentication

to check the command you show you could do it in InBeforeBody, you could validate specific upgrade in flags hsrConnectionUpgrade.

edit: what @ab just said

Last edited by flydev (2025-08-18 12:49:38)

Online

#6 2025-08-18 12:52:52

squirrel
Member
Registered: 2015-08-13
Posts: 162

Re: WSS Authentication

Thanks @ab.  How would I send the uri to TRestServerAuthenticationDefault for verification?  Is there a function I am missing that takes a uri and returns a session?  I have searched, but may have missed it.

Does TWebSocketAsyncServer have an OnBeforeBody property?

Offline

#7 2025-08-18 13:15:04

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 15,159
Website

Re: WSS Authentication

This is indeed the problem.

There are several issues:

1) The TRestHttpServer can handle several TRestServer instances, with a complex redirection system which may involve THttpServerRequestAbstract.Host value.
So it is not easy to redirect to the proper TRestServer. We could restrict to a single server.

2) The URI authentication is using a TRestServerUriContext instance, which does not exist yet when the WebSockets upgrade is done.

3) The URI authentication depends on the actual URI used.

So I guess it would need to add a dedicated method to TRestServerAuthentication...
Which seems pretty much complex for such a task.

Offline

#8 2025-08-18 13:26:46

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 15,159
Website

Re: WSS Authentication

Note that you have an alternative to OnBeforeBody.

You can just set an aOnWSUpgraded: TOnWebSocketProtocolUpgraded callback as parameter to WebSocketsEnable().
Then, don't use the mORMot URI signing, but a custom challenge, either in the URI or in the bearer.
Note that putting a signature in an URI should always be time-limited to avoid replay attacks.

Offline

#9 2025-08-18 17:24:24

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 15,159
Website

Re: WSS Authentication

Please try with
https://github.com/synopse/mORMot2/commit/1e3a67727

There is now a new rsoWebSocketsUpgradeSigned option which will require either a HTTP bearer or a specific URI parameter when upgrading to websockets.
You just supply the URI or the bearer from a safe service method, then use this value to upgrade.

On the client side:
https://github.com/synopse/mORMot2/commit/f322cc420

My guess is that this pattern (which I have commonly used before) is the right to use for safe WebSockets upgrade, in a cross-platform way.

Offline

#10 2025-08-19 08:58:55

squirrel
Member
Registered: 2015-08-13
Posts: 162

Re: WSS Authentication

Wow that was quick, thanks @ab!

I'm trying to understand the workflow of the new solution, but not very sure how to implement it.  It looks as if the upgrade to websockets replaces the mormot signing/authentication with cookies?

Offline

#11 2025-08-19 09:58:04

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 15,159
Website

Re: WSS Authentication

It is only for the Websockets upgrade itself.
Other regular HTTP requests are not affected.

But if you restrict your system to only support WebSockets connections on the server, it may be a good way to secure your service.
If it is properly used, and all other methods and services are setup to require a websockets, then TRestServerAuthenticationNone could be enough.
It is exactly the same as with a JWT bearer: in OnBeforeBody, you could only allow the upgrade URI (and perhaps /root/timestamp) and you would have a secure endpoint.

Offline

#12 2025-08-20 06:46:03

squirrel
Member
Registered: 2015-08-13
Posts: 162

Re: WSS Authentication

I am missing something frustratingly basic about the workflow.  How can I tie this back to a specific user account on the websockets side?  My workflow is:
1) user logs in using rest
2) user does rest calls - all of which need to know the user's session
3) user logs out

The websockets requirement is for when bidirectional actions are needed.  So the user upgrades the connection.  Now, for calls made by this user, I still need to tie this request to a specific session, since the user rights need to be checked and logged with every request.

I think I'm misunderstanding or missing something fundamental in the workflow of the changes to the code:
1) user logs in with rest and a session is created
2) user upgrades connection to wss and a new cookie is created
3) user gets access to the rest calls using the cookie, but there is no way to resolve the cookie to the session, so if the user logs out on rest, the wss sessions continue to be valid?

Last edited by squirrel (2025-08-20 06:48:24)

Offline

#13 2025-08-20 15:31:41

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 15,159
Website

Re: WSS Authentication

It could be e.g.
1) user logs in with rest and a session is created
2) user call a rest API to retrieve a bearer or a uri
3) user upgrades connection to wss using this bearer or  uri
4) user gets access to the rest calls using wss on this connection, using its previous session as usual

In fact, step 4) is transparent from the client point of view: it just makes some calls, and the framework will use the websockets protocol to perform its process.
The bearer or uri returned at step 2) is only used at step 3) not after.

For additional security, if you expect to accept only mORMot ws clients, you could filter the API calls to only be accessed via ws - but of course for the rest API which retrieve the bearer/uri.
Use OnBeforeBody for such input filtering.

Offline

#14 2025-08-21 12:54:24

squirrel
Member
Registered: 2015-08-13
Posts: 162

Re: WSS Authentication

Hi ab

I assume there is something I need to set, but not sure what.  The websockets signer is readonly:

    /// the TBinaryCookieGenerator created by rsoWebSocketsUpgradeSigned option
    // - equals nil if this option was not set
    // - WebSockets upgrade will be authenticated with an ephemeral secure token,
    // as retrieved from WebSocketsUrl/WebSocketsBearer associated methods
    property WebSocketsSigner: TBinaryCookieGenerator
      read fWebSocketsSigner;

so I assume it will be created automatically, but in function TRestHttpServer.WebSocketsBearer, it is nil, even though the option is included. So the exception is raised.

How should I create the httpserver so that the new websocket options can be used?  Like this?

  HTTPsServer := TSQLHTTPServer.Create('8084', [RestSvr], '+', useHttpApiRegisteringURI, 32, secSSL, '', '', [rsoWebSocketsUpgradeSigned]); //https
  HTTPsServer.AccessControlAllowOrigin := '*'; // allow cross-site AJAX queries
  Log('BEARER: ' + HTTPsServer.WebSocketsBearer(RestSvr)); //this causes the exception

Offline

#15 2025-08-21 15:55:27

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 15,159
Website

Re: WSS Authentication

Yes, as documented this instance should be created by the rsoWebSocketsUpgradeSigned option.

Offline

Board footer

Powered by FluxBB