I can prevent other web sites (e.g. example.com) access and use my server resources via WebSocket. I mean they cannot access the server by pointing to something like "ws://47.80.151.189:1234" and use its resources (bandwidth, memory) or receive data sent from it. It’s a node.js server.
However, my local computer can still receive data sent from that WebSocket url. It can still receive data even in this file location: file:///D:/test.html
I don't want the data exposes to anyone. So how can I prevent this and thank you.
You can restrict browsers connecting by checking the origin HTTP header.
When a JavaScript script running in a browser opens a WebSocket connection to some server, it will set the origin header to the URL (well, host) of the original HTML that contained the JavaScript that opens the WebSocket.
Note that non-browser clients are not required to provide an origin header and/or can fake to anything.
You can also restrict of course based on source IP of the connecting client. Or you can require some kind of authentication.
Related
Could you please advise on the following?
Let's assume I have a local html page stored on my local drive "c:\test.html".
If I open it in a browser, it's treated as a GET request to this page, right?
Is it possible to send, for example, POST request to the same local page, with "fetch"?
And inside "c:\test.html" to check if it was requested with POST method, return something?
It would be something like a local-PC API.
Static HTML pages do not have any request capabilities. What's actually happening here is that there is some sort of server that takes your request and responds with the HTML document. You would need to host your own server of some sort that could take and respond to requests. For this, libraries like express.js work well.
Edit: If you are accessing it through a file:// url, your browser is just reading the file off your drive directly, so you would need some sort of localhosted server.
This is not how it works. When you open a file with your browser, it uses a file protocol, not a HTTP protocol. Look at the URL. You'll see what kind of protocol was used to retrieve the resource.
So no, you cannot sent a fetch request to a local file. You have to establish a proper sever in your localhost and let it handle requests. Local files do NOT handle requests. Servers do.
I know there are no standard JS WebSocket APIs for the same. My main aim is to send the info like resourceId, routingInfo, auth-token, protocol etc. from JS web-socketclient to the server.
I could think of below few approaches. Kindly share the thoughts if my approach is fine or is there any other better approach:
Can we use cookies for sending the custom headers from client and retrieve them in server side?
Can we use web-storage API for storing them in the browser and retrieve them on server side?
PS: I am using a Java based server
Assuming you're talking about a webSocket connection from a browser, here are your traditional choices for sending additional "header-like" information.
You can encode them as a query parameters on the initial URL which might be fine for everything except auth-token.
If the origin you are connecting the webSocket connection is the same as the origin of your web page, then you can put the parameters into cookies and those cookies will be sent with the original webSocket connection request where the server can retrieve them upon the connection request.
You can make a "conditional" webSocket connection to the server and then send credentials in subsequent webSocket messages. You'd have to implement safety for that on your server so that the "conditionally" connected webSocket was not allowed to do anything else except authenticate itself and probably timeout the connection if appropriate credentials do not arrive shortly.
As it sounds like you may already know, the browser interface to webSockets does not allow custom headers on the initial HTTP request that starts the webSocket connection. Those custom headers are possible from some other kind of client - it's just that the browser interface to a webSocket connection does not have that feature.
Can we use web-storage API for storing them in the browser and retrieve them?
The Javascript in your web page can use the web-storage API to store data in the browser and that data can be retrieved later from another script in a page from the same origin. That data is not available to the server, it is only available within the client.
I have a home server in domainX, it returns HTML page containing
js part, which should GET data from domainY.
I can't control domainY return, which means that it it will not return any Allow-Origin headers etc.
I can't use JSON either because domainY does not support it.
postMessage may not work either, because I need to make search query
https://domainY/cars=blue&price_max=10000 etc.
I guess GET is the only way (XMLHttpRequest). I would like to avoid cors proxy because I try to keep server IO usage as low as possible.
Is there any tweak I could try without doing everything in the server side?
NO
The Same Origin Policy is designed to protect information that is private between the owner of the browser and the owner of domainY.
You can't get the browser to fetch arbitrary data (with the benefit of the browser's cookies and the browser's IP address) and then make it available to your JavaScript.
domainY might me my webmail, e-banking, or secure corporate Intranet. You aren't allowed to touch it using my browser.
I've setup a remote, hosted javascript server (DreamFactory Server http://www.dreamfactory.com/) that responds via REST API's.
Locally, I'm running an Angularjs application through the grunt web server via $grunt serve
https://www.npmjs.com/package/grunt-serve
I have setup CORS on the remote server to allow '*' for multiple http:// connection types. THIS WORKS CORRECTLY.
My question is how I can limit the CORS configuration to only allow a connection from my home, grunt web server?
I've tried to create an entry for "localhost", "127.0.0.1", also my home Internet IP that is reported from whatismyip.com, the dns entry that my provider lists for my home IP when I ping it, a dyndns entry that I create for my home internet IP... None of them work, except for '*' (which allows any site to connect).
I think it is an educational issue for me to understand what that CORS entry should look like to allow ONLY a connection from my home web server.
Is this possible? If so, what and where should I be checking in order to find the correct entry to clear in the CORS configuration?
-Brian
To work and actually apply restrictions, the client requesting the connection must support and enforce CORS. In an odd sort of way (from a security point of view), restricting access using CORS requires a self-policing client (one that follows the prescribed access rules). This works for modern browsers as they all follow the rules so it generally works for applications that are served through a browser.
But, CORS access restrictions do not prevent other types of clients (such as any random script in any language) from accessing your API.
In other words, CORS is really about access rules from web pages that are enforced by the local browser. It doesn't sound like your grunt/angular code would necessarily be something that implements and enforces CORS.
If you really want to prevent other systems from accessing your DreamFactory Server, then you will need to implement some server-side access restrictions in the API server itself.
If you just have one client accessing it and that client is using "protected" code that is not public, then you could just implement a password or some sort of logon credentials and your one client would be the only client that would have the logon credentials.
If the access is always from one particular fixed IP address, you could refuse connections on your server from any IP address that was not in a config file you maintained.
You can't secure an API with CORS, for that you will need to implement an authentication scheme on your server. There's essentially 4 steps to do this.
Update the headers your server sends with a few additional Access-control statements.
Tell Angular to allow cross-domain requests.
Pass credentials in your API calls from Angular.
Implement an HTTP Authentication scheme on your web server or in your API code.
This post by Georgi Naumov is a good place to look for details of an implementation in Angular and PHP.
AngularJS $http, CORS and http authentication
I have a browser based app that needs to communicate with another service running on the client machine via a socket connection from the browser using JavaScript.
I need to post and parse XML back and forth on the socket.
I am unable to go down the flash path as the cross domain security is a barrier, ie the service running on the socket is not able to be modified to support Flash's crossdomain security.
What are my options for a pure JS based solution?
You've got two major problems here:
It's difficult in javascript to access non HTTP resources,
It's difficult in javascript to access resources not loaded from the same server.
There are exceptions to both of these, but the conjunction of exceptions available might not exactly match with what you need. Here are some possibilities:
Some sort of proxy on your own server that connects back to the machine with the XML service on behalf of your web app.
If you can control the client machine somewhat you can run a server on it that can embed the XML in a JSONP formatted http response, you can access by adding simple script tags, and send messages the other way by using a script tag to request a url with your data encoded into it.
If when you say 'socket' you're referring to an HTTP connection, then there are a number of options, one is to add a Access-Control-Allow-Origin header to the HTTP, then you can do gets and posts using normal XMLHttpRequests in recent browsers.
Javascript will not allow you to create a socket connection to the client. It would violate the same origin policy. If you could somehow save an applet/swf to the local machine you could serve it up as file:/// and it could communicate to localhost (maybe! not tested).
Maybe creating a proxy to go in front of this unmodifiable socket server could open up some options for you. You could then use something like flash, or you could just not use sockets.
Your options for socket based interaction is limited to plugins that support such live functionality. The options generally break down as follows Flash, Java and Silverlight. All of which aside from Java, if I recall correctly, will have similar policy requirements.
If you control your own server, you could create a socket service to proxy the request to the final destination. Or, depending on the interaction, you can use standard Ajax-style requests and have the socket interaction on your server-side code. If you don't need a persistent connection, having the socket interaction via the server is your best bet.