Securing Azure SignalR +Azure App Service - Part 3
Tags: azure, azuresignalr, security, webdev
Published: 2021-06-02 09:53:36

Hope everyone is safe and well 😊

I thought of discussing azure signalr using terraform in this part, but today I found a very interesting things from azure signalr authentication which is not yet officially documented by Microsoft. So, I'm going to discuss that in this part. 

# Using Managed Identity

Now a days its common and best practice to use managed identity as much as you can to avoid using the *keys/connection string/password* in your application or event vault. So, I also would want to use managed identity for authentication from my azure app service to the Azure SignalR resource. This has been explained so well at [here](https://docs.microsoft.com/en-us/azure/azure-signalr/howto-use-managed-identity)

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e9i6ykfwthf3y3cyem68.png)

So I thought it would be super simple to implement this in my POC until I hit one road block, let’s see what is the problem and how can we solve that.

## Enabling Managed Identity for my POC

If you have followed this series from the beginning, you already noticed that I was doing a POC where I am trying to securely connect my azure signalr from my azure web app. If you missed the earlier parts, no worries please check this [Part 1](https://dev.to/jayendran/securing-azure-signalr-azure-app-service-part-1-bko) and [Part 2](https://dev.to/jayendran/securing-azure-signalr-azure-app-service-part-2-2mf1) before going further into this part.

As of now my architecture will look like 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a57e54yt2km0sp96npdu.png)
 
And my azure signalr NAC will look like

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f6o7hw5ift2ytg6vq5pt.png)

  

I have securely connected my azure signal from my azure web app, but my *authentication is still using the connection string with accesskey*. 

The typical azure signalr connection string will look like this.

```
Endpoint=https://<resource-name>.service.signalr.net;AccessKey=AsNsXs1UdfdfdererereNXa7VOVvPmZnHqnm2iCG6WTom31nXE=;Version=1.0;
```

In order to enable the managed identity, I followed the above MS doc and did like the steps like below

1. I need to enabled the `system assigned` identity for my azure web app ![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4ke0iis5b8qqt0btrztw.png)

1. Assign the above `system assigned` identity as **SignalR App Server** role in my azure signalr IAM. *Please note that this role is still in <u>Preview<u/>* ![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cilbdaq861whd0f77j09.png)

1. Update my connection by replacing the `accesskey` with `AuthType=aad`. So, my new connection string will be

```
Endpoint=https://<resource-name>.service.signalr.net;AuthType=aad;Version=1.0;
```

## The problem that I hit

After enabling the managed identity when I tried to test my app I got *500 Internal Server Error* for the negotiate connection 

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z1ix52jvhfaizbous2di.png)

hmm.. not much useful error/information to debug further. So, I have enabled the *Application Insights* to see where the failure is occurring.

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9qm3konqrg1hywe764e1.png)

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bi7f21zmogz0zlqqwpfk.png)
  

So the actual error is 
```
Failed in authorizing AccessKey for 'https://xxxxx-signalr-01.service.signalr.net', will retry in 3 seconds.
```
The real 403 Forbidden endpoint is. 
```
https://signalrsevice.service.signalr.net:443/api/v1/auth/accessKey?serverId=xxxx
```
Stack trace:

```
Microsoft.Azure.SignalR.Common.AzureSignalRRuntimeException:
at Microsoft.Azure.SignalR.AadAccessKey+<UpdateAccessKeyAsync>d__23.MoveNext (Microsoft.Azure.SignalR.Common, Version=1.8.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult (System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at Microsoft.Azure.SignalR.AccessKeySynchronizer+<UpdateAccessKeyAsync>d__13.MoveNext (Microsoft.Azure.SignalR.Common, Version=1.8.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60)
Inner exception System.Net.Http.HttpRequestException handled at Microsoft.Azure.SignalR.AadAccessKey+<UpdateAccessKeyAsync>d__23.MoveNext:
```

### Let us understand the error 

If you read the error properly you will understand what is going wrong. 

From the forbidden endpoint it seems that azure signalr is trying to call a **REST API** to Azure AD to get the token (for Managed identity) behind the screen

*https://signalrsevice.service.signalr.net:443/api/v1/auth/accessKey?serverId=xxxx*


### Joining the dots / Fixing the Issue

So let’s step back and think about our NAC control configuration
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f6o7hw5ift2ytg6vq5pt.png)

In this we have allowed only *Server Connection* from our private endpoint, there are a couple of other connections also visible in the dropdown. such as 
- REST API
- TRACE API

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p57kstyutvdynmwnuj8q.png)
 
Perfect, lets enable the *REST API* connection also from our private endpoint. Now our NAC will look like 

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/of3qgkx06qwfa20flieu.png)

That’s it, I have waited for 30min, and my application is working as expected.

#### Interesting fact

The documentation about *REST API* and *TRACE API* is still not available public or under development phase. So, it is kind of difficult to get the relevant information for now about these two API’s.

### Workflow

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n055n5vfov87na1gk9nj.png)

### Permanent fix from Microsoft

I reached out to azure signalr team about this, and I got the response like 

> We would get rid of API calls in AAD authenticating process, which means if our customer’s use our future SDK, they will not have to enable REST API explicitly. 
We will make it internally in our server connection, instead of sending a rest API. This change would take 1-2 months and the newly released SDK will be like 1.9.x. it will be documented in future release. 

### Overall Architecture

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lycm1l676owb1yr4wgjo.png)