How do people test their [RequireHttps] attribute in a Web API? - c#

Quick version
I'm sure many people have implemented a [RequireHttps] SSL check of some description (message handler, attribute, whatever) at some point in their Web API development. How do you guys and gals test that it works correctly both in terms of success and failure?
Not so quick version
I'm developing a REST service in a OWIN self-hosted ASP.NET Web API 2. I have already successfully secured the service with SSL and have implemented a custom [RequireHttps] attribute (derived from the answers to this SO question).
In the case when the client is calling the correct URL (e.g. https://my.server.com/api/values), if I add a breakpoint in the attribute definition, the debugger correctly breaks in the code (just calls the base and all is well, as expected).
The question is: how can I exercise the failure scenario for this attribute, such that the attribute code will return an error response without interfering with other server processes?
My Web API service listens on base address https://+:9443/. I've tried removing the s such that I connect to http://my.server.com:9443/api/values, but I get an error response status 502 (connection failed) after about a minute's timeout. Fair enough I suppose, but I was actually hoping to return a response ("SSL required") from my [RequireHttps] attribute.
Then I've tried creating the following StartOptions object:
var options = new StartOptions();
options.Urls.Add("https://+:9443/"); // listen on port 9443 with SSL
options.Urls.Add("http://+:80/"); // listen to standard HTTP port 80
and passing it to the WebApp like this:
WebApp.Start<Startup>(options)
Again, this didn't work when I connected to http://my.server.com:9443/api/values, but it worked when I connected to http://my.server.com:80/api/values.
However, this is not what I want to do. My production server hosts both secure (HTTPS) and insecure (HTTP on port 80) resources so my code will intercept legitimate calls to other processes that rely on port 80 and tell them to reconnect via https, which is wrong.
Can someone please advise on what options I have? Is there even a point to have [RequireHttps] given my situation, as it never seems to do anything useful?

What you are trying to do can't be done. Basically, you're trying to do the same thing as typing
http:443//www.google.com
Notice how that doesn't work either
The problem is that you're trying to access an http protocol over an SSL protocol port, and that is what's failing. Your code for the RequireHttps doesn't even get to execute because the request can't even be processed through IIS.

Related

How to consume a socket.io WebSocket API in C#

I need to consume a third-party WebSocket API in .NET Core and C#; the WebSocket server is implemented using socket.io (using protocol version 0.9), and I am having a hard time understanding how socket.io works... besides that the API requires SSL.
I found out that the HTTP handshake must be initiated via a certain path, which is...
socket.io/1/?t=...
...whereby the value of the parameter t is a Unix-timestamp (in seconds). The service replies with a session-key, timeout information, and a list of supported transport protocols. Due to simplicity, this first request is made via HttpClient and does not involve any additional headers.
Next, another HTTP request is required, which should result in an HTTP 101 Switching Protocol response. I specified the following headers in accordance to the previous request...
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Key: ...
Sec-WebSocket-Version: 13
...whereby the value of the Key-header is a Base64-encoded GUID-value that the server will use to calculate the Sec-WebSocket-Accept header value. I also precalculate the expected Sec-WebSocket-Accept header value, for validation...
I tried to make that request using HttpClient as well, but that does not seem to work... I actually don´t understand why, because I expect an HTTP response. I also tried to make the request using TcpClient by sending a manually prepared GET request over a SslStream, which accepts the remote certificate as expected. Sending data seems to work, but there´s no response data... the Read-method returns zero.
What do I miss here? Do I need to setup a listener for the WebSocket connection as well, and if yes how? I don´t want to implement a feature complete socket.io client, I´d just like to keep it as simple as possible to catch some events...
The best way of debugging these issues is to use a sniffer like wireshark or fiddler. Often connect using an IE and compare IE results with my application and modify my app so it works like the IE. Using WebClient instead of HttpClient will also work better because the WebClient does more automatically than the HttpClient.
A web connection uses the header of the client and the headers in the server webpage to negotiate a connection mode. Adding additional headers to you client will change the connection mode. Cookies are also used to select the connection mode. Cookies are the results of previous connection to the same server which shortens the negotiations and stores info from previous connection so less data has to be downloaded from server. The server remembers the cookies. Cookies have a timeout and is kept until timeout expires. The IE history in your client has a list of IP addresses and Net automatically sends the cookies associated with the server IP.
If a bad connection is made to the server the cookies is also bad so the only was of connection is to remove the cookie. Usually I go into the IE and delete cookies manually in the IE history.
To check if a response is good the server returns a status. A completed response contains a status 200 DONE. You can get status which are errors. You can also get a 100 Continue which means you need to send another request to get the rest of the webpage.
Http has 1.0 (stream mode) and 1.1 (chunk mode). Net library doesn't work with chunk. Chunk requires client to send message to get next chunk and I have not found a way in Net to send the next chunk message. So if a server responds with a 1.1 then you have to add to your client headers to use 1.0 only.
Http uses TCP as the transport layer. So in a sniffer you will see TCP and HTTP. Usually you can filter sniffer just to return Http and look at header for debugging. Occasionally TCP disconnects and then you have to look at TCP to find why the disconnect occurs.

How to get the SSL key of a https:// C# HttpWebRequest? (similar to browser environment variable SSLKEYLOGFILE)

Currently I am working on a custom HTTP publisher for the Peach Fuzzing framework.
In order to determine if the server responed in an unusual way I need to examine the decrypted incoming / outgoing packages with Wireshark (or the PcapMonitor that is included in the Peach Framework) - to do that I need the SSL keys that are being generated by the C# HttpWebRequest (similar to the content of the SSLKEYLOGFILE) since I am trying to fuzz an SSL protected RESTful webservice.
If it is not possible to get the keys or if it is very difficult - is there any other way to see the raw HTTP request / response?
Thanks!
Just found a way to get the decrypted packages:
Create a loopback interface that can be monitored with Wireshark
Create a reverse proxy (I used nginx) and redirect all traffic from "localhost" to the target URL (https://)
Tell your application not to send the requests to target (https://) but to localhost (http://localhost/)
Start listening on the loopback interface and start your application
Hope this is helpful for somebody in a similar situation

What is an absolute bare bones httpclient configuration?

I'm coming to .net web api from a JavaScript background, and I'm trying to make a proxy to help with a cross domain JSON request. I'm GETing from a server I don't control the source code for, so I can't configure CORS directly. Likewise, it doesn't speak JSONP.
So two questions as I try to get my head around Web API:
1) Is Httpclient the right tool for this job? (if not, what is?)
2) If httpclient IS the right tool, what is an absolute bare bones httpclient config so I can test this out? Not worried about throwing exceptions or anything else other than just GETing API data and feeding it to a jQuery client.
I guess one other piece of information that would be nice would be building username / password authentication into the http request.
Any help is much appreciated, as are links to any good blogs / tutorials / etc that might help as an introduction to this sort of thing. I've watched several today alone, and I'm still not able to get a basic http request going on the server side without resorting to cutting / pasting other people's code.
Thanks in advance!
** EDIT - To make this question a bit more clear, what I'm trying to test is 1) Can the proxy connect to the third party server, which involves authentication via a username and password 2) Can the proxy then respond to the jQuery client request with the JSON data it received from the third party server.
Thanks to all who have taken the time to respond.
HttpClient seems to be ok in this job.
About the minimal config- it depends on what the third party expects. In most cases would work out-of-the-box, but there always may be some minor tweaks like headers and/or auth code.
I have just found some blog entry where some author shows how to test such a proxy and shows the proxy code too. Please see: http://www.davidbreyer.com/programming/2014/10/11/create-fake-responses-to-rest-service-calls-in-c/
You can find info about sending credentials here: How to use credentials in HttpClient in c#?
HTH
EDIT:
this sample code should work (copied from blog above and modified):
public class Proxy
{
public async Task<ExampleDto> GetExample(int id)
{
var client=new HttpClient();
//set some auth here
//set other headers
var response = client.GetAsync(
string.Format("/api/restserviceexample/{0}", id))
.Result.Content.ReadAsAsync<ExampleDto>();
return await response;
}
}
It's so simple that you can just run it and see if the other server responds. If not, you can play with headers - since all the session info and user auth info are sent using ookies and/or headers, all you have to do is to see how it's made with regular browser and then fake it on the server. Probably best tool for this job will be Fiddler.
However - there is one thing to consider. If the other service has special method for authorization (other than passing credentials with each request) the whole thing becomes tricky, since your proxy should perform authorization using their service, then store their auth cookie on the server or propagate them to the browser and attach them with all next requests.
First, you don't need ASP.NET with C# if you really want minimal.
.NET has great http handling without ASP. Check out classes like HttpListener, HttpListenerContext, HttpListenerRequest, etc... Yes, you'll have to write some boilerplate as your application, but these classes are pretty good.
See among others:
http://www.codeproject.com/script/Articles/ViewDownloads.aspx?aid=599978
Second, if you want user & password, I'd checkout using oauth authentication so you don't have to deal with them directly. Google Plus, Windows Live, Facebook, etc... all have similar OAuth 2.0 APIs for that. See among others:
http://msdn.microsoft.com/en-us/library/dn659750.aspx
https://developers.google.com/+/web/signin/server-side-flow
https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow/v2.2

How can I implement ServiceStack.net rest call over HTTPS?

I would like to authenticate users of my servicestack.net rest services using basic auth over HTTPS.
Can anyone explain how the https portion of this would work or point me in the right direction? Is it the responsibility of the client to ensure the calls are made over https? Do I need to do anything involving SSL Certificates to enable this?
This service will most likely live on AppHarbor if that matters.
EDIT
Can anyone cite specific examples of how to accomplish this in service stack. I think that I would be having all of the services in my api require HTTPS. Would I be able to accomplish this using request filters?
You will need to have an SSL Certificate purchased and installed to handle https (you should be able to get one from your domain name provider, which you will then need to install on your hosting server). The service clients will generally be allowed to connect by any method they choose. It will be your responsibility to stop the request and generate an error message to the client if they attempt to connect by http, instead of allowing them access.
You can validate whether they are on http or https by checking the Request.Url.Scheme property in your REST Service API. Typically, a request for http on a service that requires https will return an HTTP 403 (forbidden) status code. If you have access to IIS, you can force HTTPS easily without doing any coding: http://www.sslshopper.com/iis7-redirect-http-to-https.html
If you don't need on all services the following at the top of any service that needs the security does the job:
if (!Request.IsSecureConnection)
{
throw new HttpError(HttpStatusCode.Forbidden,"403","HTTPS ONLY");
}
However it's better to this as a filter attribute: https://github.com/ServiceStack/ServiceStack/wiki/Filter-attributes
If you want it globally, you could apply your attribute to a shared BaseService or better use a global filter: https://github.com/ServiceStack/ServiceStack/wiki/Request-and-response-filters
...Like this:
this.GlobalRequestFilters.Add((req, res, dto) =>
{
if (!req.IsSecureConnection)
{
res.StatusCode = (int)HttpStatusCode.Forbidden;
res.Close();
}
});
If you want one that redirects to https rather than reject request then you could base it on this: http://weblogs.asp.net/dwahlin/requiring-ssl-for-asp-net-mvc-controllers

Using WCF service in MonoTouch with Authentication

I am using a WCF service client generated by slsvcutil form Silverlight toolkit version 4. I've also tried version 3 with the same problems. When I use a client instance running on http with no user credentials it runs without problems. But I need to switch to https for productive servers and send user credentials that are hardcoded for my application. I use the following code for that:
var binding = new BasicHttpBinding (BasicHttpSecurityMode.TransportCredentialOnly);
var endpoint = new EndpointAddress (AppSettings.FlareEndPoint);
_service = new TopicAnalystAPIClient(binding, endpoint);
_service.ClientCredentials.UserName.UserName = "xxx";
_service.ClientCredentials.UserName.Password = "xxx";
When I call a method on that service pointing to http with no authentication it works. When I use the this code against http/https with the credential I get "There was an error on processing web request: Status code 401(Unauthorized): Unauthorized" exception. I've checked that the credentials are correct, I am able to open the service reference in my browser. I've also tried several combinations of http/https and SecurityMode value. I've also tried it on four different servers always with the same result.
What can be the problem?
A lot of permutations are possible. BasicHttpSecurityMode.TransportCredentialOnly should be usable without SSL [1] using HTTP itself. This means the server will send one (or more) authentication method(s) to the client (e.g. basic, digest, ntlm) and Mono (including MonoTouch) should be providing support for the most of them.
It is possible that the linker (if used) removes one of them. In that case you could try building and testing without linking (or skip linking of System.Net.dll).
It's also possible that the authentication method that the serve insist on is not supported. You could find which one is used by running a network trace (e.g. wireshark) or, maybe, it will show up in more details in the server log (along with the 401 error).
[1] http://msdn.microsoft.com/en-us/library/system.servicemodel.basichttpsecuritymode%28v=vs.95%29.aspx

Categories