signalR giving 403 when authenticated - azure

I have a MVC app that uses signalR and Forms authentication and published to Azure Service - Was working fine with MVC4, SignalR 1.1.2
We upgraded to VS 2013 and the latest and greatest of all the packages, MVC 5.5.2 and signalR 2.1.2, and made the required changes for mapping SignalR via OWIN
Now when I am not logged in, signalR works as expected and connects using WebSockets. But when I do login and refresh the same page, signalR no longer works.
I get an 403 error on connecting via websockets
It then tries server sent events with comes back as (cancelled)
and then Long Polling also fails with a 403 - Forbidden error
Note that when running locally it works fine, it just when publish to azure service that I get this problem
I must be something simple I'm missing. Anybody done a similar upgrade?
Its a large app, so can't really share much code, but in essence all I'm doing is connecting to the signalR hub
<script type="text/javascript" src="/signalr/hubs"></script>
<script type="text/javascript">
$(function () {
// SignalR - Initialise
var dashboardHub = $.connection.miHub;
// start signalR hub - this will connect the user
$.connection.hub.start();
});
</script>
and hub class
public class MiHub : Hub
{
public override Task OnConnected()
{
ConnectUser();
return null;
}
....
}
When I am not logged in to my app, dev tools shows the following:
wss://myservice.cloudapp.net/signalr/connect?transport=webSockets&clientProtocol=1.4&connectionToken=...
response 101
wss://myservice.cloudapp.net/signalr/connect?transport=webSockets&clientProtocol=1.4&connectionToken=...
response 200
{ "Response": "started" }
When I logged in and hit F5 on the same page I get
wss://myservice.cloudapp.net/signalr/connect?transport=webSockets&clientProtocol=1.4&connectionToken=...
response 403

Related

Azure Notifcation Hub CreateOrUpdateInstallationAsync not failing but Installation not being created

I have an ASP.NET Web Api that is registering Android and iOS installations in our Azure Notification Hub. It creates a HubClient using a connection string
this.azureHub = NotificationHubClient.CreateClientFromConnectionString(
"Endpoint=sb://OUR-HUB-NS.servicebus.windows.net/;SharedAccessKeyName=DefaultFullSharedAccessSignature;SharedAccessKey=tK/SEXXXXXXXXXXX/7LUtvRoNt+HjToFmP+T++yW5g=",
"OUR-HUB");
We then create an installation using this code
try
{
await azureHub.CreateOrUpdateInstallationAsync(installation, token);
}
catch(Exception e)
{
this.logger.LogError(e, "CreateOrUpdateInstallationAsync failed with" + e.Message);
return false;
}
return true;
When I had the NoticationHubClient incorrectly configured I was getting 401 errors and if I pass in nonsense for the installation data I will get a 400. Currently the call does not throw an error so I asm going to assume what I am passing is correct and it can successfully connect to the hub. However registrations are not being created. If i try and get the installation after it is created with
GetInstallationAsync(installation.InstallationId)
I get an error saying the installation cannot be found and if I try and get all registrations i get an empty list
var registrations = await azureHub.GetAllRegistrationsAsync(0);
Further confirmation that my installations are not being created is that if I use the "Test Send" in Azure Portal I get "Message was successfully sent, but there were no matching targets." for either Apple or Android platform
What is happening to my registration?
I recreated the Notification Hub with a different name, in the same namespace and everything just started working.
I then recreated the non-working hub in Azure Portal and it now all works.
All I can say is that I had previously deleted the hub using the OSS Service Bus Explorer and perhaps that deleted the hub in a way that Azure didn't like.
Not the answer I was expecting.

Requests to third party API from .NET Core app timeout in IIS

I have a .NET Core Web API app running in IIS that can receive and respond to requests, but it needs to make requests to a third party API (Twilio). Those requests succeed when hosted locally but they time out when hosted in IIS.
The .NET Core Web API app is targeting v2.1 and running on Windows Server and IIS 7. I setup a dedicated app pool for the site following guidelines in this article.
App pool settings:
I'm using Postman to make GET and POST requests to the app.
GET and POST requests to a test controller work fine. All I'm doing with these test endpoints is returning the parameters that are received.
[Route("api/[controller]")]
[ApiController]
public class TestController : ControllerBase
{
[HttpGet]
public string Get(int id)
{
return $"response to GET; id:{id}";
}
[HttpPost]
public string Post([FromBody] int id)
{
return $"response to POST; foo:{id}";
}
}
The above endpoints work locally running debug mode in VS2019 using IISExpress, and they also work when deployed to the web server and hosted with IIS7.
The trouble starts when I try to call out to a third party API (Twilio). Again these calls succeed when the app runs locally. There's almost no delay. I post to the SMSController's post endpoint, the request is triggered, and I get a text message within seconds. However, GET and POST requests to these endpoints fails from the web server and IIS.
[Route("api/[controller]")]
[ApiController]
public class SMSController : ControllerBase
{
private string twilioSID = "xxxxxx";
private string twilioAuthToken = "xxxxxx";
private string twilioPhoneNumber = "+15555555555";
[HttpGet]
public string Get(string phoneNumber)
{
TwilioClient.Init(twilioSID, twilioAuthToken);
var message = MessageResource.Create(
body: $"TEST message via Twilio",
from: new Twilio.Types.PhoneNumber(twilioPhoneNumber),
to: new Twilio.Types.PhoneNumber(phoneNumber)
);
return message.Status.ToString();
}
[HttpPost]
public string Post([FromBody] GeoEvent geoEvent)
{
TwilioClient.Init(twilioSID, twilioAuthToken);
var message = MessageResource.Create(
body: $"TEST message via Twilio",
from: new Twilio.Types.PhoneNumber(twilioPhoneNumber),
to: new Twilio.Types.PhoneNumber(geoEvent.PhoneNumber)
);
return message.Status.ToString();
}
}
GET and POST requests to the above endpoints get a 500 response when hosted in IIS. The following exception is thrown:
System.Net.Http.HttpRequestException: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond ---> System.Net.Sockets.SocketException: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond
Lastly, here is the web.config that the SDK generated for me when I published the app in VS2019.
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<location path="." inheritInChildApplications="false">
<system.webServer>
<handlers>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />
</handlers>
<aspNetCore processPath=".\TwilioService.exe" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" />
</system.webServer>
</location>
</configuration>
Neither my local machine nor the web server running IIS are behind a corporate proxy.
Am I missing an IIS or web.config setting that will allow .NET Core to make requests through IIS to a third party?
UPDATE:
I have now reproduced the same issue on a different web server running Windows Server 2016. This machine is setup with .NET 5, IIS 10, and the hosting bundle for .NET 5. I also installed VS2019 and recreated the web api project to run locally on the server. Here are the results:
Running locally in IIS Express, the api controller can successfully
make a request to the Twilio api and gets a response. The SMS
message is sent successfully. No errors.
Running locally in IIS 10, the api controller calls Twilio but
fails to get a response. The following error occurs:
Twilio.Exceptions.ApiConnectionException: Connection Error: POSThttps://api.twilio.com/2010-04-01/Accounts//Messages.json
---> System.Net.Http.HttpRequestException: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond. (api.twilio.com:443)
To reiterate, both of the above scenarios are running on the same machine. The only difference is IIS Express vs IIS 10. Is this an SSL cert issue? Because IIS 10 works as a reverse proxy for .NET core apps, could there be a problem with a cert getting recognized or forwarded from the .net core app through IIS?
Try to ping the third-party service URL from your machine command prompt.
Make sure the firewall port is set to allow. check the antivirus is now blocking the connection.
try to add the defaultProxy section to my web.config in order to get my website to connect to a web service.
https://learn.microsoft.com/en-US/troubleshoot/dotnet/framework/cannot-consume-web-service-via-http-proxy
Solved. It turned out to be a corporate proxy after all. I had bad information that the web server was not behind a proxy but it was. Twilio has a solution for this exact scenario in their documentation involving the use of a custom proxied rest client class. It's a wrapper around System.Net.HttpClient. The service can now make calls to Twilio through the proxy using this class with the proxy server url set.

Azure App Service cannot connect to Azure Redis when calling from Web Browser

I have a REST API services application that is using Asp.net core, and hosted on Azure App Service.
I am adding Azure Redis as a cache mechanism.
I tested the application on my local machine using local redis and it is working fine.
I deployed the Web service To Azure App Service, and test it.
When I try to test the services using Postman, it is working fine, and it is populating the cache, and reading from the cache.
But when I run the Front-end application which is a JavaScript Single Page Application that is calling the back-end services.
I am not querying Redis from the front-end. but from the backend .net application.
The calls to the services fail with this error
Timeout performing EVAL, inst: 1,
clientName: <.....>, serverEndpoint: Unspecified/my-redis.redis.cache.windows.net:6380,
keyHashSlot: 15126 (Please take a look at this article for some common client-side issues that can cause timeouts: http://stackexchange.github.io/StackExchange.Redis/Timeouts)
As I said, I am calling the same EndPoint (which is my App service), with the same parameters, from Postman, and it is working.
But from the browser, it is not working
This is my configuration and code:
In the Startup.cs
public void ConfigureServices(IServiceCollection services)
{
...
services.AddDistributedRedisCache(options => {
options.Configuration = Configuration.GetConnectionString("AzureCache");
options.InstanceName = "master";
});
}
And in the controller (ProductController)
using Microsoft.Extensions.Caching.Distributed;
public class ProductController: ControllerBase
{
IDistributedCache _cashe;
IDataRepository _repo;
public ProductController (IDistributedCache cache, IDataRepository repo)
{
_cache = cache;
_repo = repo;
}
[HttpGet]
public Async Task<IActionResult> GetProductions([FormBody] DataRequest request)
{
string data = _cache.GetString(request.AsKey());
if (data == null)
{
data = _repo.getData(request);
_cache.SetString(request.AsKey());
}
return Ok(data);
}
}
}
The client side code is as follows:
const request = axios.post('https://mydata.myserver.azure.com', reqBody, headers);
request.then(res => {
.... process the data
});
P.S: the error mentioned an article online.
I read the article and nothing jumped out. All my services are less than 5k in size except one, which is between 250k and 300k, and all calls are failing for me.
Error itself describing 'Please take a look at this article for some common client-side issues'. Could you share your client side code through which you are making call?

IsWebSocketRequest always false in azure

I have published my websocket on azure and I have enabled the web socket feature in my web app but i keep getting IsWebSocketRequest false when i connect to my web socket, note that locally using localhost it is working normally
if (context.IsWebSocketRequest)
context.AcceptWebSocketRequest(new TestWebSocketHandler());
below is my web app configuration
I am not clear what cause your error.
You could refer to this sample.
I add IsWebSocketRequest in Get method, and run in local and on azure it works fine.
public HttpResponseMessage Get(string username)
{
HttpContext currentContext = HttpContext.Current;
if (currentContext.IsWebSocketRequest)
{
HttpContext.Current.AcceptWebSocketRequest(new ChatWebSocketHandler(username));
}
return Request.CreateResponse(HttpStatusCode.SwitchingProtocols);
}

IDX10803 and IDX10804 error with Azure AD

I have created a Web API in ASP.NET Core 2 and it is secured with Azure AD. The requests work fine in my dev environment. However when I publish the API to IIS and pass in a Authorization header in request I am getting these error:
fail: Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler[3]
Exception occurred while processing message.
System.InvalidOperationException: IDX10803: Unable to obtain configuration from: 'https://login.microsoftonline.com/xxxx/.well-known/openid-configuration'. ---> System.IO.IOException: IDX10804: Unable to retrieve document from: 'https://login.microsoftonline.com/xxxx/.well-known/openid-configuration'. ---> System.Net.Http.HttpRequestException: An error occurred while sending the request. ---> System.Net.Http.WinHttpException: A connection with the server could not be established
What am I doing wrong? I can browse the url in browser successfully.
I figured it out. It was because of a proxy setting to access the internet. Since ASP.NET Core does not pick up proxy setting from system.net area of web.config, the ideal solution was to create a middle ware to act as proxy.
I was running short of time. So I created a new user and logged on server with that new user and configured the proxy settings in Internet Explorer options. Then I configured the App Pool in IIS to run under that user's identity. Problem solved!
The correct answer is to add a proxy to the metadata request that ADAL makes using BackchannelHttpHandler. You can do it like this:
public void Configure(string name, JwtBearerOptions options)
{
options.BackchannelHttpHandler = new HttpClientHandler
{
UseProxy = true,
Proxy = new WebProxy
{
Address = new Uri($"{appSettings.InternetProxyUrl}:{appSettings.InternetProxyPort}"),
UseDefaultCredentials = true
}
};
}

Resources