I’ve been developing and maintaining a Chrome extension for my company where each customer would be assigned a unique ID in the code. We’ve been using the ID to determine license status and login to our services (paid extension with monthly subscription fee).
So far we’ve hosted the extension files ourselves and had unique update URLs for each customer extension. This has been nice and simple; go to our website, click install and you’re done. With the latest Chrome release, however, that installation procedure has been thwarted by Google since they now require users to install extensions by dragging and dropping the CRX files into the chrome://chrome/extensions/ tab. Unless of course your extension is available through Chrome Web Store – which leads me to the problem:
- We don’t want the drag and drop CRX installation – requires Web Store.
- We don’t want multiple versions of the extension (one for each customer) on the Web Store since that’s a maintenance hell every time we update the extension.
- We don’t want to use Web Store licensing because:
- It requires OpenID login.
- We sell the extension to schools with many students where the school pays the bill – not the student.
- We don’t want to lock our payment method to one browser, i.e. we want to be able to maintain licensing and payment through our or servers.
- We don’t want to have users input a license key since that’s too much of a risk with several thousand students having to input the key – also it requires some kind of storage (cookies/localStorage) which would eventually get cleared requiring the license key to be input again.
I’m not 100% certain that my statements are completely correct, so feel free to enlighten me if I missed something.
If they are, the question is whether or not we can somehow tailor the extension for each customer through the Web Store (using the unique ID) without needing to publish one extension per ID?
As a side question any answers that might solve the problem with another method will also be accepted.
For the answer below, I assume your app is a packaged app, not a hosted app.
I have a solution that’s fairly similar to your current implementation, but adds one extra step for users. For the student user, the process will work like this:
https://myserver.com/activateapp.php?custid=123456789. You host one such link for each institution you support, and it is the institution’s job to provide its link to its students. This link activates the app.From an implementation point of view, here’s how it works:
https://myserver.com/activateapp.php, on your server. Server-side, check that thecustidparameter is valid. If it is not, send a 404 error.https://myserver.com/activateapp.phpthat scans the URL and picks out the customer ID. Once the app finds the ID, it stores it in localStorage. Since invalid customer IDs produce a 404 error, you know that when the content script runs, the page is not a 404 error; therefore, it is reading a valid customer ID.localStorageerased unless your app is programmed to wipe its own storage, or the user does it from the console. Storage erasure will never “accidentally” happen. Even the strongest browser-wide data/cache purge will only clearlocalStoragefrom Web pages, not from apps and extensions.For extra security — if you don’t want people randomly guessing customer IDs — you can add an extra signature parameter, like
https://myserver.com/activateapp.php?custid=123456789&sig=2464509243. This extra parameter is some server-verified transformation of the customer ID (ideally a cryptographic signature or a purely random value associated with the ID in a database) that is impossible for anyone to guess. When the request foractivateapp.phphits the server, it checks for a valid customer ID and a valid corresponding signature. Of course, this doesn’t stop people who have legitimate access to a valid link from sharing the link to unauthorized people, but I expect that was a vulnerability that existed in your old system anyway.