2

Let's assume that I have created my REST service smoothly and I am returning json results.

I also implemented API key for my users to communicate for my service.

Then Company A started using my service and I gave them an API key.

Then they created an HttpHandler for bridge (I am not sure what is the term here) in order not to expose API key (I am also not sure it is the right way).

For example, lets assume that my service url is as follows :

www.myservice.com/service?apikey={key_comes_here}

Company A is using this service from client side like below :

www.companyA.com/services/service1.ashx

Then they start using it on the client side.

Company A protected the api key here. That's fine.

But there is another problem here. Somebody else can still grab www.companyA.com/services/service1.ashx url and starts using my service.

What is the way of preventing others from doing that?

For the record, I am using WCF Web API in order to create my REST services.

UPDATE :

Company A's HttpHandler (second link) only looks at the host header in order to see if it is coming from www.companyA.com or not. but in can be faked easily I guess.

UPDATE 2 :

Is there any known way of implementing a Token for the url. For example, lets say that www.companyA.com/services/service1.ashx will carry a querystring parameter representing a TOKEN in order for HttpHandler to check if the request is the right one.

But there are many things here to think about I guess.

Sam Holder
  • 32,535
  • 13
  • 101
  • 181
tugberk
  • 57,477
  • 67
  • 243
  • 335

3 Answers3

1

What you're describing is generally referred to as a "proxy" -- companyA's public page is available to anyone, and behind the scenes, it makes the right calls to your system. It's not uncommon for applications to use proxies to get around security -- for example, the same-origin policy means that your javascript can't make Ajax calls to, say, Amazon -- but if you proxy it on your own system, you can get around this.

I can't really think of a technical way to prevent this; once they've pulled data from your service, they can use that data however they want. You have legal options, of course; you can make it a term of service that proxying isn't allowed, and pull their API key if they don't comply. But most likely, if you haven't already included that in the TOS, you'd have to wait for, say, a renewal of their subscription to your service.

Presumably if they're making server-side HTTP requests to your service, those requests are all coming from the same IP address, so you could block that address. You'd probably want to tell them first, and they could certainly get around that if they wanted to.

Jacob Mattison
  • 50,258
  • 9
  • 107
  • 126
  • thanks for the detailed answer. The both above characters are fiction for now. So, I am thinking for both parties here. Your last paragraph is so right. But no certain solution for now. I can make it harder but not impossible. – tugberk Oct 21 '11 at 13:42
1

You could always require the client to authenticate, using HTTP Basic Auth or some custom scheme. If your client requires the user to login, you can at least restrict the general public from obtaining the www.companyA.com/services/service1.ashx URL, since they will need to login to find out about it.

It gets harder if you are also trying to protect the URL from unintended use by people who legitimately have access to the official client. You could try changing the service password at regular intervals, and updating the client along with it. That way a refresh of the client in-browser would pull the new password, but anyone who built custom code would be out of date. Of course, a really determined user could just write code to rip the password from the client JS programmatically when it changes, but you would at least protect against casual infringers.

With regard to the URL token idea you mentioned in update 2, it could work something like this. Imagine every month, the www.companyA.com/services/service1.ashx URL requires a new token to work, e.g. www.companyA.com/services/service1.ashx?token=January. Once it's February, 'January' will stop working. The server will have to know to only accept current month, and client will have to know to send a token (determined at the time the client web page loads from the server in the browser)

(All pseudo-code since I don't know C# and which JS framework you will use)

Server-side code:

if (request.urlVars.token == Date.now.month) then
   render "This is the real data: [2,5,3,5,3]"
else
   render "401 Unauthorized"

Client code (dynamic version served by your service) www.companyA.com/client/myajaxcode.js.asp

var dataUrl = 'www.companyA.com/services/service1.ashx?token=' + <%= Date.now.month %>
// below is JS code that does ajax call using dataUrl
...

So now we have service code that will only accept the current month as a token, and client code that when you refresh in the browser gets the latest token (set dynamically as current month). Since this scheme is really predictable and could be hacked, the remaining step is to salted hash the token so no one can guess what it is going to be .

if (request.urlVars.token == mySaltedHashMethod(Date.now.month)) then

and

var dataUrl = 'www.companyA.com/services/service1.ashx?token=' + <%= mySaltedHashMethod(Date.now.month) %>

Which would leave you with a URL like www.companyA.com/services/service1.ashx?token=gy4dc8dgf3f and would change tokens every month.

You would probably want to expire faster than every month as well, which you could do my using epoch hour instead of month.

I'd be interested to see if someone out there has solved this with some kind of encrypted client code!

Josh Diehl
  • 2,913
  • 2
  • 31
  • 43
  • I have only read the first paragraph so far and I would like say that no, company a's users will browse the web site with anonymous access – tugberk Oct 21 '11 at 13:44
  • 1
    Your update 2 (using a custom token in url) is the same concept as 'changing the password' I mentioned above, i.e. providing a moving target for those that would use the service without permission. In this case, you'd have to expire the token after some time, since a url your JS calls is easily discoverable. Your official client would have to get the updates of the new token when it changes. The weak spot here is if someone writes code to hack your client code, since it's javascript and therefore is open for inspection. Encrypting the relevant JS code somehow would provide obfuscation. – Josh Diehl Oct 21 '11 at 13:56
  • your solution sounds so logical but I just cannot visualize how I can implement that. Can you provide me any sample code on C# to implement this? or do you know any resources on this topic? – tugberk Oct 21 '11 at 14:02
0

With the second link exposed by Company A I don't think you can do much. As I understand it, you can only check whether the incoming request comes from Company A or not.

But each request issued to www.companyA.com/.. can't be distinguished from original request from Company A. Everyone they let in uses their referrer as a disguise.

Martin
  • 183
  • 8
  • Yes, Company A's HttpHandler (second link) only looks at the host header in order to see if it is coming from www.companyA.com or not. but in can be faked easily I guess. – tugberk Oct 21 '11 at 13:38