In a in WinRT app, how do I connect using TLS1.2? - windows-runtime

I've got a Windows Store app that's a WinRT Phone/Desktop app (i.e. not a UWP app), targeting Windows 8.1 and up.
It's been on the store for several years now, but recently it stopped being able to connect with various web APIs and websites (YouTube, as well as my own site) using HTTPS.
I have a WPF version of this app as well, and this happened on that app recently as well, and to fix it I used System.Net.ServicePointManager. Unfortunately, in my WinRT environment, System.Net doesn't include ServicePointManager. In my WPF app, I did this, and it worked just fine:
ServicePointManager.ServerCertificateValidationCallback = delegate
{
Debug.WriteLine("returning true (the ssl is valid)");
return true;
};
// our server is using TLS 1.2
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
In doing some research around the internet, it seems that .NET 4.6 should include ServicePointManager, but I don't see any way to change (or even see) my version of .NET in the WinRT development environment.
I looked some more and found that a StreamSocket could be used to connect with TLS1.2... but that seems primarily designed to enable bluetooth communications, or communications to a web endpoint, but only by hostname... which is insufficient for me. I need to connect to an actual website, not just the base-level domain.
Trying this, I did the following:
StreamSocket socket = new StreamSocket();
string serverServiceName = "https";
socket.Control.KeepAlive = false;
url = "inadaydevelopment.com";
HostName serverHost = new HostName(url);
await socket.ConnectAsync(serverHost, serverServiceName, SocketProtectionLevel.Tls12);
text = await ReadDataFromSocket(socket);
I can include the code for ReadDataFromSocket() if necessary, but it seems to work, reading the data from the socket as expected when I point it at https://google.com. However, I can't seem to figure out how to point the socket at anything useful. The homepage of inadaydevelopment.com isn't what I want; I'm looking to consume a web API hosted on that server, but can't seem to find a way to do that.
Since the first parameter to the ConnectAsync() method is just HostName, the second parameter (remoteServiceName) must be the way to connect to the actual API or webpage I'm trying to connect to. According to the docs, that is The service name or TCP port number of the remote network destination... I haven't seen any example values for this parameter other than https and various numeric values, neither of which is going to get me to the API endpoint or webpage I'm trying to connect to.
So, with that super-long preamble out of the way, my question boils down to this:
Is there a way for me to use System.Net.ServicePointManager in my WinRT app like I do in my WPF app? If so, how?
If not, how can I use StreamSocket to connect to the exact web service or webpage I want to connect to, rather than just the top-level host?
If that's not possible, by what other means can I consume web content using TLS1.2?
Thanks in advance for any help or advice.

Use Windows.Web.Http API instead of System.Net.Http API.
System.Net.Http does not support TLS1.2 but Windows.Web.Http does in WinRT apps.

Related

C# WebRequest to a URL that is configured for Windows Authentication

I am trying to get user photos out of Microsoft Exchange using the GetUserPhoto REST request documented here: https://msdn.microsoft.com/en-us/library/office/jj190905%28v=exchg.150%29.aspx?f=255&MSPPError=-2147217396
My problem is no matter what I do the connection gets closed automatically and it can't authenticate using NTLM. Microsoft even provides code but when you run this in a IIS web application even if it is using an application pool running as a domain user, it never can authenticate.
This is my current code that isn't working:
request = System.Net.WebRequest.Create($"https://{Settings.ExchangeServer}/ews/exchange.asmx/s/GetUserPhoto?email={primarySmtpAddress}&size=HR240x240") as System.Net.HttpWebRequest;
request.ServerCertificateValidationCallback = delegate { return true; };
request.UseDefaultCredentials = true;
resp = request.GetResponse() as System.Net.HttpWebResponse;
Now I can put this in a console application and run it and then it works. But in IIS it just won't work at all. I've even tried RestSharp with no luck.
Sounds like a delegation issue eg the credentials your impersonating can only be used to access resources local to the IIS server they are being impersonated on. For you to access Exchange you need to have delegation configured correctly see https://blogs.msdn.microsoft.com/emeamsgdev/2012/11/05/ews-from-a-web-application-using-windows-authentication-and-impersonation/
The problem was it wasn't trying to connect with TLS 1.2. Once it clicked in my head, the error message was saying the connection closed and not actually returning a 401. I user ServiceManager to set it to TLS1.2 and then it started working.
Glen Scales help point me in the right direction though to troubleshoot it further.

Web API call not returning

I have a RESTful Web API that is running properly as I can test it with Fiddler. I see calls going through, I see responses coming back.
I am developing a tablet application that needs to use the Web API in order to fetch data or make updates in the repository.
My calls do not return and there is not a single trace in the Fiddler to show that my calls even reach the server.
The first call I need to make is to login. The URI would be this:
http://localhost:53060/api/user
This call would normally return some information about the user (such as group membership, level of authorization and so on). The Web API uses Windows Authentication, so the repository is able to resolve all these fields based on the credentials passed in. As I said, in Fiddler I see the three calls made to the URI as the authentication is negotiated between the caller and the server. The third call returns with a JSON object that contains all information generated from the repository as expected.
Now, moving to my client I have the following:
var webApiClient = new HttpClient(new HttpClientHandler()
{
UseDefaultCredentials = true
})
{
BaseAddress = new Uri("http://localhost:53060/")
};
webApiClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await webApiClient.GetAsync("api/user");
var userLoginInfo = await response.Content.ReadAsAsync<UserLoginInformation>();
My call to "GetAsync" never returns and, like I said, I see no trace of it in Fiddler.
Any idea of what I'm doing wrong?
Changing the URL where the Web API was exposed seemed to have fixed the problem. Thanks to #Nkosi for the suggestion.
For anyone stumbling onto this question and asking themselves how to change the URL of the Web API, there are two ways. If the simulator is running on the same machine with the Web API, the change has to be made in the "applicationhost.config" file for IIS Express. You can locate this file by right-clicking on the IIS Express icon in the Notification Area (the bottom right corner) and selecting show all websites. Highlight the desired Web API and it will show where the application host configuration file is located. In there, one needs to locate the following section:
<bindings>
<binding protocol="http" bindingInformation="*:53060:localhost" />
</bindings>
and replace the "localhost" name with the IP address of the machine where the Web API is running.
However, this approach will not work once you start testing your tablet app with a real device. IIS Express must be coerced into exposing the Web API to the outside world. I found an excellent node.js package that can help with that. It is called IISExpress-proxy.

How can Firebase be used for WebRTC signalling?

I've achieved a successful WebRTC connection using Firebase - but it only works if both users are on the same local network. I've tried using using different STUN servers, and even used TURN, but with the same result.
Is there any sample code or any place which shows how to achieve basic signalling for WebRTC using Firebase? I've tried looking at the docs, and there doesn't seem to be. What confuses me more is that my app works in the local network, but not outside of it.
Btw, I've also used PubNub and I've no problem using that to achieve signalling (even across networks).
I've set up a reference to my data like this
myDataRef = new Firebase('https://<myapp>.firebaseio.com');
myDataRef.on('value', function(snapshot) {
var json = snapshot.val();
and I communicate messages like so:
myDataRef.set(json);
The json message will include the action type (candidate, or offer or answer) and will also include the SDP, if required.
Any help on this will be appreciated!

Adobe AIR, URLRequest, and local ports

I'm looking at writing an app with Adobe AIR, but I wanted to figure out if this is feasible with the platform first. (Mostly new to Flash and AIR)
What I would like to do is know ahead of time what local port a URLRequest will be using. If possible, I would like to hold a connection open even and keep using the same socket.
What I'm basically trying to accomplish is doing some NAT-Traversal and port negotiation ahead of time. Once I have both the client and the server negotiated, I'd like them to connect and basically use HTTP in a peer-to-peer way to stream media, like this sample:
var s = new air.Sound();
var url = "http://www.example.com/sounds/bigSound.mp3";
var req = new air.URLRequest(url);
var context = new air.SoundLoaderContext(8000, true);
s.load(req, context);
s.play();
The problem is that I don't see this happening unless I can get some information from AIR on what ports it's planning to use. I would be OK with creating my own Socket connections to the server and using them, but I would need a way to leverage the Sound framework to stream in the same way from a socket.
Ideas? Thoughts? Thanks!
Even if you managed to guess which port AIR is going to use on your device, it is not going to be very helpful, since there is a reasonably high probability that your NAT will translate it to another value IF your AIR device has a private IP address.
This issue does not happen if your AIR server has a public IP address. Most often, you can configure the server's NAT/Router to forward traffic as is. A port scan from the WAN will quickly tell you which port is used.
If you want to 'hijack' an outbound connection created by AIR itself, then you might try to have it contact a special server peer you have implemented which will forward traffic from and to it. Not simple, but possible. Basically you would collect holes punched in the NAT by the server.

Starting multiple HTTP listeners on IIS using C#.NET 2.0

I have two windows services running on the same machine. Both the services uses
private HttpListener listener;
I specify the baseURL as "http://IPAddress:8080/" & "http://IPAddress:8081/" respectively for each of the services. Then I do the needful and call
listener.Start();
The first service starts successfully at 8080 port. But when I now start the 2nd service,
I get HTTPListenerException "The process cannot access the file because it is being used by another process" for listener object.
Could anybody please tell me:
1) If it is possible to start two HTTP listeners on the same IIS at two different ports.
2) If yes, how can we achecive this?
3) Is there any other way of doing this?
For your information:
I am using C#.NET 2.0 and IIS 6.0 server.
Thanks & Regards,
Hari
Doesn't HttpListener work independently from IIS? Can you stop the IIS service and see what happens?
Or maybe port 8081 is used by another program or process. I suggest to try to set the port to another number. You could open a command line and execute the "netstat" command to see if the port is used before starting your services.
(source: googlepages.com)
The HTTPListener is indeed not a part of the IIS. It's just C# code.
did you do it like this?
String[] prefixes = { "http://localhost:8280/", "http://localhost:8281/"};
HttpListener listener = new HttpListener();
listener.Prefixes.Add("http://localhost:8280/");
listener.Start();
1) If it is possible to start two HTTP listeners on the same IIS at two different ports.
Yes, it is. But listeners on the IIS is not made through code, it's through the IIS administration tool, so that's probably not what you're trying to do. IIS is separate from the c# code you're attempting.
2) If yes, how can we achecive this?
Try some other port numbers (like 58080 and 58081) and try replacing "IPAddress" with "localhost". Most likely your port number is used by some other web server
3) Is there any other way of doing this?
If you're trying to serve web pages, you probably wan't to make a web application instead of making your own HTTP server
If you're doing something custom, you might want to take a look at WCF (Windows Communication Foundation), as it's the new framework for web, sockets, web services etc. and it's what MS will be using going forward
It's usually a good idea to take a quick look at this page when using port numbers...just to make sure a temp number you're trying to use isn't in use already.