2

Trying to protect my azure function with a function key (AuthorizationLevel.Function)

My azure function uses signalR. If I use AuthorizationLevel.Function on negotiate and my other signalR entry points, how can I pass the function key when the javascript code connects to signalR: function:

       public static SignalRConnectionInfo Negotiate(
       [HttpTrigger( AuthorizationLevel.Function, "post" )] HttpRequest req,
       [SignalRConnectionInfo( HubName = "myHub")] SignalRConnectionInfo connectionInfo,
       ILogger log )
       {
          return connectionInfo;
       }

website:

        const connection = new signalR.HubConnectionBuilder()
             .withUrl('https://<myfunction>.azurewebsites.net')
             .configureLogging(signalR.LogLevel.Information)
             .build();

        connection.start()
            .catch(console.error);

It seems HubConnectionBuilder can access the Headers in c# but not in javascript.

I have read Add headers to @aspnet/signalr Javascript client but the first suggestion appends the key to the url, and when connecting it would append /negotiate to it resulting in an invalid url with https://host/&code=/negotiate.

If it's not possible, any alternate way to protect my signalR function suggested? (Maybe bearer token as in https://learn.microsoft.com/en-us/aspnet/core/signalr/authn-and-authz?view=aspnetcore-3.1)

Thank you

  • did you manage to make it work? If the answer below was of any help, please mark it as correct, so others with similar issue know it's the solution :) – Michał Żołnieruk Nov 01 '20 at 13:21

2 Answers2

0

If you take a look at the documentation of the withUrl method, it allows an options object as a second parameter:

function withUrl(url: string, options: IHttpConnectionOptions)

The type of options is IHttpConnectionOptions, which gives some possibilities:

a) you can provide the implementation of IHttpConnectionOptions.accessTokenFactory, which should return a Bearer token (for this to work, you'd need to manually validate the Bearer token in your Azure Function)

b) you can provide your own HttpClient implemenatation, in which you'd modify the Post request by adding the Azure function key, something like below:

const connection = new signalR.HubConnectionBuilder()
  .withUrl('https://<myfunction>.azurewebsites.net', {
    httpClient: {
      post: (url, httpOptions) => {
        const headers = {
          ...httpOptions.headers,
          'x-functions-key': YOUR_AZURE_FUNCTION_KEY,
        }

        return axios.post(url, {}, { headers }).then((response) => {
          return (newResponse = {
            statusCode: response.status,
            statusText: response.statusText,
            content: JSON.stringify(response.data),
          })
        })
      },
    },
  })
  .configureLogging(signalR.LogLevel.Information)
  .build()

Sources:

https://learn.microsoft.com/en-us/aspnet/core/signalr/javascript-client?view=aspnetcore-3.1

How to pass Custom Header from React JS client to SignalR hub?

Michał Żołnieruk
  • 2,095
  • 12
  • 20
  • i was looking at https://learn.microsoft.com/en-us/aspnet/core/signalr/configuration?view=aspnetcore-3.1&tabs=dotnet#configure-additional-options-1 In .NET there was a way to pass the headers but in not in javascript. I will try the way you suggested. Thank you. – Francois Nguyen Nov 02 '20 at 17:47
  • 1
    It almost worked out of the box. It was complaining about "getCookieString is not a function". I added getCookieString: (url) => { return ""; } below the post and it appears to work. – Francois Nguyen Nov 05 '20 at 00:09
0

As noted in my answer to the question linked to in this question, you can now do as follows:

const connection = new signalR.HubConnectionBuilder()
  .withUrl('https://<myfunction>.azurewebsites.net', {
       headers: {'x-functions-key': YOUR_AZURE_FUNCTION_KEY}
   })
  .build();
Arithmomaniac
  • 4,604
  • 3
  • 38
  • 58