Friday, September 19, 2014

Secured File sharing

We were building a social media piece on a website. Images and videos were uploaded by end user. We store media in a social media service called Pluck.

Pluck allows us to create multiple galleries like Personal, Friends or anything you could think off. We could set permission on folders managing whether anonymous user can upload to these folders via API. However, we noticed that the image path themselves are not secured. Meaning, say you upload an image to private gallery but if you get hold of the path anyone could view the file. Based on the privacy constraints of your website this could be a major issue. This is true with Google+ and FB as well I think (atleast when we tested)

So problem in hand is URL should NOT be accessible without making sure user is signed in to our website.

Other side effects we had to handle was however allow other features like social sharing work - since that is happening after user consent to share them outside out system.

First problem in hand was to secure access to the URL. Website use OpenID connect and idea was use the access token issued and authorize the image request. Every image request would include Authorization header as part of the request and token is validated. There were few other options discussed like cookie based access control etc. But sticking to Authorization header based solution sounded more RESTful or HTTP-kind and decided to use Authorization. Akamai had edge authorization model that allowed us to configure the token validation against our OpenID.

Second problem, having decided how to secure the URL, this had a direct impact on how image, video and audio were loaded. To allow authorization header to be included, means we cannot display images, for e.g., using "src" attributes. We had to issue an AJAX request to load the image, which would add the necessary headers. Response would be binary image data and fortunately there are couple of options to bind the binary to HTML5 controls. One is to bind them using "data uri" and other being bind them as "blob".  Read more here. Data URI was little complicated with base64 encoding involved and our application was Angular application and doing all this on javascript, faced bunch of issue and resolved them to get the base64 working and bind them. We did not opt to do this as it was too much to do on the client side. But if anyone of you guys interested, here is the link that can help to perform base64 encoding (btoa function did not work). We built an Angular directive to do all this for various html element.

At this point, we are able to load image securely and bind that to HTML5 element using blob attribute.

Third problem, going back to social sharing feature and some of this restricted contents cannot be shared anymore as, say, Pinterest is going to issue a get and above solutions in place would return nothing to Pinterest. So our next solution was to hand off a short-living image URL to social sharing providers and this link would expire and it would not affect the sharing either as these provider make a copy of the content and store them in their CDN. Keep it short, we are heading toward one of the 2 solutions - either use AWS or Akamai short living secure signed URL. Refer below links

Akamai was better as we were already using their service and we don't have to upload the image, instead since we are using their Remote Authorization Feature.

This solution may not fit for others but for us this worked out and there could be alternatives. Any other approaches?