Calling a web service from Javascript - javascript

What is the best way to add authentication / security while calling Web service from javascript ?
I want my web services should only get called from my application , anyone else should not be able to access my web service by copying web service URL into browser.
From the first few answers it seems like its next to impossible.
So what should I reply to my client as he is unaware of word impossible ?
~Ajinkya.

Have a look at using the synchroniser token pattern so that the service can only be consumed with a piece of data known to the page which loads the service reference. There's an example of doing this with a web service in OWASP Top 10 for .NET developers part 5: Cross-Site Request Forgery (CSRF). This should achieve what you're after.

This is not possible. If you allow a client to access your webservice from JavaScript, the client will always be able to do that. You can only reduce access by using some kind of constraint, like a Token that needs to be sent along with the request to authenticate it. You might even turn it into a one-time token. But this will create new problems (e.g. what happens if the answer gets lost. The client javascript cannot rerun the query).

Related

Hiding API access credentials from an AngualrJS app

This is a design question for AngularJS websites that access a REST API. Since all the AngularJS code can be viewed from the client side (assuming obfuscation is not completely secure) how do you hide the API access credentials (the API key and password or even a JWT)?
This can be extended to a broader question about how other application logic can be hidden in an AngularJS website?
My research led me to some insights, one of which was
http://billpatrianakos.me/blog/2016/02/15/securing-api-keys-in-a-javascript-single-page-app/
But this has me more confused now, since the post suggests an SPA connecting to a REST API is not a good architecture. I thought it was and now can't figure what the right approach is.
The closest I can come to an answer is this resource:
https://developers.facebook.com/docs/facebook-login/security#appsecret
Facebook, is pretty good with their security and say:
Never include your App Secret in client-side or decompilable code.
Use unique short-term tokens on clients.
In short, do not keep API secrets on the client side
Answering the discussion in comments for sake of not being brief:
And then my question would be "what then is the correct architecture for SPAs and server side code (or database access)?".
There's no one correct architecture, it depends on the size and scope of your project. It will also depend on what frontend and backend frameworks you choose. Those choices also will depend on how many other APIs you are calling, or what other developers or you are most familiar with.
Speaking more specifically about security though, ideally you'd like to set up a session for the user which consists of a token that the user uses to identify himself. This is usually generated for each user by the server when they login. Generally this is provided by the framework you are working in, but even if it isn't, it's fairly simple to build. You will want to prevent cross origin requests (making sure the user is actually on YOUR frontend) and have secure connections (setting up SSL and https, though this can get complicated). You will generally want to run your JS code through something like Uglify to prevent it from being too easy to look through, but this does NOT guarantee that people cannot take that code and un-uglify it.
As the other answers have suggested, you should never keep API keys or any secrets in the client source code. There is no way to hide anything on the client, and obfuscation != security.
If you are looking to architect secure authentication/authorization into your app, you will want to return a JWT to the AngularJS application. You can then pass this JWT as a Bearer token to your API which will verify the validity of the token and allow the API to authorize access to the AngularJS application.
As for where to store the JWT token, you can store it in either Local Storage or in a cookie. There are serious considerations between choosing whether to store the token in either of these locations.
If security is your concern, I would look into the OAuth 2.0 Implicit Flow.
Don't put API keys in your client side source code. Keep them on your server, and have your client make a request to YOUR server, which then calls out to external APIs for data.

restrict access to to web Application

I have a JSP webapp developed in Eclipse as a dynamic web project.
we use a third party web application that invokes my application, I need to validate that only the requests that come from that application are allowed to create a new session in my application.
I´m tring to do it with javascript and thinking , as a last resource, to use a Filter class to know the request origin and define the behaviour.
the problem is that the user requires that the operation is done on the client side, meaning I have to use javascript or similar, I have read about document.referrer on JS, but so far nothing is shown on the console.
Anything that you do in the client using JS for handling sessions wouldn't be secure as it can be easily modified by a malicious user. Also, using the referer or any other http header params would be insecure as they can also be easily spoofed.
If this third party application is directly calling your application I imagine that you have some degree of control over it. Can you access and modify its source code or are you just using configuration params?
Ideally the third party application would use an authentication token on each request that it makes to your application. And these authentication requests as well as all the session handling logic would always be handled on the server side.

How to Secure ASP.NET Web API with Cross Domain AJAX Calls?

I want to create an API at www.MyDomain.com that is accessible from public websites www.Customer1.com and www.Customer2.com. These public websites display each customers inventory and do not have any login features. They will use AJAX calls to read data from my API.
How can I secure the API so that it can be accessed via AJAX from different domains but no one can access the API to be able to scrape all of my customers data and all of their inventory?
I have tried thinking of different solutions on my own but they would all either require people to login to the public websites (which isn't an option) or it would require some secret "key" to be displayed publicly in the browser source code which could then be easily stolen.
Any ideas would be greatly appreciated.
Thanks!
P.S. Are their any obstacles that I am going to run into using Javascript & CORS that I need to look into now?
Anything that is accessible without authentication from a browser is by definition insecure, so you can't stop that. Your best bet is to have to have a relationship with the owner of customer1.com and customer2.com - the server apps for those two websites would make an HTTP call to you and authenticate with your service. Going this way also avoids the CORS issues you're talking about.
If you've already designed the client functionality, you can still probably do it without much change to the javascript - have it point to customer1.com for its AJAX call instead of your API, and customer1.com would accept this request and just act as a proxy to your API. Aside from the authentication, the rest of the request and response could just be pass-throughs to your API.
You can use Microsoft.AspNet.WebApi.Cors.
It's just need add ONE line at webapi config to use CORS in ASP.NET WEB API:
config.EnableCors("*","*","*");
View this for detail.
The simplest way to provide a minimum security here is to provide some kind of token system. Each app has its own token, or combination of tokens which it must pass to the server to be verified. How you generate this tokens is up to you and other than being linked to app's access, doesn't have to mean anything.
Provide a way for each API implementer to open an account with you. This way you will know who is accessing what and in some cases you can block/stop service.
For instance, a token can just be an MD5 hash:
7f138a09169b250e9dcb378140907378
In the database, this hash is linked to their account. On each request, they send this token with what they want. It is verified first to be valid, then the request is fore filled. If the token is invalid, then you can decide how to deal with it. Either don't return anything or return an "access denied" (or anything you want).
One thing to avoid is having a single token for everyone, though this can be a starting point. The reason for this is if some unauthorized app gets a hold of this token and exploits it, you have to change the token for everyone, not just the app that somehow leaked the token. You also can't control if someone has access to something or not.
Since you listed ASP.NET, I can also point you to WCF, which is fairly complex but has all the tools that you need to setup a comprehensive web service to service both you and your clients.
I hope this gives you a starting point!
EDIT:
There are security concerns here in the case that someone leaks their token key somehow. Make sure that you setup a way in which the app/your service do not expose the the token in anyway. Also have a flexible way of blocking a token, both by your clients in you, if it so happens that a token is exploited.

Is it possible to restrict an API to only one web interface/app?

I have a question regarding cross-origin policies.
I have a web app that gets data, usually in JSON format, via ajax.
When the web app initialize, a unique 'key' or 'token' is created from the server via ajax and is sent to the client, as a mean to identify it. The token is sent back on every ajax call for validation purposes. If it is not validated within two hours, a PHP script deletes it, and the user is required to authenticate him/herself again.
If the user sends another ajax call (i.e. if there is activity with the associated token), the token sets its expiration for another 2 hours.
On every call, I validate the token and then process the request. Everything works well but my issue is security-oriented.
Since the token is stored client-side (very crudely, like window.token = 'YTM0NZomIzI2OTsmIzM0NTueYQ==';), won't it be possible for malicious users to inspect the code, copy the JavaScript including the token, and create another app that will access the same data?
Since the token is stored client-side (very crudely, like window.token = 'YTM0NZomIzI2OTsmIzM0NTueYQ==';), won't it be possible for malicious users to inspect the code, copy the JavaScript including the token, and create another app that will access the same data?
Yes.
And possibly even more disturbing to you may be this: it doesn't even matter how your token is stored client-side - they'd even be able to login using the same API you expose to your users for logging in. (And if you think you don't have a login API because it's a form-post or something similar, you're fooling yourself - a form post is just as much an "API" as anything else... and can easily be replicated elsewhere).
The cross-domain stuff has very little to do with anything - as that's a client-side restriction of a browser - intended for the user's protection - not yours. I can make any HTTP request I want from a desktop or a server. I can even setup a service which allows me to proxy all requests made to my service over to your service... so the cross-domain security in browsers is of no help to you.

How to restrict access to my web service?

I have http://example.com/index.html, which from within the HTML uses JavaScript (XmlHttpRequest) to call a web services at http://example.com/json/?a=...&b=...
The web service returns to index.html a JSON array of information to then be displayed on index.html.
Since anyone can view the source code for index.html and see how I'm calling the JSON web service (http://example.com/json/), how do I prevent people from calling my JSON web service directly?
Since the web service is essentially an open read into my database, I don't want people to abuse the web service and start fetching data directly from the web service, start DoS my server, fetching more information than they should, etc..
UPDATE:
Is there no way to limit requests for http://example.com/json/ to only come from the same server (IP) and URL request of http://example.com/index.html?
Meaning, can't http://example.com/json/ detect that the Requester is ($_SERVER['REQUEST_URI'] == http://example.com/index.html) and only allow that?
There are no easy way to prevent that. If your service isn't extremely popular and thus being likely target for denial of service attacks, I wouldn't bother.
One thing which came into my mind is using disposable tokens (valid for 10 or 100 requests).
Other (naive) approach is checking that X-Requested-With header exists in request, but of course that can be easily faked. So, my advice is: do nothing unless the problem is real.
One more idea: hash calc. The idea is to require client performing rather expensive calculation per every request, while validating the calculation in server side is cheap. For a single request the overhead is very small, but say for 1000 requests it may take significant amount of CPU time. I have no idea if hashcalc has been used to prevent DoS'ing web services. Some years ago it was proposed as antispam measure, but never became popular.
Answer is really simple, use CSRF protection. http://en.wikipedia.org/wiki/Cross-site_request_forgery
Simply, when user comes to your site (index.php), put in session:
CSRF=(RANDOM_HASH)
Ask for JSON request, example.com/json.php?hash=$_SESSION['CSRF']
And in json.php check if $_GET['hash'] matches $_SESSION['CSRF']
Simple as that...
It's Server-Side solution!
I would keep track of the IP addresses making the requests. If you ever saw a large number of requests coming from the same IP, you could block it or offer a CAPTCHA.
There are a wide array of things you can do to add security to your service. Check this out
You can't properly secure a web-service that is callable from client-side javascript.
You can try security through obscurity techniques like javascript obfuscation, but it won't stop someone motivated.

Categories