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.
Related
I'm looking to implement some efficient (i.e. with good performance) logic that does payload signing in our web application. The goal is for the HTML5 client to have a guarantee that the contents of a received payload are indeed those that were generated by our backend.
We don't want to do payload hash generation with shared salt because the user can easily open the HTML5 source and find the salt phrase.
We have implemented RSA signing for now where our backend adds a payload signature using its Private Key and our HTML5 client validates it using its baked in Public Key. However the signature generation process takes 250ms (for a relatively small payload) and due to the nature of the signed request this amount of time is unacceptable.
The only other idea is to generate a shared secret at runtime every time a client initializes its session with the backend. The secret however can't be sent in plaintext form so it seems we're going to have to implement a Diffie-Hellman exchange mechanism, something we'd like to avoid if possible or automate with existing libraries.
Remember that the secrecy and encryption need to be done at the Application layer, due to the nature of how we sell our product. We're not looking to encrypt our traffic, this is something that our customers might or might not implement (since it's an intranet application). However, we have to avoid exposing stuff that are related to our licensing checking mechanisms etc to them. The backend is not cloud based and is not controlled by us, but installed on the customers' machines, on premises.
Frontend is Javascript and backend is Java.
Note that Diffie-Hellman exchange mechanism is not protected against MITM attack, therefore not encrypting traffic means that you need to authenticate the DH data coming from the server. This is why a web server using a DH-based cipher suite signs the DH elements sent over the network with the private key of its server certificate, for the client to check that those elements are really from the server that he wants to connect to. Those elements are public but need to be signed.
What you call "payload hash generation with shared salt" is a keyed-hash message authentication code, so it is based on a shared secret, as you noticed, and since you do not want to use this mechanism, it means that you do not trust the client. Therefore, you have to use asymetric cryptography to sign your payload.
Signing a server payload with an asymetric algorithm means that you first need to let the server share a public key with the client. Since you do not encrypt data between the client and the server, you need to deploy the server public key inside the client source code.
You talk about the signature generation process, but the signature check process on the client side is also very important in your case, because the total time the user has to wait for the result is the addition of the time to sign and the time to check the signature (moreover, the signature can often be anticipated on the server, if the data to sign is not dynamically generated, but the verification can never be anticipated). So you need a rapid way of checking a signature on the client side. First, sign a hash, not the whole payload. Then choose the fastest asymetric signature algorithm that is available in your development environment, on the client side. Note that checking an RSA signature is faster that checking a DSA or ECDSA one, for respective keys length corresponding to the same security level. So you should stay with RSA.
All of this until this line may not help you so much! Now there is a way to increase the performances using RSA to sign and verify signatures, and this way is rather the same that SSL/TLS implements to increase browser performances when downloading multiple pages or other objects from the same server: use a session cache. You share a common secret for a specific session with one specific user. Never use this common secret for other sessions. When the user is connecting for the first time, use RSA only once, to exchange an ephemeral shared secret or exchange DH material to create this shared secret. Then, each time the server needs to sign an object, it creates a keyed-hash message authentication code with this specific secret. Therefore, if the user finds the secret, for instance using the debug mode of his browser, it's not a problem: this secret is only here to help him know that something that comes from the server has not been altered. So the user can not use this secret to alter data exchanges between the server and other users.
We ended up by using TweetNaCl both on the client and on the server side. The library provides a every easy and fast way to do DH-like shared secret exchange without going through a custom implementation. With an ephemeral shared secret we can easily generate hashes instead of signatures for our payloads dropping from 250ms to 10μs. Also RSA signing the initial DH exchange is important and the only place we use RSA.
Please read #AlexandreFenyo answer for proper theory on how to usually handle such cases.
I would to ask a few questions to better understand some procedures. I'm trying to write a web api project which will be a backend for both web and mobile clients.
The problem that i've in mind is about security. I don't want to use Identity or any other providers. I want to use my own database user and role structures.
Only authenticated client applications should be consuming my application. So that anonymous applications should not consume it.
So what should be the approach ? I 've written a custom AuthorizationAttribute and check some custom headers like "AppID","AppSecurity" key which i store in my own database and if the client sends the right appId and the key it means the app is authenticated to consume the API which does not sound very secure to me.
Another issue is that ; Lets say i've developed a javascript web application and i've to first authenticate the application itself before making GET/POST/PUT/DELETE etc requests which means i've to add some kind of authentication data like username, appkey, password in one of the js files for sending the "AppID" and the "AppSecurity" keys in the header. A client who knows how to use some developer tools or fiddler can easily capture my header values that are being sent to the server side? Even if i pass authentication values on the body of my json request it still can be found on the js files that are sent to the client. I'm also confused about that tooç
So basically i want to build a server side api that will serve the data and get data from the authenticated client applications only. What i need is a simple example for that without using any identity providers.
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.
Quick background:
Full Javascript SPA AngularJS client that talks to a REstful API server. I am trying to work out the best authentication for the API Server. The client will have roles and I am not concerned if the user can see areas of the client they aren't allowed because the server should be air tight.
Authentication flow:
User Posts Username and Password to let's say /api/authenticate
If a user the server generates api token ( sha hash of fields or md5) and some other meta data determining roles to pass back in 1) post reply.
The token is stored in a session cookie (no exp, http only, ssl)
Each request after authentication takes the token in the cookie and verifies this is the user.
SSL user on server.
Questions:
Is this the best way to secure the server?
Do I need to worry about replay attacks w/ SSL? If so best way to manage this?
I tried to think of a way to do HMAC security with AngularJS but I can't store a private key on a javascript client.
I initially went the http authentication method but sending the username and password each request seems odd.
Any suggestions or examples would be appreciated.
I'm currently working on a similar situation using angularjs+node as a REST API, authenticating with HMAC.
I'm in the middle of working on this though, so my tune may change at any point. Here's what I have though. Anyone willing to poke holes in this, i welcome that as well:
User authenticates, username and password over https
Server (in my case node.js+express) sends back a temporary universal private key to authenticated users. This key is what the user will use to sign HMACs client side and is stored in LocalStorage on the browser, not a cookie (since we don't want it going back and forth on each request).
The key is stored in nodejs memory and regenerates every six hours, keeping record of the last key generated. For 10 seconds after the key changes, the server actually generates two HMACs; one with the new key, one with the old key. That way requests that are made while the key changed are still valid. If the key changed, the server sends the new one back to the client so its can flash it in LocalStorage. The key is a SHA256 of a UUID generated with node-uuid, hashed with crypto. And after typing this out, i realize this may not scale well, but anyway ...
The key is then stored in LocalStorage on the browser (the app actually spits out a your-browser-is-too-old page if LocalStorage is not supported before you can even try to login).
Then all requests beyond the initial authentication send three custom headers:
Auth-Signature: HMAC of username+time+request.body (in my case request.body is a JSON.stringify()'d representation of the request vars) signed with the locally stored key
Auth-Username: the username
X-Microtime: A unix timestamp of when the client generated its HMAC
The server then checks the X-Microtime header, and if the gap between X-Microtime and now is greater than 10 seconds, drop the request as a potential replay attack and throw back a 401.
Then the server generates is own HMAC using the same sequence as the client, Auth-Username+X-Microtime+req.body using the 6-hour private key in node memory.
If HMACs are identical, trust the request, if not, 401. And we have the Auth-Username header if we need to deal with anything user specific on the API.
All of this communication is intended to happen over HTTPS obviously.
Edit:
The key would have to be returned to the client after each successful request to keep the client up to date with the dynamic key. This is problematic since it does the same thing that a cookie does basically.
You could make the key static and never changing, but that seems less secure because the key would never expire. You could also assign a key per user, that gets returned to the client on login, but then you still have to do user lookups on each request anyway, might as well just use basic auth at that point.
Edit #2
So, after doing some testing of my own, i've decided to go with a backend proxy to my REST API still using HMAC.
Angular connects to same-domain backend, the backend runs the HMAC procedure from above, private key stored on this proxy. Having this on same domain allows us to block cors.
On successful auth, angular just gets a flag, and we store logged in state in LocalStorage. No keys, but something that identifies the user and is ok to be made public. For me, the presence of this stored value is what determines if the user is logged in. We remove the localStorage when they logout or we decide to invalidate their "session".
Subsequent calls from angular to same domain proxy contain user header. The proxy checks for user header (which can only be set by us because we've blocked cross-site access), returns 401 if not set, otherwise just forwards the request through to the API, but HMAC'd like above. API passes response back to proxy and thus back to angular.
This allows us to keep private bits out of the front end, while still allowing us to build an API that can authenticate quickly without DB calls on every request, and remain state-less. It also allows our API to serve other interfaces like a native mobile app. Mobile apps would just be bundled with the private key and run the HMAC sequence for each of their requests.
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.