Как использовать бессерверный Azure SignalR (REST API / восходящий поток) с ReactJS?

#node.js #reactjs #signalr

Вопрос:

На высоком уровне я хочу добиться связи в реальном времени между двумя приложениями ReactJS. Мне нужно иметь возможность создавать определенные группы для разделения конечных пользователей, эта группа будет принадлежать другой группе с одним или несколькими пользователями-менеджерами. Менеджер должен иметь возможность отправлять сообщения (может быть строкой или объектом) всей группе конечных пользователей или только для одного пользователя в этой группе, после чего я могу действовать в приложении конечного пользователя. Конечные пользователи должны иметь возможность отправлять сообщения для определенной группы менеджеров.

Поскольку Azure Cloud предоставляется, разумным выбором было бы использовать Azure SignalR, особенно потому, что он имеет бессерверный план.

  • Я создал службу SignalR, установил ее в бессерверный режим.
  • Установлен пакет @microsoft/signalr для приложений React.
  • Создал функцию Nodejs согласования HTTP-триггера с привязкой SignalR.

В этот момент я подключен к SignalR. Но я не знаю, как действовать дальше. С одной стороны, я должен иметь возможность использовать API REST SignalR, с другой стороны, я мог бы использовать SignalR вверх по течению. Восходящий поток кажется более подходящим, поскольку пользователи могут вызывать методы концентратора (в моем случае привязки Nodejs SignalR в приложении функций), и пользователи получают уведомления при подключении или отключении клиентских подключений. Это важно для пользователей диспетчера, чтобы видеть, кто подключен и работает ли соединение. В качестве следующих шагов:

  • определенный восходящий URL-адрес
  • созданные подключенные/отключенные привязки в приложении функции

функция.json:

 {
  "bindings": [
    {
      "type": "signalRTrigger",
      "name": "invocation",
      "hubName": "default",
      "category": "connections",
      "event": "connected",
      "direction": "in"
    },
    {
      "type": "signalR",
      "name": "signalRMessages",
      "hubName": "default",
      "connectionStringSetting": "AzureSignalRConnectionString",
      "direction": "out"
    }
  ]
}
 

index.js:

 module.exports = function (context, invocation) {
  context.bindings.signalRMessages = [
    {
      target: "connected", // name of the client method to invoke
      arguments: [invocation.ConnectionId],
    },
  ];
  context.done();
};
 

Аналогичным образом, отправляя широкое сообщение:

 {
  "bindings": [
    {
      "type": "signalRTrigger",
      "name": "invocation",
      "hubName": "default",
      "category": "messages",
      "event": "broadcastMessage",
      "parameterNames": ["message"],
      "direction": "in"
    },
    {
      "type": "signalR",
      "name": "signalRMessages",
      "hubName": "default",
      "connectionStringSetting": "AzureSignalRConnectionString",
      "direction": "out"
    }
  ]
}
 
 module.exports = function (context, invocation) {
  context.bindings.signalRMessages = [
    {
      target: "broadcastMessage", // name of the client method to invoke
      arguments: [
        context.bindingData.message, // arguments to pass to client method. binding with parameterNames
      ],
    },
  ];
  context.done();
};
 

After connection from the React app, the connected method is fired automatically and I could invoke other methods like: siglarConnection.invoke("broadcast", 'Hi')
But this is as far as I got. No private message, no user groups and still need to manage the active connections somewhere.
Also there is a suggestion, that I could use userId to send messages directly, no need to bother with the connectionId. Since other functions are using App Service Authentication and the users are stored in AD B2C:

  • enabled the App Service Authentication for the Function app

Now for the React apps to connect I need to pass an access token with to the connection builder else I get a 401. Now I can apps connect again but now using the authenticated users access token, which is a good thing, but because of this my invokations does not work anymore. Most likely because I cannot supply access token with these and I get back 401.

Security is a must, so I decided to take a look at the REST API way.

Looks fairly straight forward, I need to call the specified endpoints, but calling them actually gives 401 response www-authenticate: Bearer error=»invalid_token», error_description=»The signature key was not found». Figures since I call the signalR service directly, providing AD B2C access token does not help. I probably need the access token from the negotiate, but I don’t know how to get it. Sure enough it’s in the negotiate response, but I was not able to intercept that.

Sorry for the lengthy description, but I believe it was necessary to understand my scenario. I may have a major overlook somewhere or someone with similar experience can clear up the confusion. There are tons of examples using C#, but I cannot use that.
Any help is appreciated.