Ever needed to deliver images securely? I had a usecase for delivering map tiles only if the user was authenticated - but I was using stateless authentication with Java Web Tokens (JWT). In order to use web tokens I need to place an Authentication header on each web request - easy enough. But that isnt possible to do when using a html img tag - it only allows for a url souce.
So you have two options - extend your JWT token reading service to allow it to read tokens from the url params object too (ie <img src='someurl?token=foo'> ) or instead of using the standard src attribute - use javascript to securely download the image data into a blob, and use the html5 blob data attribute for img tags.
This angular directive will do such a thing. I based my solution on this source code- except noting adding that I use an angular service "Authentication" that has a promise that will resolve only if there is valid non-expired authentication (and will refresh the token if expired).
So I only needed to modify the directive's core method to add my extra waitForAuthenticated() promise.
attrs.$observe('httpSrc', function (url) {
revokeObjectURL();
if (url && url.indexOf('data:') === 0) {
$scope.objectURL = url;
} else if (url) {
Authentication.waitForAuthenticated().then(function(ok){
$http.get(url, {
responseType: 'arraybuffer',
headers: {
'accept': 'image/webp,image/*,*/*;q=0.8'
}
})
.then(function (response) {
var blob = new Blob(
[response.data],
{type: response.headers('Content-Type')}
);
$scope.objectURL = URL.createObjectURL(blob);
});
});
}
});
The blue text is the core of the directive, pipeling the securely delivered image data into an HTML objectURL. You can attach headers easily using an injected interceptor to all $http requests.. This wont work on older browsers not supporting the objectURL standard.
No comments:
Post a Comment