elsa-core icon indicating copy to clipboard operation
elsa-core copied to clipboard

Authorization with SignalR

Open Jejuni opened this issue 3 years ago • 3 comments

Currently I see no way way to add authorization to the "WorkflowTest" feature added in 2.4 . Not having any way to add authorization means a protected API will never be able to use the SignalR component of Elsa. Is there any guidance on adding authorization to the SignalR component of Elsa like there is with the http client?

The code in elsa-workflow-test-panel simply creates a hub connection via:

    this.hubConnection = new HubConnectionBuilder()
      .withUrl(this.serverUrl + "/hubs/workflowTest")
      .build();

Traditionally to add authorization you would do something like:

 this._hubConnection = new HubConnectionBuilder()
      .withUrl(hubUri, {
        accessTokenFactory: () => {
          // get token from somewhere
          return sessionStorage.getItem('access_token');
        },
      })
      .build();

The server side would probably not need an update to its method for this so long as the prefix of hubs is kept for all current and future SignalR connections. The reason being that one can simply intercept the OnMessageReceived event during JwtBearer configuration and read and set the access token this way when the request path starts with hubs.

Jejuni avatar Jan 04 '22 17:01 Jejuni

Indeed, we need to add an extensibility point to the creation of the hub. We could do it similar to the way the Axios client is instantiated by publishing an event, which can then be handled by a custom Elsa plugin.

E.g.

const hubBuilder = new HubConnectionBuilder().withUrl(this.serverUrl + "/hubs/workflowTest");

await eventBus.emit('creating-signalr-hub', this, { hubBuilder });

this.hubConnection = hubBuilder.build();

Then the plugin would do something like this:

function AuthenticatingPlugin(elsaStudio) {
   const { eventBus } = elsaStudio;

   eventBus.on('creating-signalr-hub', e => {
      const { hubBuilder } = e;
      
      hubBuilder.accessTokenFactory: () => {
          // get token from somewhere
          return sessionStorage.getItem('access_token');
        },
   })
}

sfmskywalker avatar Jan 07 '22 11:01 sfmskywalker

I think that's a good idea, especially to keep in line with existing functionality and enable specialized scenarios.

To make the configuration story more streamlined, what about also adding a simple helper method like:

addAuthorization(tokenRerieveCallback: () => string)

In both the http middleware as well as the signalR case all the user really needs to supply is a way to get the token. The rest could be handled by Elsa.

Jejuni avatar Jan 10 '22 08:01 Jejuni

This looks really promising, something we need to add today (or as quick as possible).

Is this being worked on currently or are you accepting PRs?

Nico-VanHaaster avatar Aug 05 '22 01:08 Nico-VanHaaster