My objective for a project I’m working on was to find a secure and simple way to publish ephemeral content without actually sharing files or hosting it anywhere.
I’m not going to lie – this has been a super difficult problem to solve. Here’s the Apps Script library I came up with.
Background
The project needed to find a way of securely sharing content with a 3rd party browser based app that normally needs its input data from an uploaded file. So the normal work flow would either be to download a file from Drive, then upload it or host the drive file somewhere that could serve it up to the app.
I use Google Forms data to create a network visualization of the responses, then export the result to Drive as a GraphML file. NodeXL, which is an Excel Add-on that runs on the desktop, usually consumes these kind of files.
This extra step was to be able to get an immediate vizualisation using a hosted version of gephi-lite and avoid all the downloading and uploading faff associated with a desktop application.
Objectives
This Drive data could be private, so I wanted the solution to meet these objectives
- Create a link to content that would work from the browser, a Node or other server based app, from Apps Script and most importantly, from web based app without hitting CORS problems
- Limit the longevity and number of times the link could be used
- Avoid uploading the data to any hosting service
- Avoid the need for login/auth while keeping the data private to the person creating the link in the frst place.
Solution
Workflow summary
- The user creates a link request by passing over an access token, some optional metadata, and the content that will need served.
- The ContentServer writes the content to the user cache belonging to the requesting user. It will also compress the content, and if necessary, it can also spread the compressed data across multiple physical cache entries.
- This returns a public link that eventually leads to the original content. The link has a limited lifetime, and a limited number of usages set by the original creator. It also has various fingerprint validation checks built in. You can use this link without the need for login or auth to access.
- Both the public and private link are one off – it will never generate the same link. The webapp link is useless without the url parameters, and will return an error. The url parameters are checked against the cache contents to ensure that the authorized cache entry is being accessed
- The link is to a webapp, managed by the library which accesses metadata in the script cache. It doesn’t return anything directly to the user, but instead calls itself again, this time with the private link it found in the script cache, impersonating the original user that created the content.
- This allows it to access the user cache, decompress the data and use Apps Script’s ContentService to return the original data.
Examples
Links to library etc, at bottom of article.
Hello world
Sharing the contents of a file
Serve json content
Allow more than 1 access and/or change the link lifetime
Probing
You can use probe on the returned links if you want to check on whether the link is live. Just add &probe=yes to the returned link. You’ll get this served as JSON
Probing an expired link will return this
probeInfo
You can include probeInfo with the content – this will be returned in response to a probe request.
Note that probe requests never return content data, and only access the public cache. Accessing a probe counts as an access, if your use case includes probing then retrieving content, set the maxHits to more than 1.
Add-on usage example
For this project I needed to feed a web hosted (Gephi) with GraphML content from a Drive file created by the Add-on. Gephi normally expects files to be interactively uploaded, but it also takes a parameter to pick up a feed from a remotely hosted file.
I didn’t want to temporarily host this file anywhere, so using this one shot Content serve method was a good solution, especially since it defeats the CORS problem you would normally get with Apps Script content service in this scenario.
Here’s the card (it’s an editor Add-on) invites the user to do a quick online visualization of the GraphML file they’ve created in previous steps.
Clicking on the “viz lite” button will prepare content taken from the graphML file on Drive, create one off links and startup gephi lite using the public link as input. Gephi will be able to read the file content without needing any oauth complexity. Each time you click a button it creates a new one-off link, which expires shortly afterwards or after it has been used once.
Links
To use this library you’ll just need the BmContentServer library ID
12ZqFY1xFQjjuF43JsvQbOASfPwuiazMKTTlwNSGgxyjHLaJ1HC_hu2w5
The code on Github if you are interested.
Add an Exports script file in your project with this content.
The test code mentioned in this article is here or on github.
Related
Here are a some other articles that could provide some background on some of the code used in this library