I see in this thread that hiding credentials from the front end of a website is not possible, but I was wondering if there was an option to restrict calls to a single domain? To prevent the possibility of another site linking to the same content.
Currently Contentful does not restrict requests by domain.
You use your api keys (which should remain a secret) to access your data.
I would highly recommend putting your requests behind a server so that you can keep your keys private.
Here is a tonic example where a node server has the access key set up as an environment variable:
https://tonicdev.com/mrsteele/contentpull
Related
I've developed simple REST API using a expressJs. I'm using React as my client side application. So the problem is anyone can see my API endpoints because of react app is in client side. So they will also able to make request and fetch data from my REST API. (May be they will build their own client side apps using my API.) I've seen some question about this and couldn't find any comprehensive answer. How these kind of a security problem should be handled? Is it possible to give the access for API to only my client app? If not how huge brands that using REST API prevent that? (Also I don't have a user authenticating scenario in my product as well. People can just visit and use the website. They don't need to register).
Authentication can be a way but it can be bypassed. Another way is you can create a proxy server which strictly blocks cross origin requests, hence it blocks requests from other domains to make request to your API, and you can make your API call from that proxy server. In this way your API server endpoint will also be not compromised.
If, as you state in your comment, this is about users on your own website being allowed to use your site's API, while disallowing off-site use (e.g. other websites, wget/curl, etc) then you need to make sure to set up proper CORS rules (to disallowed cross-origin use of your API) as well as CSP rules (to prevent user-injected scripts from proxying your API), and you also make sure to only allow API calls from connections that have an active session (so even if you don't want user authentication: use a session managemer so you can tell if someone landed on your site and got a session cookie set before they started calling API endpoints).
Session management and CORS come with express itself (see https://expressjs.com/en/resources/middleware/session.html and https://expressjs.com/en/resources/middleware/cors.html), for CSP, and lots of other security layers like HSTS, XSS filtering, etc, you typically use helmet.
I'm going to create an API service for my clients to use. The api is gonna return some data that will be displayed to the customers using my client's website. The api does not need any kind of user data.
I was thinking to use an api key and use it to return the relevant data. But I want to make sure that only the customers using my clients website should be able to access the api.
My question is if I use the api in the front end and expose the api key anyone will be able to use the api from their browser. I don't want that to happen. How do I authenticate this? If that's not gonna work can I use the api from my server to client server? Even then how will I authenticate the server?
I'm using nodejs and express in the backend. Any ideas? Thanks!
This is a tricky thing to do; essentially restricting public apis. At the end of the day, the web page is going to be in the user's browser on their local machine. So if they can access it from their browser, then they can access them manually too. An API key is the best approach really, but this only acts as a deterrent more than access control. Pretty much any access control type you put into a browser can be mimicked outside the browser unfortunately.
If you want to go down the route of having users login to some extent you should look into json web tokens (jwt). This doesn't need to be on a user level, and can be on a sort of session level if you prefer. This however won't restrict the user accessing the apis directly.
If your API is public, without user authentication, then there is no way to restrict the access to it.
There are many workarounds like checking for referer or creating special tokens, but it will all be stored at client-side, and a malefactor can reuse it.
It all does not make sense in general. You have already exposed your API to your clients. Even if you create a working algorithm, a malefactor can simply run your website JavaScript methods to make it work. What are you trying to protect from?
If you to restrict the access to your API, then the most proper and efficient way is to make this API back-end, so that only your webclients at server-side have access to it.
I have a main website running on AppEngine. It's on a subdomain like main.example.com. This main application is a content portal for our customers. It offers an Ajax application built on YUI. Customers can upload data to it. Users authenticate using Federated Login.
The Ajax application on it allows users to process the data previously uploaded. To do it it should use an webservice running on other subdomain like service.example.com. The webservice does not run on AppEngine but on our services - it's CPU heavy and built on other set of technologies. It would need to download the data on main application - but the downloading service - like everything on the main application - is behind the authentication wall.
I could programatically always allow the service to download wharever it wishes but I think this can turn into a major security problem.
How can I reuse the OpenID authentication "token" to allow it (the service) to appears to the main application as the authenticated user so it can download data? Or If I can do this what would be the best way to accomplish what I intend to do?
You can't really reuse the authentication token. What you should use is something akin to OAuth, though since you control both ends you can make it somewhat simpler:
Generate a shared secret, accessible by both main.example.com and service.example.com
When a user accesses service.example.com for the first time (no authentication cookie), redirect them to main.example.com/auth?continue=original_url (where original_url is the URL they attempted to access)
When you receive a request to main.example.com/auth, first log the user in the regular way (if they're not already). Then, take their user ID or other relevant credentials, and generate an HMAC from them, using the shared secret you established in step 1. Redirect the user to service.example.com/finish_auth, passing the computed HMAC, the authentication details such as user ID, and any parameters you were passed in such as the continue URL.
When you receive a request to service.example.com/finish_auth, compute the HMAC as above, and check it matches the passed in one. If it does, you know the request is a legitimate one. Set an authentication cookie on service.example.com containing any relevant details, and redirect the user back to their original URL.
This sounds complicated, but it's fairly straightforward in implementation. This is a standard way to 'pass' credentials between mutually trusting systems, and it's not unlike what a lot of SSO systems use.
I'm creating a web service with create/update/delete calls. But for now I'd like to restrict use of it on my own web app and no other clients. How can I have clear text javascript code that makes these calls but still be confident the credentials won't be used elsewhere?
My idea is to use server side generated nonces for each request. But I am open to different ideas you guys may have. Thanks.
Do the users of your web-app have a loginid/password? If yes, then ask them to login, and use standard session management approaches to achieve what you want.
If your users don't have unique account, and you only want your javascript code to make the web-service calls - then it cannot be achieved. Its trivial to sniff the traffic / extract password from javascript.
You could use the firewall on front of your webserver to filter out based on MAC
Yet simpler, collect the credentials (authentication token) with a dynamic dialog box (javascript is very rich on creating UI dynamically)
We have one web application (sharepoint) that collects information from disparate sources. We would like to be able to link users to the main websites of those various sources and have them pre-authenticated. I.E. they enter their credentials for the other sources (which are a number of different types LDAP, AD and home grown!) and we retrieve some information for them, and remember there details (Possibly Single Sign-on to keep em nice and safe). The user can then click a link that will open the full app in another window already authenticated.
Is this even likely to be possible?
Office Server has a Single-Sign-On api as a builtin feature. you may want to look into that. It enables you to register user credentials securely, and to access it at runtime.
You need to act as a web browser acts to different sites with storing credentials (usually in cookies) locally. Use therefore a a proper client library with cookie support. This could go probably for most of sites. There are sites using HTTP authentication, which are also easier to access from appropriate client libraries. The most demanding can be access to SSL websites, but again, most client HTTP libraries cover that nowadays as well.
All you need now is just to prepare your web application to act as a proxy to all those separate web resources. How exactly this is done in Sharepoint, well, I hope others will answer that...
True Single Sign-on is a big task. Wikipedia describes common methods and links to a few SSO projects.
If you want something lighter, I've used this approach in the past:
Create a table to store temporary security tokens somewhere that all apps can access.
From the source app (Sharepoint in your case), on request of an external app, save a security token (maybe a guid, tight expiration, and userid) in the token table.
Redirect to a request broker page/handler in the destination app. Include the final page requested and the guid in the request.
In the broker, look up the security token. If it exists and hasn't expired, authenticate, authorize, and redirect to the final page if everything is good. If not, send a permissions err.
Security-wise, a guid should be near impossible to guess. You can shrink risk by letting the tokens expire very quickly - it shouldn't take more than a few seconds to call the broker.
If the destination app uses Windows Auth and doesn't have role-based logic, you shouldn't have to do much. Just redirect and let your File/UrlAuthorization handle it. You can handle role-based permissions with the security token db if required.