Self hosting Web API with OWIN on EC2 - owin

I followed step-by-step instructions from http://www.asp.net/web-api/overview/hosting-aspnet-web-api/use-owin-to-self-host-web-api.
Here is the code of console application:
namespace OWINTest
{
class Program
{
static void Main(string[] args)
{
string baseAddress = "http://localhost:1961/";
// Start OWIN host
WebApp.Start<Startup>(url: baseAddress);
...
}
}
class Startup
{
// This code configures Web API. The Startup class is specified as a type
// parameter in the WebApp.Start method.
public void Configuration(IAppBuilder appBuilder)
{
// Configure Web API for self-host.
HttpConfiguration config = new HttpConfiguration();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
appBuilder.UseWebApi(config);
}
}
public class ValuesController : ApiController
{
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
}
}
The following is true:
OWIN server is running (can connect from the same machine using Fiddler, browser)
Port of EC2 instance is opened to inbound traffic via security group
No other processes are listening to that port
OWIN version is Microsoft.AspNet.WebApi.OwinSelfHost 5.2.2
.NET 4.5 is installed on EC2 instance
Issue I run into:
HTTP/1.1 502 - Connection Failed error when calling http://(uc2-00-000-000-us-west-1.compute.amazonaws.com):1961/api/values with the following message: The connection to 'ec2-00-000-000-us-west-1.compute.amazonaws.com' failed. Error: TimedOut (0x274c). 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
I tried the following without success:
1. 'netsh http add urlacl url=http://localhost:1961 user=everyone'
2. 'netsh http add urlacl url=http://+:1961 user=everyone'
3. 'netsh http add urlacl url=http://*:1961 user=everyone'

Use base address http://+:1961/ and depending on which windows account you are running your owin server as you won't need the urlacl.
ie:
you're running your owin server as a windows service using the local system account then you won't need the urlacl.
you're running the owin server from the command prompt while logged in the administrator account.

Related

HttpClient 401 Unauthorized - How to authenticate IIS website to another IIS website

I have this well known 401 Unauthorized error. My scenario is that website A needs to call HTTP request (GET) to website B. Both websites runs on the same IIS server under different application pools (accounts). When I call HTTP request within the browser on my computer (that is connected to the windows domain) the HTTP request works and website B returns JSON data. But when that call is done by website A it seems that the information about the service account of website A is not added into the HTTP request and website B denies that request with 401. That leads to two questions
Why the IIS server does not recognize (authenticate/authorize) the website A account?
How can I add manually the account info into the HTTP request (using HTTP Client) so that I don't need to know username and password of the service account?
Currently my code looks like
namespace Infrastructure
{
public class FooService
{
private readonly HttpClient _httpClient;
public FooService(HttpClient httpClient)
{
_httpClient = httpClient;
_httpClient.BaseAddress = new Uri("https://domain/");
// Adding basic header does not work.
// var byteArray = Encoding.ASCII.GetBytes("user:passowrd");
// _httpClient.DefaultRequestHeaders.Authorization =
// new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
}
public async Task<FooServiceData> GetDataAsync() =>
await _httpClient.GetFromJsonAsync<FooServiceData>(
"foo/data");
}
public class FooServiceData
{
public string Url { get; set; }
public string Token { get; set; }
}
}
and the call that throws 401 is executed in controller action
var credentials = _fooService.GetDataAsync().Result;
Update:
When I connect to the website B via browser it does work. When I run ASP.NET MVC website project (on my development machine in Visual Studio) that sends HTTP request, it also does not work (401). The IIS setting (launchSetting.json) contains following
"iisSettings": {
"windowsAuthentication": true,
"anonymousAuthentication": false,
"iisExpress": {
"applicationUrl": "http://localhost:26978",
"sslPort": 44339
}
}
I thought that the Visual Studio is running under my account (and also the IIS service it runs in the background) but it seems that there are some changes in the Auth that prevent the website B to Auth me, any idea?
Update 2:
We tried to setup following property in the properties of the Website B service account but it didn't help.
I solved the issue with the following code on the caller side. Previously I registered the FooService as follows
services.AddHttpClient<FooService>();
but for Windows Authentication the credentials has to be specified
services.AddHttpClient<FooService>()
.ConfigurePrimaryHttpMessageHandler(x => new HttpClientHandler()
{
Credentials = CredentialCache.DefaultNetworkCredentials
});

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
}
};
}

WCF Discovery with multithreading - The caller was not authenticated by the service

I try to implement WCF Discovery service using multithreading.
static void InvokeService()
{
var Services = discoveryClient.Find(new FindCriteria(typeof(WCFDiscoveryContract.IService1)));
discoveryClient.Close();
ServiceClient.ServiceReference1.Service1Client client = new ServiceClient.ServiceReference1.Service1Client();
client.Endpoint.Address = Services.Endpoints[0].Address;
var loanResponses = new MultiThreadedServiceCall<IService1, int, string>()
.CallMethod((service, request) => service.GetData(request))
.AttachService(new ServiceClient.ServiceReference1.Service1Client())
.GetResults(111);
string ss = client.GetData(1);
Console.WriteLine("Data is " + ss);
}
When i discover a service hosted in the same machine, it is working fine with the output.
But when i use the service hosted in another machine in the same network, it throws error in the following line.
string ss = client.GetData(1);
Error is
SecurityNegotiationException was unhandled
The caller was not authenticated by the service.
The request for security token could not be satisfied because authentication failed.
I use wsHttpBinding.
Please note wcf discovery service is working fine for service hosted in another machine.

Resources