Is there some way to determine the client to my HTTP SOAP API currently? - iphone

I know that user agent can be faked easily when connecting through HTTP. I want to ensure access to my SOAP API only from iPhone devices. We don't know how many users will be using this when it is released but it might be a lot and we can't handle traffic from outside of the devices. Any other means to prevent this?

It's not clear to me why limiting just to iPhones would be the way to go since I guess what you're really worried about is volume per user on the API (iPhone or not) and number of users. Spoofing the client is pretty easy so a better way to would be either to issue keys/ids on signup and then limit volume on each key or by IP address. Using keys also means you'll have a better ID on your users which might be useful in the long run. IP addresses could be problematic with mobile clients but at least you can do some basic load limiting.

Unless you control both sides, there's no way to determine the type of the other party reliably over HTTP.

No. (Outside of asking them if they're on an iPhone of course.)

Related

Restrict REST API to Mobile App Only - Proposed Method

I read a lot that you can't restrict your Public REST API to only your mobile application, but I have an idea and I want opinions on it:
Variable App Key Method
Mobile App
Get IP address of current connection
Use a secret algorithm to generate a hashed AppKey from IP address.
Send the AppKey with each API request
Server Side
Check the IP address of incoming request
Generate AuthKey from that IP address using same secret algorithm.
Compare AuthKey with AppKey, if they match then you know that your
Application is talking to you, because only the application knows
the secret algorithm.
When IP address changes:
On mobile App regenerate the AppKey using the new IP address
Server side will always generate same key because it depends
on IP address of the request
The main advantage of this is that the AppKey will always change, which is better than hardcoding 1 application key inside the code, which can be easily stolen by reading request headers. And even if you stole the AppKey from a user you must be using the same IP address where that key was generated.
Any thoughts?
The "secret" algorithm would have to be in the app... given to everybody. It is not secret at all. Security by obscurity is bad anyway, you should not have supposedly secret algorithms, because it's hopeless to keep them confidential. In this case the algorithm is trivially revealed.
Also refer to Schneier's law. :)
Edit:
So theoretically, this can never be secure, because any algorithm you put into the app needs to run on the client, and hence can be analysed and decompiled. But one can argue that it doesn't need to be theoretically secure, it is ok if it's "secure enough", ie. the risk is low enough, because for example the effort needed to get to the algorithm is too much.
But then consider the two possible options:
This is a really cool API that everybody totally wants to build a client for, or there is at least one such party. In this case, no effort is too much, and the algorithm will be "broken", that is, it will be decompiled and implemented in a different client.
People don't care all that much about this API, it is not very important for anybody else to build a client. In this case they probably won't build a client anyway, and much simpler methods can be used to prevent other clients from popping up with a reasonable success.
But obviously, it's your choice, an approach similar to what you describied does raise the bar somewhat - just don't expect it to be actually secure, because it will not be.

Authenticating lots of clients for a REST API

We have a large number of small devices deployed in the wild that communicate with a central server via a REST API. It will send a status update on a regular basis with some sensor data and will also ask the server if there are any software updates that need to be applied. If there are, it will download it etc.
I'd like some way to prevent my server API from being used by unauthorised clients. Here are the solutions that I have and the issues which I anticipate. This question is somewhat open ended but it is mostly a question of best practices for, what I think is, a common situation.
Keep a single username/password on the server and then use basic auth over https. This is simple but if I change it, I'd have to somehow change the credentials on all of my devices (which number in the low thousands). This is hard to do reliably. There's also a problem with how the devices are going to get the update without first changing their creds.
The second is to create a username/password for every device. Then I can update individual ones and manage them but there's a lot of state on the server and I'm worried about having this much data on the server.
Some kind of automatic key based system whereby the devices can ask for an expirable key and then use that for all transactions. If the key expires or is invalidated, that device can't connect anymore. This would necessitate some kind of id for the device which I'm not sure how to handle.
So, how would I do this?
Update
In our setup, we have assigned hostnames for each of the devices we're going to deploy created beforehand. Once the devices switch on, they will contact the server with their hostnames and thereby register themselves. The MAC address and other information is passed as part of the initial registration handshake.
So, the "unique identifer" which was mentioned in the answer (and comment) by Noksi is the hostname. This can be easily spoofed (since the hostnames have a pattern). However, when the devices first come online, we can get the mac and, after that, only refresh the token if the request comes from the same mac. This opens up the possibility of a fake registration happening the first time though.
If there is some way to uniquely identify each device (similar to a MAC address) then that would be the key. Keep a registry of the devices and each device would register with the server. the server would provide the device with a token and associate it (the token) with the registered device. the device uses that token to make requests. tokens can be made to expire and renewed as needed or can be black listed if needed. This seems to be similar to option 3 in the proposed options.

Setting resource in XMPP Facebook chat

When we connect to googletalk using xmpp, we can set the resource attribute, and can thus identify whether the user is logged in from android, pc etc.
I was wondering if there is any similar way to specify/identify device in facebook chat API.
When I connect with xmpp, facebook do all the internal transation and erase off my resource value.
Is there any other way to achieve this?
This is not what the resource identifier is meant for, even if many users or software put human readable text there. For security reason the resource should be unpredictable.
Use Service Discovery:
http://xmpp.org/extensions/xep-0030.html
Use XEP-0115: Entity Capabilities. Mark up your presence stanzas with caps. Pre-load the caps cache of all of your clients with the disco#info describing each. This will just barely work for your clients on FaceBook, and will interoperate really well on other systems.
Please read the XEP multiple times. Almost everyone misunderstands it at first.

XMPP: Make client appear online only to other instances of that client

I'd like to use XMPP as the message bus for a desktop application. As the application would use the users existing XMPP account (GTalk or the like) and doesn't provide IM service I would like to make instances of my client invisible to other XMPP clients.
To do this I'm considering using client service discovery and privacy lists to block outgoing presence notifications to the full JIDs of clients other my own. I do however doubt the scalability and robustness of this approach. Is there a better way of accomplishing this?
EDIT:
I'm now thinking the closest I can get to this behaviour is to set a presence of away with a negative priority. This will hopefully minimise user confusion and work fairly universally.
XEP-0126 doesn't have the tools you need, since there's no way you'll find out about the other clients to which you have to direct presence... because they're invisible.
How about if all of your clients join a MUC room?

How secure is it to call "secret" URLs in an iOS app?

We want to use a web service in our app which obviously requires to call a URL. It's not HTTPS, just plain old HTTP, using NSURLConnection.
The problem is: This web service is VERY expensive and every thousand calls costs us real money. The fear is that someone could figure out which URL we call and then misuse that, letting the costs explode. There is no way for us to track if a call to that web service was legitimate.
We're calculating based on how many apps we sell, multiplied by an assumption of how often that app will be used per user in average. We have some good statistics on which we base our assumptions.
Are there known ways of figuring out which URL an app is calling on the Internet to retrieve information?
You could easily use a network sniffer while the phone is on WiFi to figure out this information. It sounds like it is actually critical that you use SSL with some sort of secure token in the URL.
If this is not an option perhaps you can provide your own proxy service that would use SSL and security tokens? Proxy also grants the ability to throttle requests and block users known to be malicious. Throttling puts an upper bound on the expense each user can incur within a given time interval. Another benefit of a proxy is that it allows one to gather statistics and measure the costs incurred by different users facilitating malicious user detection and business planning. Proxy could also save you some money if the service behind it is stateless by adding a cache that would remove a lot of expensive calls.
If the Web service is not encrypted, it would be trivial to use a proxy to intercept the Web requests made by the phone. If the expensive Web service does not offer at least some form of basic authentication, I would seriously reconsider including its URL in a public app.
Using plain URLs is a sure way of letting script kiddies run you out of business. If there is no way for you to track if a call to the expensive web service was legitimate, set up your own web service that fronts the real web service to make sure that your own web service can verify the legitimacy of the call before forwarding the request to the real web service.
Yes, there's plenty of ways to do this. For one example, hook up the iPhone to a wifi network, in which the router has a transparent proxy. Examine the proxy's logs. You'll see all URLs. Depends how determined your users are, but this is rather easy.
Ignoring the fact that people who jailbreak their devices could possibly look at your application, I believe it is possible to examine traffic like any other device (laptop, tablet, etc.) if someone was sniffing traffic over a WiFi hotspot using applications such as WireShark. However, I doubt there would be much risk of this over a cellular 3G network.
Good question.
As many have said, yes, it's easy to figure out the urls your app requests.
Note about HTTPS:
But since you are using HTTPS you are okay because over HTTPs the domain will be obscured to the IP address, and people cannot see the URL query string parameters. For example, if your URL was https://somewebsite.com?uid=mylogin&pass=mypass, they definitely won't be able to see "uid=mylogin&pass=mypass", and they probably can only see the IP address, not the domain name itself. (see https://serverfault.com/questions/186445/can-an-attacker-sniff-data-in-a-url-over-https)
Sidenote:
Might be safe to assume that Apple performs some sort of HTTP request diagnostics when they review your app -- which would make sense because it's in their best interest to try and figure out what your app does from many angles.