I have an Angular JS app, wherein the back end is built in .NET. To fetch the data I call the exposed API controller methods from .NET project.
While calling the controller methods, I need to add "http://localhost:port" at the starting of controller method path. So my complete URL is something like:
http://localhost:port/api/controller/method
This seems obvious to me. However, while migrating this app to higher environments, I manually need to replace this string with the IPs of environment server. SO that same URL on PROD becomes:
http://PROD-IP:port/api/controller/method
Although this too makes sense, my queries are as below:
Should not localhost point to the server automatically. I mean if I deploy my app on 127.0.0.1 on every environment, then localhost:port should work fine in each case, and I need not to replace the IP for each environment. (This is my opinion and this approach is not currently working)
Is there a way in JS to fetch the IP address from the current URL. So that, a user enters the app URL at beginning and later for all back end call, I get the server URL. I tried document.location but it didn't work as expected.
I tried looking for solutions on various blog, but probably I couldn't frame correct words and didn't get any relevant solution.
JavaScript doesn't have any concept of hostnames or IP addresses. You would have to use an external service to resolve an IP address from a hostname.
You can get the domainname using location.hostname and then use some external webservices to lookup its IP
Related
Please help me rephrase the question if it doesn't fully reflect what I want.
I have an app that consists of:
1)Go server API
2)Go server Frontend that utilizes API's endpoints
3)Docker container that runs both servers
During development I had localhost set statically in multiple places, such as:
1)In the API server for enabling CORS in order for Frontend to be able to communicate with the API
Example:
func enableCors(w *http.ResponseWriter) {
(*w).Header().Set("Access-Control-Allow-Origin", "http://localhost:8080")
(*w).Header().Set("Access-Control-Allow-Credentials", "true")
}
2)In the API server for redirecting to and from the API in order to authenticate the user
3)In the Frontend server JavaScript part to access the API
4)In Google API Authorized redirect URIs as:
http://localhost:8001/oauth/authenticate?method=google
For the first time I want to make my application operate in a more production like way.
If every time someones downloads my application and builds a docker image from it the resulting container would have a different external IP address how should I set up my code structure to look like in order to account for this dynamic IP?(Especially with Google cloud APIs redirect for OAUTH)? Or am I fundamentally wrong and this is not possible/not wanted behavior in the first place as there usually is one server on which X application is hosted and its IP is always known and static in the real world?
The only thing I came up with if after all it is something achievable is to somehow get container IP inside the Dockerfile and then set it to an Environment variable that would then be used by both servers but that still doesn't solve the Google API OAUTH static allowed redirect URI problem. Hopefully, I was able to convey what the problem is because I have had trouble phrasing it.
Progress:
So far I have managed to set environment variable through a shell script during docker build like so:
export SERVER_IP=$(hostname -I | xargs)
and for the JavaScript I used webpack plugin Dotenv with systemvars parameter set to true to capture system env and incorporate it into JS.
It is enough to ask users of your app to complete config file. They must write their own APIKey at least, and I think they will configure their Google API and can easily get their IP(or just writes their static domain name). You must only inform users in README.
I quick question!
I have a webapp that only fetches data from an API so i dont have i backend part. My question is where do you keep your API key? Accordingly to React docs you should not store API keys in the app so how do you manage this when you have an webapp that consumes an API and you have to use the API key in your get requests?
Let's do a bit of explanation, so you connect the dots and design it more robustly. There are two (three) places where to store it in the end:
frontend (your React application)
backend (your server)
third-party service
TL;DR: use non-frontend solution + rate limiting to a registered user and have the registration step secured properly (+ captcha).
Frontend
Storing anything on the frontend side is mostly a bad idea, unless you're completely sure you can allow such data to be exposed - constants, names, icons, maybe some URLs so you don't have it hardcoded in the JS files.
Your "compiled" ReactJS (or any other framework) when built is just a slightly mangled (minified/transpiled/etc etc) JavaScript, but for that to work the client has to retrieve it and have it executed in the browser. Therefore before the ReactJS application even starts, there are 1+ requests downloading the JavaScript code and other parts of the application depending on the framework.
Those you can see in the network monitoring tab in any modern browser or simply use Wireshark (unless encrypted, then it's a little bit annoying) or a local proxy if using a less sane browser.
After retrieval you can simply try Ctrl+F or any online deminifier/deobfuscator if you don't know how to do it yourself and you can retrieve the key.
Implications when retrieved
I can impersonate you for the service that issues the API key
I can lock your key/account by calling too often (just for fun or to retrieve some info)
I can use your web for scraping while not needing to pay for the API key (if paid) or to register to such service vendor
If it's per-request API key and there's some limitation that would make it cost you money, I can just run some silly while (true) { callYourApi() } via a service to make me anonymous just to make it cost you
Depending on the API key and how serious you intend to approach this problem, you might utilize the .env file for development purposes only. Though you should never ever store an API key in the frontend unless you explicitly have to store it in there (e.g. maps) because it's mostly a very stupid idea and allows anyone to misuse it.
Backend
Your server, if properly configured and secured, will store the key anywhere which isn't accessible by simply path traversing (if in a file) or scraping (if you attempt to retrieve the key to execute on the frontend part).
Therefore the most sane and secure way would be to retrieve the data (of any service) by having either a custom API or a scheduled script collecting the data, which when your frontend gets called will be able to retrieve as pre-rendered or already fetched, thus no key needed for that case.
However! There's a trick to that. If you design your custom API as /api/<key>=123 or /api/<param> and you use that parameter for the original API to filter on frontend, the attacker couldn't care less for the API key because you've already created an API for free and made it public and unsecure.
So GET /yourapi/<my data> and API key for free without even needing to have one displayed.
How to do it safely? Two simple approaches:
pre-rendering data to HTML
You then fetch with frontend and just display - but this one can be scraped, it's just a bit annoying if more complex, but that's it. Server-side rendering sounds nice, but doesn't really work for this case. It should be mostly used to make the frontend fast or to template the views, but never for security purposes as the silver bullet solution (because it doesn't work that way).
rate limiting + CORS + account management
with rate limiting you make sure that a user (preferably you have that API called only after a user is logged in) can call that API only e.g. 10 times within 1 hour and with CORS you make sure it's callable only by your frontend.
It's not a silver bullet either, anybody with a little bit of brain can simply scrape your API locally thus go around CORS, but the rate limit will still hit hard, if you forbid registering more than 1 user from a single IP or if you require a phone number for verification. And add some annoying captcha, so it's problematic to automate for some people.
Still it can be attacked and misused, but it's painful unless you allow the same phone number (or any other ID less comfortable to get / requiring effort to get) to be used multiple times, so it'll make the most incompetent people go away... and the remaining ones, well, they'd play with your website anyway, so have a proper security assessment / harden your server if you maintain it alone.
Third-party
It's like 2., but you don't maintain the "low-level" server part, because the third-party is then managing it for you, you just need to specify conditions under which it'll be called. This applies to Firebase or Supabase which kind of behaves like a separate backend, but can have multiple modules (for FB, 1, 2).
Thus you'd use Firebase functions (or other alternatives), where you'd have your key e.g. even hardcoded and the client (browser) wouldn't have any access to that, add a limit, cors, perhaps some user registration limit and you're kind of done.
Note: Any domain, IP, region, phone number restrictions can be bypassed, so do not rely on them. It's just a mean to require effort when misusing your website for something different than you intended.
domain: curl http(s)://yourweb/path -H "Host: spoofed-domain"
region or IP: proxy, VPN, Tor, I2P, just somebody else's computer/server + ssh, some random WiFi
phone number: can go to a local shop and buy 10 fresh ones if I wanted to
It's more of a recommendation for them to keep your API keys server-side, and let your web app communicate with your server. Otherwise malicious users could easily steal your API key and use it for whatever.
If you think it isn't much of a security risk if your key gets (scratch that, is) compromised, that's fine then, you can just keep it in your webapp. Really depends on your use case and what that API key is for.
The only way to do this without exposing your API keys in your client app is to create a backend and serve the client app from the backend app as stated by Kelvin Schoofs and Peter Badida answers above (or use a third party service such as AWS Credential Vault). I suggest you use Node Express library for a backend as this will handle a lot of the boiler plate code for you. There are plenty of tutorials online for this.
Using a dotenv file as suggested by a few other users will only hide your API code from version sharing tools like Git (because you can ignore the dotenv in gitignore). It is very important that you understand the process of dotenv with a react app. Any user who opens the Dev console in their browser can view your exposed API keys in the static HTML.
Create a dotenv file and store all secret and API keys. Make sure to use REACT_APP_ before every variable.
DOCS: https://create-react-app.dev/docs/adding-custom-environment-variables/
dotenv package: https://www.npmjs.com/package/dotenv
I'm working on a project in which we need to authenticate the user in an application by using his/hers windows credentials. Frontend is using Angularjs and backend java.
After doing a sensible amount of research, I discovered that there is no way on the the frontend to obtain directly the Windows user & pass due to security concerns.
But I'm thinking that the whole process should start here, from the frontend, by obtaining these two encrypted credentials or at least a token and sending them to the backend in order to kickstart the ntlm authentication process.
And also, not sure if the user should have to log in the app by typing his windows credentials or if it should automatically be done with ntlm passthrough.
I do not have a good grip on the concept, and that is because most of the related sources that I found are referring to backend solutions (C# 80% of them), but almost nothing for fronted. So, I humbly require some clarifications on this topic. Is there some sort of middleware or npm package that I should use in order to obtain the user & pass, or what would you advise?
Web servers expose certain server variables to code handling requests they serve.
For me, using IIS, these are described here: https://learn.microsoft.com/en-us/previous-versions/iis/6.0-sdk/ms524602%28v%3dvs.90%29
Since I am using IISNode; my node.js environment is completely embedded into IIS; I have access to these server variables. As the link described, each programming language seems to have their own way to access these variables.
So I would doubt it if Java does not have those as well. The exact code to use will depend on you back end.
But a quick search for "java server variables" already yields me the following:
https://docs.oracle.com/cd/E19534-01/820-3288/gawim/index.html for the java access manager.
http://users.polytech.unice.fr/~buffa/cours/internet/POLYS/servlets/Servlet-Tutorial-CGI-Variables.html for old school JSP.
How can I obtain server variables using apache wicket 1.54? for java wicket server.
So have a look at the documentation of your specific web server software or Java API.
There should be a list and example code of how to access these.
Once you obtain this data server side, you can do the LDAP query and then return the results client side.
I have a website which is completely client-side. When it is in a testing environment, I use localhost for all links to other services: databases, report builders, etc.
When the website is deployed to apache2, for to go live, I have to manually change those link to the IP address of the server.
Is there any way in code to avoid doing this? Or, is the only way to automatically change them (grunt for example) during the deployment phase?
You could check the window.location object and put some conditional logic around the hostname, e.g. if (window.location.hostname == 'localhost') {}.
Although mixing environment specific / test-time code is typically a smell. Your hunch about this being a build/deploy time activity is probably the right way to go. The gulp-inject plugin is worth considering.
how I'd do it. (nginx)
run my application from server (you can access it via localhost on the server)
use nginx to serve the localhost application whenever a request comes to the server.
you can do the same with apache2:
i was about to write how to do it, but this website says it all: http://subinsb.com/linux-apache-localhost
I built an app with Google App Engine that:
Queries a URL (e.g. http://myapp.appspot.com/query?name="SomeName"&start_date="2012-01-01")
Receives a JSON response. This JSON response contains data from my own datastore within the same domain.
Plots a chart using that response.
The app.yaml configuration has the following lines:
- url: /.*
script: main.py
Where in main.py, I assigned the URL query to be handled by the class QueryHandler.
All is well and good if I run the app online. However, I cannot receive a JSON response if I run the app using the offline development server.
When testing offline, I also duplicate my online datastore into the offline development server. I can confirm that it works well because I have other scripts that query into it and they work fine. The only problem is the JavaScript chart.
Attempted solutions
If I change the query URL to http://localhost:8080/query?name="SomeName"&start_date="2011-01-01", the chart renders fine.
If I insist on the querying the URL on the cloud http://myapp.appspot.com/query?name="SomeName"&start_date="2012-01-01", I cannot render the chart.
Objective
I'd like to be able to query the cloud URL at all times, without having to change the domain to localhost. This will be useful to me in the long run when I decide to open up a public API. Is there a way to do that? Or is this just a limitation on the development server?
Your javascript should always query back to the server from where it was loaded.
Use window.location.hostname and window.location.port to get the host & port of origin server.
As you are apparently in control of the server who generates the JSON, you might workaround SOP by serving JSONP which is not much additional work.
Just check for a callback parameter and wrap your output within the fucntionname passed as callback. See JSONP.