I am about to create a API for my web service. Now it's time to think about security.
There will be multiple clients accessing my API, however their all created by me, so no third party clients.
For now I planned a mobile App (Phonegap / JS), a web app (Also JS) and a Chrome App (also JS).
Sadly I don't have the possibility to use HTTPS for my API requests. Thats why I thought about oAuth 1 for security.
My question now: How safe is it to use oAuth in combination with JS, because the Secrets will be stored client side.
Is oAuth a good decision or could anybody recommend a alternative?
Thanks a lot!
Sorry, I've got bad news for you.
oAuth is not safe at all. You need to use SSL. The only way to be secure is to have a third party, that is trusted by the web browser vendor, provide a certificate signed to prove that you are who you claim to be. Without that, anybody on the same LAN as the user can easily hack into your system.
Also note that oAuth 2.0 actually requires an SSL connection anyway.
Finally some more bad news, you cannot store any secrets client side. Client side is controlled by anyone who uses your app, and they can access all secrets you store there. It is impossible to change this, SSL won't help either.
The takeaway is:
you need to use SSL, there's no alternative.
you must not store any secrets client side. All secrets must be server side.
Related
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.
I have implemented json web service in java(server) and client is in pure javascript. It is possible to authenticate web service call from javascript?
I know that is standard to use private key on both sides, but javascript is public, so this is not very secure :)
I already checked this: Authorization and Authentication to REST API from JavaScript Client
and read lot of information on internet, but it seems to be impossible to authenticate from javascript (code is visible)
Thanks a lot!
Yes, you can but there are some things to be aware of. Once the user of your JS application is authenticated, you can store them within the local storage. Then you can use them within your request. Be careful of possible XSS attacks.
Here are some links that can help you:
https://templth.wordpress.com/2015/01/05/implementing-authentication-with-tokens-for-restful-applications/
Securing a API consumed by AJAX
Hope it helps you,
Thierry
As you mention, storing confidential credentials in the browser is a bad idea (due to XSS vulnerabilities). HTTPS-Only cookies are the most secure way to store an authentication token on the client (to minimize XSS attacks) but you'll need to setup a CSRF prevention strategy as well.
Here's an article I've written that discusses the details in greater depth:
Token Based Authentication for Single Page Apps
Disclaimer: I work at Stormpath
I am planning a Cordova mobile application (a Meteor.js app to be precise) and I need to POST/GET some sensitive data from a remote server securely.
When the request is pointed at https endpoint is it secure? My guess is that it does not work this way.
Just to say - I have read some SO questions and searched google but most of them refer to CORS problems, which I am not facing.
Thanks for any help.
Yes and no
Sending data to a https server is secure?
Yes if you are sure that you are sending the data to your server
But, you might be connected to a public wifi, and somebody could be doing a man in the middle attack, so you think that you are sending your data to your sever, but the hacker is getting the data instead.
To avoid this, you can do server certificate pinning, there are a few plugins available, so you make sure the server where you are sending the data is really yours (comparing certificate fingerprint or checking some of the values)
https://github.com/EddyVerbruggen/SSLCertificateChecker-PhoneGap-Plugin
It depends on what you need. Https (TLS) will provide your mobile users with the certainty that they are communicating with the server that is identified by the certificate. It will also encrypt the communication between the server and the mobile application so no one can listen in.
It won't authenticate your users and allow you to serve certain data to specific users only. You'd need some kind of authentication scheme for that.
It won't protect you from XSS, CSRF, SQL injection or other attacks either. So it very much depends on what your requirements are, but https by itself is not enough to protect a website.
A Dropbox browser client with application API key and secret stored in its source code is a bad idea as anyone could impersonate the application using them.
But what about the Dropbox API key encoder, if used, can a
third-party obtain the original key/secret?
If an attacker obtain the key/secret pair, what is the worst case
scenario that can happen to users of the compromised application?
What are the best practices dealing with Dropbox security in a
browser only client in order to have a perfectly secure
implementation (if possible)?
I think that the application stored on the client can never be completely secure, but I still would like to hear from developers more experienced than me.
Thank you in advance for your help
Caveat: I'm not a security expert.
Using the encoder might discourage a casual "attacker" from picking up your app key and secret, but it doesn't provide any true security. Here's a line of code using the JS library that converts an encoded key back into the unencoded key/secret pair:
Dropbox.Util.atob(Dropbox.Util.encodeKey(encodedSecret).split('|')[1]).split('?')
That said, the security risk here is that someone else uses your app key and secret, which is arguably not the end of the world. Pretty much all client apps that use OAuth (in the browser, on the desktop, and on mobile platforms) suffer from this problem. For example, here's one article discussing Twitter's leaked consumer key/secret: https://news.ycombinator.com/item?id=5337099.
I think the most likely consequence of exposing your app key and secret is that someone will copy/paste your code and use your credentials. This would be misleading to users (who will see the name of your app when they authorize via OAuth), and if another app takes your key and uses it in a malicious app, your legitimate app might end up being collateral damage.
Looking at Twitter OAuth Libraries, I saw this note:
Be cautious when using JavaScript with OAuth. Don't expose your keys.
Then, looking at jsOAuth examples, I noticed that the keys are exposed in the code.
So my question is: How it is possible to not expose your keys when you use an OAuth library in Javascript?
Thanks.
UPDATE: Ok, maybe jsOAuth is not the right library to use, but how it is possible to do authentication with OAuth on a full Javascript web site?
As said in the documentation linked by you:
Written in JavaScript, jsOAuth aims to be a fully featured open source OAuth library for use in Adobe AIR, Appcelerator Titanium and PhoneGAP. In fact, anywhere that javascript can be used and has cross-domain XMLHttpRequests. For security reasons jsOAuth doesn't run in the browser. Browsers are only mentioned here for running the test suite. If you need jsOAuth in the browser, write an extension.
A good answer to your added question is available here:
Secure OAuth in Javascript
The only really reasonable way, right now, to do OAuth 1 in the browser, is to route API-calls via your server.
There simply is no way, as far as I have understood it, around this. If you do OAuth 1.0a calls through JavaScript from the browser -> You will HAVE to expose your consumer secret and access token secret, to at least the end user.
You cannot store these credentials in:
a cookie, the user can find them.
local storage, the user can find them (better than cookie though, since it does not entail sending a cookie back and forth all the time over HTTP)
in javascript, the user can find them (although this is probably your best bet since it is easier to obscure).
If it were only the access token secret that was exposed to the end user, that would be bearable - since it is in fact he/she who have authenticated your application. But losing your consumer secret is really not so hot, it means that your application is eligible for identity theft. I.e someone else could write an app that claims to be your app.
Even if you made it work securely in the browser, you are hampered by cross domain security blocks.
You could also make a script that sends all necessary values and parameters to the server to do the signing with.
The signed URL can then be sent back to the client (browser) that in turn does the actual request.
I have implemented OAuth 1.0a on the Twitter API that way using jsonp requests.
The benefit of this is that the response body is not relayed via your server, saving bandwidth.
That way you can have your cookie and eat it too.