This Q&A is part of a weekly series of posts highlighting common questions encountered by technophiles and answered by users at Stack Exchange, a free, community-powered network of 100+ Q&A sites.

Gaz_Edge asks:

Over the last few years, the trend for client-side (browser) applications has really taken off.

For my latest project, I have decided to try and move with the times and write a client-side application. Part of this application involves sending transaction emails to users (for example, validate sign up, password reset emails, etc.). I am using a third-party API to send the emails. Normally I would have my application running on a server. I would call the third-party API from code on my server. Running a client-side application means this now needs to happen on a user's browser. The third-party API provides the necessary JavaScript files to achieve this.

The first glaring issue I can see is I need to use an API key. This would normally be safely stored on my server, but now presumably I will need to provide this key to the client browser. Assuming I can get round this problem, the next problem is stopping a tech-savvy user from loading up the JavaScript developers tool on a browser and using the email API anyway they like, rather than adhering to any rules I have set in the application.

My question is: how can we prevent malicious use of a client-side application?

See the full, original question and all answers here.

Defend against less-determined attackers

Kilian Foth answers (166 votes):

You can't, and the more people understand this, and the deeper they understand, the better for the world.

Code that runs on a device under the user's control cannot be controlled. Smartphones can be jailbroken. Set-top boxes can be cracked. Ordinary browsers don't even attempt to prevent access to JavaScript code. If you have something worth stealing or abusing, a determined attacker will be able to do that unless you validate everything you cherish server-side.

Obfuscation is of very little help; the kind of opponent you will attract as soon as anything remotely financial is involved reads assembly language like classified ads. Encryption cannot help you, because the device that would guard the key is the same device you have to assume is cracked. There are many other, seemingly-obvious countermeasures that don't work, for similar reasons.

Unfortunately, this is a very inconvenient truth. The world is full of small-time and big-time operators who think they can somehow get around the fundamental brokenness of remote trust, simply because it would be oh so nice if we could assume that our code will be run the way we assumed. And yes, it would make everything so much easier that it isn't even funny. But wishing doesn't make it so, and hoping against hope that you are the one smart cookie who can avoid the unpleasantness will only burn you and your clients. Therefore, get into the mindset that the Internet is enemy territory, include that added cost in your estimates, and you'll be fine.

That said, of course there is such a thing as defense in depth. Obfuscating your JavaScript doesn't put off a determined attacker, but it may put off some less-determined attackers. If your assets are worth enough to protect, but not at any cost, any of those measures may add business value to your system; it just can't be perfect. As long as you are fully aware of the trade-off you are making, that may be a reasonable strategy.

Related: "What are the differences between server-side and client-side programming?"

Handling it locally

Voo comments (34 votes):

I haven't seen any sane person ever define "client-side application" as "under no circumstance ever communicate with a server." That seems more like a strawman than a reasonable argument. Clearly there are some things you have to handle on the server-side but the vast majority of actions can be done locally without problems, which will in turn vastly improve responsiveness and scalability.

Authorized transactions should happen on a server

Jan Hudec answers (24 votes):

This is exactly the case where making it a completely client-side application is not appropriate.

You can make the logic and basic validation of forms client-side (you still have to revalidate on server, because someone may try to fake the request) to improve responsiveness, you can do HTTP requests from JavaScript passing data there and back in JSON to avoid re-sending page decorations and such, but if the transaction itself needs to be authenticated and authorized, it should still happen on a server.

Find more answers or leave your own answer at the original post. See more Q&A like this at Programmers, a question and answer site for professional programmers interested in conceptual questions about software development. If you've got your own programming problem that requires a solution, log in to Programmers and ask a question (it's free).