3

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?

4
  • The following article should contain the info you need concerning CORS: asp.net/web-api/overview/security/… -- which incidentally includes a manner for restricting what ORIGINs (addresses of incoming requests) are permitted. Commented Sep 3, 2013 at 15:43
  • However even with CORS there's nothing really stopping someone from hitting the api with a server rather than a browser. Commented Sep 3, 2013 at 15:47
  • Remember though with AJAX it's your customers clients hitting you and not your customers directly. Commented Sep 3, 2013 at 15:50
  • There's very little that you can do to solve this, short of not allowing clients(browsers) to make the api requests. Commented Sep 3, 2013 at 16:15

3 Answers 3

1

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.

Sign up to request clarification or add additional context in comments.

7 Comments

Looking at your second paragraph, wouldn't that just open up the api to everyone, making it no better than an api with no authentication? Anyone would be able to take their favorite server-side language and get all the data from customer1.com, i guess unless it was restricted per user using a login/password system on customer1.com.
@KevinB Now that you mention it, yep, if there's no authentication on customer1.com, all you're really doing is just moving the public endpoint from the API itself to customer1.com, which doesn't really do a lot of good. But then again, with no authentication, a malicious user wouldn't even need the API anyway, and could just screen-scrape customer1.com to get the data. So I guess this doesn't really solve anything.
If a pass through proxy is created on customer1.com then within the proxy a secure key could be added to the call on the server side. This secure key would not be visible in the browser and could limit data to only that specific customer. I'm not too concerned if someone is able to scrape all of 1 customers inventory, because like you said they could do that with screen scraping. What I don't want to have happen is to be able to scrape all inventory for every customer. So far I am liking your answer. I need to do some more research first.
If I used this method though what would stop someone from creating a program that just makes the API call to customer1.com? Then the proxy would generate the key for them and pass the request through...
@Jeremy I think that was Kevin B's point - this method basically just moves the API endpoint from your API to customer1.com, but from the client's perspective, it can make whatever calls it wants to that one and still get everything back. But if your real API restricts the results to only the customer who is making the call, like you're suggesting, then at least the client could only get Customer1 data by using customer1.com - they'd have to go to customer2.com in order to get the data for Customer2. Not exactly secure, but it's a little better.
|
1

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.

Comments

0

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.

4 Comments

What stops a user from taking that token from the browser (since the browser is sending the request) and generating their own requests using that token?
Hmm...I do not really have an answer for you. The issue with JS is that NOTHING is secure because it runs through your browser which you can access. I guess the only real way to get around this is to generate a predictable token. In other words, an algorithm on the back end generates a unique hash which the receiver can verify. One way could be to hash together some kind verifiable variables. An (not so good) example is the current hour in central time against an ID. Taking the current hour, the server can find your ID. There are big issues with using time, but I hope you get the idea.
Also, you don't really want to hash compare every record, but what is import is the idea of a predictable token; there are probably good ways to implement it.
I thought about generating a key but then like Kevin B said it would get passed to the browser and could then be easily stolen.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.