Following this question: Can a cookie that was generated with Javascript (not send in the header by the server) be stolen / used by an attacker?
This is driving me crazy.
How can one ever keep state at the client using a FB access token?
One should use it to access resources on one's own server, and also from the FB server. Assuming that one uses a js framework (Backbone / Marionette) and REST authentication.
It cannot be encrypted as such, and yet there is no other way than to use a cookie to keep state at the client.
I have done plenty of research.
Every source mentions to keep state at the client, to avoid server sessions, yet I can't find a single source that explains how to do it safely.
If you know the answer, please share.
Thanks.
You can store information on the client safely if the server is delivering it.
You can encrypt or sign the data using a secret key which only the server knows and decrypt/validate the information using it.
However, by definition, you cannot store information safely which is also generated on the client itself. It's just the client playing with itself. Anyone can inspect what exactly is going on, so you can't sign or encrypt anything using any secret key, because by definition the key ceases to be secret if you give it to every client. You can also not trust any information the client is sending to the server because the client is free to send anything to the server it wishes. You cannot trust any code running on the client because it is entirely out of your control.
Related
I've recently started using modern front end technologies like React/Angular and as a result have started using tools like JSON Server to recreate dummy restful db interactions.
My understanding is that most rest api's authenticate via some kind of token and secret that is either passed as part of the url or as a header. This seems fine for retrieving data, but is it not risky exposing these login credentials in a front end language like JS when writing is possible?
My thinking is that all it would take is a simple view source for somebody to steal my token/secret and potentially start populating my db with data.
In the problem that you describe the client (browser) has the login credentials because the server provide them. There is no "exposing" as the credentials are already exposed. Exposing your credentials to every client means that there is no security.
When we talk about security we consider as a client the browser not the real person that operates the browser. As you said, the real person can access all the browser's data.
To secure your API the secret key must be kept secret. This means that each client has a different key and uses it to get their data/services from your RESTfull server.
In a simple senario this key can be used/managed like the session id.
The client should first pass through an authorization process (login maybe) and then a temporary key can be generated for the client's session.
Generally, a key is converted to rights. If every client by default has the key, everyone has the default rights, so you may also remove the key and set the default rights to every request.
A client that you don't want to have full access to your db should have a key that gives him limited access to your db.
On the other hand, if the client provides the key, this is secure. For example a php code on a server that uses the secret key for accessing your API.
I'm currently working on a mobile app that is built primarily with HTML and css, then run with phonegap. Part of the app requires that the user logs in and sync data with a backend. I want it done in such a way that once the user is logged in on their device they will remain logged in until they manually log out; they should only have to enter their information once. I've found some decent information when working with native code, but not so much that applies to my situation.
Right now, I'm not sure how to properly do this in a way that is secure. My first idea was to handle the login normally, then pass back a secret code that is stored both in local storage on the device, as well as in the database under the user that was authenticated with it. On subsequent requests it would pass this and allow access to the user that had a matching secret code. My question is whether this is secure enough to be practical?
I've also done a bit of research and it appears JWT is similar to what I'm looking for? My two concerns for this approach are:
How do I maintain the persistent login with this method.
What prevents someone from spoofing a connection? From what I know there's a secret string that is passed with each request to verify it. But, since the code in my app would be visible to someone who knew how to access it what is to prevent them from learning what the secret is and spoofing a connection?
I assume my questions with JWT are due to me misunderstanding some fundamentals of how it works. If it satisfies what I'm looking to do I'd much rather use a more standardized process like JWT as opposed to writing my own solution.
Am I on the right track with what I'm thinking above or am I way off base?
Your idea is correct and this is how it's usually done. It is a combination of cookie and session concepts. A 'session' is started on the server once the user logs in. The session is identified by a string (e.g. md5 format) and passed back to the client. The string is saved in a cookie on the client, and since cookie info is sent in each HTTP request, the server can assign that request to the session, thus considering your user as logged in. The signout process later basically consists of removing your cookie, and / or sending a request to the server to remove the session object.
In most HTTP server side frameworks there is an API used for sessions, so you don't have to reinvent the wheel. And yes, it is secure enough, as you don't usually base your security on this layer of transport, but rather on a lower layer by introducing https.
I have a JavaScript application.
It's built with jQuery.
It uses $.get() to pull JSON data from a server, and uses the data to load a puzzle.
I want to distribute the JavaScript application to clients, and make it easy for them to install.
I'd like it to simply give them a JavaScript block they can drop into their page, and it will interact with my API.
I'm not passing sensitive data, any my API is protecting the database from SQL injection, etc.
I just want to try to prevent unauthorized use of my API, and I can't think of a way to do that with JavaScript, since anyone with a DOM inspector can scrape any credentials from any variables or can monitor any server traffic POST or GET data...
Would it be possible to authenticate the referrer on the other side?
I know that's not bulletproof, but it's not sensitive data. I just want to reduce the unauthorized use as much as possible..
Any ideas?
note: I know obfuscating an API key or something is futile, I'm wondering what other controls I could put in place other than a traditional key to identify the caller to the API.. I have full control over the API itself so I could do anything on that side of things...
JavaScript authentication has holes
With JavaScript, just about any authentication system is going to have holes, simply because the code runs directly in the browser and can be seen by anyone (as can the network calls). So there are a couple of things you can try, depending on your situation.
IP whitelisting
If you are distributing this application to a small subset of clients, and you know exactly where they will be accessing it from, you could use IP whitelisting. This really is the only way to completely secure the API. However this method is very cumbersome, since with every new client you have to update the API whitelist, and considering what you're talking about here probably not what you're looking for (but I mention it just because it is a possibility).
Access tokens
Another method is access tokens. This is a common method used by sites such as Facebook. There are two methods to do this. One is to just give each client a secret key. You can have the same secret key for everyone, but this is not very secure. Having a different secret key for everyone allows you to not only track usage, but also revoke access privs if necessary.
The first method for access tokens is to just give it inside the JS client. However this means that anyone who looks at the source will be able to access your key, and make requests using it.
The second method is to have the secret key stored somewhere on the SERVER of the website where your client runs. This server can then make a server-to-server call using that key to obtain a temporary session token. People will still be able to access the temporary session token via the front-end, but they will have to access this site first in order to get it (this allows you to pass off responsibility for handling this to the website operator) and the token will eventually expire. However this means there needs to be some server-side code, and the app won't just be a drag and drop thing.
For the method given above you can also look into things like OAuth, to avoid re-inventing the wheel.
Whitelist hard-cap
Another possible thing using IPs is to set a hard-cap on either how often or how much per day a specific IP can hit the whitelist. Though you may run into problems with users who REALLY like the puzzles, this will prevent some of the potential abuse.
This is probably a generic security question, but I thought I'd ask in the realm of what I'm developing.
The scenario is: A web service (WCF Web Api) that uses an API Key to validate and tell me who the user is, and a mix of jQuery and application on the front ends.
On the one hand, the traffic can be https so it cannot be inspected, but if I use the same key per user (say a guid), and I am using it in both then there's the chance it could be taken and someone could impersonate the user.
If I implement something akin to OAuth, then a user and a per-app key is generated, and that could work - but still for the jQuery side I would need the app API key in the javascript.
This would only be a problem if someone was on the actual computer and did a view-source.
What should I do?
md5 or encrypt the key somehow?
Put the key in a session variable, then when using ajax retrieve it?
Get over it, it's not that big a deal/problem.
I'm sure it's probably a common problem - so any pointers would be welcome.
To make this clearer - this is my API I have written that I am querying against, not a google, etc. So I can do per session tokens, etc, I'm just trying to work out the best way to secure the client side tokens/keys that I would use.
I'm being a bit overly cautious here, but just using this to learn.
(I suggest tagging this post "security".)
First, you should be clear about what you're protecting against. Can you trust the client at all? A crafty user could stick a Greasemonkey script on your page and call exactly the code that your UI calls to send requests. Hiding everything in a Javascript closure only means you need a debugger; it doesn't make an attack impossible. Firebug can trace HTTPS requests. Also consider a compromised client: is there a keylogger installed? Is the entire system secretly running virtualized so that an attacker can inspect any part of memory at any time at their leisure? Security when you're as exposed as a webapp is is really tricky.
Nonetheless, here are a few things for you to consider:
Consider not actually using keys but rather HMAC hashes of, e.g., a token you give immediately upon authentication.
DOM storage can be a bit harder to poke at than cookies.
Have a look at Google's implementation of OAuth 2 for an example security model. Basically you use tokens that are only valid for a limited time (and perhaps for a single IP address). That way even if the token is intercepted or cloned, it's only valid for a short length of time. Of course you need to be careful about what you do when the token runs out; could an attacker just do the same thing your code does and get a new valid token?
Don't neglect server-side security: even if your client should have checked before submitting the request, check again on the server if the user actually has permission to do what they're asking. In fact, this advice may obviate most of the above.
It depends on how the API key is used. API keys like that provided by Google are tied to the URL of the site originating the request; if you try and use the key on a site with an alternate URL then the service throws and error thus removing the need to protect the key on the client side.
Some basic API's however are tied to a client and can be used across multiple domains, so in this instance I have previously gone with the practice of wrapping this API in server side code and placing some restrictions on how the client can communicate with the local service and protecting the service.
My overall recommendation however would be to apply restrictions on the Web API around how keys can be used and thus removes the complications and necessity of trying to protect them on the client.
How about using jQuery to call server side code that handles communication with the API. If you are using MVC you can call a controller action that can contain the code and API key to hit your service and return a partial view (or even JSON) to your UX. If you are using web forms you could create an aspx page that will do the API communication in the code behind and then write content to the response stream for your UX to consume. Then your UX code can just contain some $.post() or $.load() calls to your server side code and both your API key and endpoint would be protected.
Generally in cases like this though you proxy requests through the server using 'AJAX' which verifies the browser making requests is authorized to do so. If you want to call the service directly from JavaScript, then you need some kind of token system like JSON Web Tokens (JWT) and you'll have to work out cross-domain issues if the service is located somewhere other than the current domain.
see http://blogs.msdn.com/b/rjacobs/archive/2010/06/14/how-to-do-api-key-verification-for-rest-services-in-net-4.aspx for more information
(How to do API Key Verification for REST Services in .NET 4)
I'm checking out amazon simpledb documentation. They mention only server side languages.
Is there anyway to insert data into the db directly from the client side without going through a server?
If not, how come?
Yes and no. Since you need to protect your secret key for AWS (hackers could use it to abuse your account), you can't authenticate requests in JS directly.
While you could create an implementation in JS, it would be inherently insecure. Practical for some internal uses, it could never be safely deployed (as that would expose your secret key). What you could do instead is use your server to authenticate the requests to SimpleDB and let the JS perform the actual request to Amazon. Though it's a bit roundabout, it would work.
The downside is that you'd need to do a bunch of processing on the client side. You're also likely fetching more data than your app consumes/outputs, so processing the data on the client instead of on the server would likely encounter more latency simply because you're transferring more data to the user and processing it more slowly.
Hope this helps
If not, how come?
Security. You authenticate to the DB with your developer account. Amazon does not know about your end users (which it would need to, in order to authenticate access directly from the browser). It is up to the application code to determine what end users are allowed to do and what not.
That said, there is the Javascript Scratchpad for Amazon SimpleDB sample application. It does access SimpleDB directly from the browser (you have to type in your AWS credendials).
SimeplDBAdmin is a Javascript/PHP based interface:
http://awsninja.com/2010/07/08/simpledbadmin-a-phpmyadmin-like-interface-for-amazon-simpledb/
The PHP side is a relay script[relay.php] which will pass the requests made from the Javascript client and send them on to the server, takes the response from the server and reformats it for the client. This is to easily get around the cross-domain problems with Javascript[if the web client had downloaded the web page containing the javascript code from www.example.com it will only allow javascript to connect back to www.example.com by default].
Everything else, including request signing, is done by the Javascript code.
Also note that Amazon has released a new beta service recently to allow you to setup sub-accounts under your Amazon account. The simpleDB protection is very basic[either on or off per account] but as it does provide some limited form of request tracking, it could be argued that using Javascript and giving each user their OWN userid and key for request signing is MORE secure. Having every user use the SAME userid and certificate would, of course, be insecure.
There is a free, pure JavaScript interface available. Please see https://chrome.google.com/webstore/detail/ddhigekdfabonefhiildaiccafacphgg
See this answer to the similar question on allowing secure, anonymous, read-only access to SimpleDB from untrusted clients: anonymous read with amazon simpledb .
Some variations from that answer:
don't set access policy to read-only. However, it allows fine grained control, so you may still wish to limit the kind of writes allowed
don't be anonymous. The AWS docs on token based auth and example apps show parallel paths: anonymous access or non-anonymous AWS/federated access with your credentials but without exposing your secret key.