I don't do much client side web programming, so I'm trying to grasp this concept in how it relates to my specific situation.
I have a RESTful WCF service running on a port in the 50000s. Additionally, I have a bunch of web forms (not ASP WebForms) written in HTML5/CSS3/JavaScript that make AJAX calls to this WCF service. The web forms are hosted on the same host, but are using port 80. The AJAX calls made by the web forms are all GET only requests.
Additionally, I have a third-party cloud-hosted application that's in a completely different location (different host), which needs to call the WCF service as well. This communication is performing POSTs & PUTs to the WCF service.
Obviously the calls being made from the third-party hosted cloud application is cross origin. From my research it appears that the different ports are in fact different origins.
I know that security & CORS are different concepts, but here is what I'm trying to accomplish and I need to better understand how all of this works:
Right now I allow all cross-origin requests, and everything is working, but I'd like to limit it down to improve security and then eventually set up HTTPS with transport security with both the webforms & WCF service using the same certificate. The third-party cloud service hosted-app would still need to be able to communicate with the WCF service so I would need to allow it to authenticate differently, so that would be done with a secret-key being passed since everything is server-side only.
This whole communication 'triangle' feels murky to me, and I hope that SO is the right place for me to be posting this question since it isn't directly code related.
Is the WCF - web forms situation described above considered cross-origin?
A) If the above is not cross-origin, would I then only need to pass the Access-Control-Allow-Origin: 'https://my-cloud-host' in my web.config?
B) If it is I understand that just need to echo back the allowed origins(s) in the header. What do I set (if anything) for Access-Control-Allow-Origin in IIS in this case? What do I echo if it's not allowed, just the original origin?
Would my idea to use the same certificate for mutual SSL Authentication work if they are hosted on different ports? Would this prevent the cloud-service from communicating with the WCF service, or would having a second endpoint allow for this?
Am I losing my mind? I'm so confused by this whole thing.
Yes. In all major browsers except for IE, a different port IS considered to be another origin.
A) is correct. You need only to allow your port-80 origin to send requests.
I'm not sure about that. I tend to beleive that SSL is port-awared, and you can't use the same certificate on different ports.
You can read this excellent article to give your mind some rest.
Related
I have read many articles in the web so far, about the differences between WCF and ASP.Net web API. Unfortunately I could not come up to a clear idea about what will serve my purpose. Most of the Articles I have read highlighted on the design point of view of the two web services. But I am confused what will work best for my project and why? Here is my brief description of the project.
I need to create a communication channel between two servers (both are written in C#). The servers will communicate using messages (certain type of commands). The messages sometimes can be only acknowledgements, and sometimes the messages may contain instructions to do some computation. For example, one message can be draw something, or send an SMS etc. And not necessarily the messages will involve any database transactions. But the messages can sometimes send large text files as payload (around 1-5 MB maxm). What I believe WCF is very will surely do this, but can I do the same with ASP.net web API. Because so far all the example I have seen for ASP.Net web api: they are good for RESTful services that manipulate some kind of DB store (GET, PUT, DELETE). But in my case I will need to expose service points that will
do some kind of processing such as return the value of a computation, sending and acknowledging messages, etc.
Not just manipulating a DB-store.
So, what should be the best and simplest way to do so? It is needed to be mentioned that I did not find any straight forward example of achieving this using ASP.Net web API.
The Question you have asked is an overly-broad or primarily opinion-based, and its hard to give an example for what you have asked.
Important Points:
Firstly, if you are going to create a service which would be used on different platforms, then go with WCF.
Secondly, if you are creating internet service which is going to use external resource, then go with Web API.
Web API is the best choice if you are going to create a service for low bandwidth devices or mobile devices to access client.HTTP
request/response is also more readable as compared to SOAP because it
contains header, body, etc. which makes it complex.
Just take few minutes and read the below article, until you get complete understanding of few principles.
Original Source Can be found Here, Here and Here.
To whom choose between WCF or WEB API :
Choose WCF when you want to create a service that should support special scenarios such as one way messaging, message queues, duplex communication etc.
Choose WCF when you want to create a service that can use fast transport channels when available, such as TCP, Named Pipes, or maybe even UDP (in WCF 4.5), and you also want to support HTTP when all other transport channels are unavailable.
Choose Web API when you want to create a resource-oriented services over HTTP that can use the full features of HTTP (like URIs, request/response headers, caching, versioning, various content formats).
Choose Web API when you want to expose your service to a broad range of clients including browsers, mobiles, iphone and tablets.
Why to choose Web API
Web API doesn't have tedious and extensive configuration like WCF REST service.
It is very simple, creating service with Web API. Where as With WCF REST, service creation is bit difficult (requires clear understanding of configurations).
Web API is only based on HTTP and HTTPS and easy to define, expose and consume in a REST-full way.
Web API is light weight architecture and good for devices which have limited bandwidth like smart phones.
My Opinion:
Simplest way to do so - Web API (Since you dont have any examples for this)
Hardest Way is (Configurations) - WCF (Better go with WCF, since you have examples)
I hope this gives you a clear idea about what to choose...
First things first, RESTful is a stateless and uniform interface norm that can be applied to web services. It doesn't have to be automatically and only plain old CRUD service backed by a DB.
In the real world, we can hardly say that all web REST API respect fully the norm, in fact they don't most of the time, especially the stateless part.
For your message based API, especially if it's bidirectional and event based, you can use websockets and consider the REST API a way to expose an uniform, stateless web interface to create those. And yes you can use websockets with ASP.NET WebApi there's plenty of tutorial out there, even for the newer ASP.NET Core.
The "between services" interactions part is no different than the usual Web browser <=> Web service, you're just using C# code instead of JS for the client.
I can hardly recommend WCF that uses SOAP since it's hardly portable considering the web standards nowadays. For instance if want to use a browser client instead of another ASP.NET service, well you'll have to do additional code client side to handle supports.
You can use WCF websockets, providing the almost all the advantages of WCF SOAP.
tl;dr :
You can mix RESTful and Websockets, it can actually be better than going full REST or full Websockets
It's personal preference to use SOAP over websockets but do comes with a potential technical debt considering what you want to do afterwards
Message API between services is no different than a message API between a service and a browser
WebAPI is not just good for RESTful webservices. You can easily send requests to a WebAPI controller and handle it the way you want : calculations, sending messages, interact with a CRM, interact with DB or anything else.
WCF was created to manage SOAP based webservices and brings extra complexity. It handles TCP, Mime...
If you just need to handle HTTP requests, the simplest way is to go with WebAPI.
I would suggest Web API if it is for RESTful services as WCF was never made to serve as Restful services although you can serve as one where as Web API was made particularly for this.
I have a Windows Service application written in C# which performs a number of tasks in the background. As a side-feature, the application offers interfaces for UI clients to connect to (currently a WPF client application). This is mainly WCF Data Services (OData) and WCF services for now, but may also include serving web pages (through embedding ASP.NET) so a browser could be used to access the service.
All of this works pretty well, with self-hosted services through ServiceHost+WSHttpBinding and DataServiceHost+WebHttpBinding, which is all setup in code (since it is somewhat dynamic/flexible).
Now I started to look into authentication and worked myself through setting up a basic authentication with a custom name/password validator through MessageCredentialType.UserName, UserNamePasswordValidationMode.Custom, etc. Now clients need to provide correct username/password which is validated against an application specific user list. This also works well, with something like
webHttpBinding = new WebHttpBinding(WebHttpSecurityMode.TransportCredentialOnly);
webHttpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
serviceHost.Credentials.UserNameAuthentication.UserNamePasswordValidationMode = UserNamePasswordValidationMode.Custom;
serviceHost.Credentials.UserNameAuthentication.CustomUserNamePasswordValidator = new UserRepositoryPasswordValidator { UserRepository = UserRepository };
serviceHost.Authorization.PrincipalPermissionMode = PrincipalPermissionMode.Custom;
However, as I understand, without any kind of transport security, username/password as well as any data is being transmitted in plain text between client ans service, which is not desirable. I have therefore tried to find a way to use a secured/encrypted communication. This sounds like ssl/https would be the way to go.
I went through a number of articles to find out how to do this, but find the approach overly complicated and confusing. My application obviously does not use IIS or another web server, so many articles and posts do not seem to apply to my scenario.
Also, the application in question should be deployed/installed onto different target machines and "just run" without the need to tweak any operating system aspects. I was highly confused to see that using ssl/https requires to run netsh commands to register the certificate with the port, etc. Why is this so complicated?
I can accept that the certificate used for ssl/https would not be a highly trusted one, since it would be impractical to create a new certificate for every target machine my software gets installed on (most of which I do not even control or ever see).
Does anyone have instructions about a good acceptable strategy to get my current C# Windows Service with self-hosted WCF/WCF Data Services to use ssl/https without too much trouble and without complicating the installation process of my app?
J.-
I have a challenge and I believe there is a developer smarter than me that can provide some insight.
I have a web service. This web service is written with ASP.NET MVC in C#. I want to allow developers to call this web service. When developers are writing code, I recognize that web apps typically run from localhost. When they call this service, I want to be able to identify if the request is coming from localhost. However, if I look at the IP address, its the IP address of their machine.
Is there a way for me to even do this? Clearly Request.IsLocal won't work as my web service is running on an entirely different machine.
When you call a web service, the browser usually passes the page in the Referer header. So you can check if that value starts with "http://localhost". Virtually anything in an http request can be forged (including this), so be careful what kind of decisions you make based on this data.
Without passing some additional data along with the request from the app, there's not going to be any way for you to know.
You'll only be able to get the IP address or Host name that was used to make the request to your Web Service and it sounds like you want to be able to find the Host Name (localhost) that was used to make the request to the app (which then triggers the call to the Web Service).
How will you then define local (from the perspective of your service)? You'd be better off setting up a development service on a different API end point instead of attempting to guess this.
All production level API calls can go to something like api.yourservice.com with all development level requests coming in via dev.yourservice.com.
You can then have two separate services or have your service read the URL being requested and differentiate based on this.
I want my web app (running in a browser) to, at some point, communicate (bidirectionally) with a desktop app (in Windows), the client has installed in its computer.
What's an elegant and modular and simple way of doing this (with Java and C#)?
Not much information will be passed between the web app and the desktop app. Just something like "I was here", "Pick this from this point", etc.
I solved that problem by using a database on the network.
All communications where made trough the database.
Website -> DB -> User logged in <- DB <- Desktop
However, if no trusted information needs to be shared, you could consider just posting and reading some http headers to a common website, or a simple log file.
Greetings
I suggest you to use the backend part of your webapp, assuming that your app is based on some backend services.
You have two options:
Your desktop apps use the same services of your web app. You must use a class that mimic a web-browser to give the data (curl, ie). If your web app is based on AJAX push ( APE Server i.e ) use library that is able to run some javascript
Use a REST protocol, with a JSON format in your backend services. It's easy to manage and is supported by many client-side languages (java/c#/python....)
Use a specialized endpoint only for your desktop app,for C#, you can use WCF, that allow you, in one of his forms bidirectional communications. For JAVA, there are WSDL, DWR
My preferred solution is to decouple the web app in a front-end side and a backend side, that expose the services as REST that are used by the web app via AJAX.
If I need true bidirectional communication with other desktop app, I'll create a separate service / endpoint for it. (APE , WCF, ..)
I see several options to achieve part of what you are asking:
Besically you expose the relevant parts of your apps (web and desktop) via some sort of API and use that for the communication - for example DB and/or WCF (SOAP/REST/whatever).
BEWARE:
If you are after some sort of direct/interactive communication between both apps on the same computer then this won't be possible - at least not without some security related issues.
The browser executes your web app in a sandbox which doesn't allow for direct communication between the web app and the desktop... there are technologies which can help circumvent that (ActiveX, signed Java applets, some Flash technology called AIR etc.)... or you could host some webbrowser/control in your desktop app which in turn runs the web app... BUT basically I would recommend against using any such measures...
IF you really want to go this route then please describe your environment and goal with much more detail.
Disclaimer: I've tried Googling for something that will do what I want, but no luck there. I'm hoping someone here might be able to lend a hand.
Background
I have a .NET class library that accesses a secure web service with the WSE 2.0 library. The web service provides a front-end to a central database (it's actually part of a data-sharing network spanning multiple customers) and the class library provides a simple wrapper around the web service calls to make it accessible from a legacy VB6 application. The legacy application uses the class library to retrieve and publish information to the web service. Currently, the application and class library DLL are both installed client-side on multiple workstations.
The Problem
The catch is that the web service we are accessing uses HTTPS and a valid X509 client certificate needs to be presented to the web service in order to access it. Since all of our components live on the client machine, this has led to deployment problems. For example, we have to download and install per-user certificates on each client machine, one for each user who might need to access the web service through our application. What's more, the web server itself must be accessed through a VPN (OpenVPN in particular), which means a VPN client has to be installed and configured on every client machine. It is a major pain (some of our customers have dozens of workstations).
The Proposed Solution
The proposed solution is to move all of this logic to a central server on the customer site. In this scenario, our legacy application would communicate with a local server, which will then go off and forward requests to the real web service. In addition, all of the X509 certificates would be installed on the server, instead of on each individual client computer, as part of the effort to simplify and centralize deployment.
So far, we've come up with three options:
Find a ready-made SOAP proxy server which can take incoming HTTP-based SOAP requests, modify the Host header and routing-related parts of the SOAP message (so they are pointing to the real web server), open an SSL connection to the real web server, present the correct client certificate to the server (based on a username-to-certificate mapping), forward the modified request, read the response, convert it back to plaintext, and send it back to the client.
Write a proxy server by hand that does everything I just mentioned.
Think of completely different and hopefully better way to solve this problem.
Rationale
The rationale for trying to find and/or write a SOAP proxy server is that our existing .NET wrapper library wouldn't have to be modified at all. We would simply point it at the proxy server instead of the real web service endpoint, using a plain HTTP connection instead of HTTPS. The proxy server will handle the request, modify it to so that the real web service will accept it (i.e. things like changing the SOAPAction header so that it is correct), handle the SSL/certificate handshake, and send the raw response data back to the client.
However, this sounds like an awful hack to me me at best. So, what our my options here?
Do I bite the bullet and write my own HTTP/SSL/SOAP/X509 aware proxy server to do all this?
Or...is there a ready-made solution with an extensible enough API that I can easily make it do what I want
Or...should I take a completely different approach?
The key issues we are trying to solve are (a) centralizing where certificates are stored to simplify installation and management of certificates and (b) setting things up so that the VPN connection to the web server only occurs from a single machine, instead of needing every client to have VPN client software installed.
Note we do not control the web server that is hosting the web service.
EDIT: To clarify, I have already implemented a (rather crappy) proxy server in C# that does meet the requirements, but something feels fundamentally wrong to me about this whole approach to the problem. So, ultimately, I am looking either for reassurance that I am on the right track, or helpful advice telling me I'm going about this the completely wrong way, and any tips for doing it a better way (if there is one, which I suspect there is).
Apache Camel would fit the bill perfectly. Camel is a lightweight framework for doing exactly this kind of application integration. I've used it to do some similar http proxying in the past.
Camel uses a very expressive DSL for defining routes between endpoint. In your case you want to stand up a server that is visible to all the client machines at your customer site and whatever requests it receives you want to route 'from' this endpoint 'to' your secure endpoint via https.
You'll need to create a simple class that defines the route. It should extend RouteBuilder and override the configure method
public class WebServiceProxy extends RouteBuilder
{
public void configure()
{
from("jetty:http://0.0.0.0:8080/myServicePath")
.to("https://mysecureserver/myServicePath");
}
}
Add this to a Camel context and you'll be good to go.
CamelContext context = new DefaultCamelContext();
context.addRoute(new WebServiceProxy());
context.start();
This route will create a webserver using jetty bound to 8080 on all local interfaces. Any requests sent to /myServicePath will get routed directly to your webservice defined by the uri https://mysecureserver/myServicePath. You define the endpoints using simple uris and the dsl and camel takes care of the heavy lifting.
You may need to configure a keystore with your certs in in and make it available to the http component. Post again if you've trouble here ;)
I'd read the camel docs for the http component for more details, check the unit tests for the project too as they are chock full of examples and best practices.
HTH.
FYI: To have the http component use your keystore, you'll need to set the following properties
System.setProperty("javax.net.ssl.trustStore", "path/to/keystore");
System.setProperty("javax.net.ssl.trustStorePassword", "keystore-password");
You should look into WCF, which supports the WS-Addressing protocol. I believe I've seen articles (in MSDN, I think) on writing routers using WCF.
You should also get rid of WSE 2.0 as soon as possible. It's very badly obsolete (having been replaced by WSE 3.0, which is also obsolete). All of its functions have been superceded by WCF.
I believe an ESB (Enterprise Service Bus) could be a viable, robust solution to your problem. There is an open source ESB called Mule, which I've never used. I did mess around with ALSB (AquaLogic Service Bus) a while back, but it would be expensive for what you are describing. Anyway, the thing that you would want to look at in particular is the routing. I'm not sure it would be a simple plug 'n play, but it is indeed another option.
You can also do this with Microsoft ISA Server, a commercial Proxy/Cache server. It will do many of the things you need out of the box. For anything that is not possible out of the box, you can write an extension to the server to get it done.
ISA Server is not free.
ISA is now being renamed to "Microsoft Forefront Threat Management Gateway".
It is much more than a web proxy server, though - it has support for many protocols and
lots of features. Maybe more than you need.
There is a service virtualization tool from Microsoft available on Codeplex called the Managed Service Engine which is intended to decouple the client from the web service implementation. It might fill the bill or give you a running start. I haven't really investigated it thoroughly, just skimmed an article in MSDN and your description reminded me of it.
http://www.codeplex.com/servicesengine
http://msdn.microsoft.com/en-us/magazine/dd727511.aspx
Your security model doesn't make sense to me. What is the purpose of using HTTPS? Usually it is to authenticate the service to the clients. In that case, why does the server need to keep the clients' certificates? It is the clients who should be keeping the server's X509 Certificate.
Why do you need to go through VPN? If you need to authenticate clients, there are better ways to do that. You can either enable mutual authentication in SSL, or use XML-Security and possibly WS-Security to secure the service at the SOAP level. Even if you do use SSL to authenticate clients, you still shouldn't keep all the client certificates on the server, but rather use PKI and verify the client certificates to a trusted root.
Finally, specifically for your proposed proxy-based solution, I don't see why you need anything SOAP-specific. Don't you just need a web server that can forward any HTTP request to a remote HTTPS server? I don't know how to do this offhand, but I'd be investigating the likes of Apache and IIS...