Open jcnelson opened 6 years ago
I like this proposal. Does this mean that single player apps will now also be published in the user profile? Maybe we should encrypt the app origin as well for single player apps.
Yeah, that's a good idea for single player apps. I'll update the proposal.
I like this proposal and wouldn't object to going forward with it, but there's another (very similar) option which might be a little less error prone in the event of a synchronization issue between those two structure (apps
and hubUrls
):
Basically, you still use apps
and hubUrls
, but hubUrls
is a list of (encrypted) hubs, rather than a dictionary. Then, when logging in (or can be cached), the browser checks to see which of the hubs is capable of writing to the appropriate readURL and then uses that. It's functionally pretty similar, but it doesn't have a parallel structure that could get out of sync (let's say I'm manually editing my profile, and forget/don't know what the hubUrls entries are for).
Basically, you still use apps and hubUrls, but hubUrls is a list of (encrypted) hubs, rather than a dictionary. Then, when logging in (or can be cached), the browser checks to see which of the hubs is capable of writing to the appropriate readURL and then uses that. It's functionally pretty similar, but it doesn't have a parallel structure that could get out of sync (let's say I'm manually editing my profile, and forget/don't know what the hubUrls entries are for).
As long as there is a well-defined approach to pairing Gaia hub to its read URL, then I'm fine with this solution. I'm assuming the steps are (1) get the /hub_info
route for each Gaia hub in hubUrls
, and (2) match the read_url_prefix
. However, I still have questions pertaining to how we handle the following plausible scenarios:
Having a hubUrls
list gives us a way to unequivocally bind an application to a (hub, read URL) pair, so that if the hub stops corresponding to its read URL, the browser can both update the read URL and prompt/inform the user that it needs to do so on the next sign-in.
Having a hubUrls list gives us a way to unequivocally bind an application to a (hub, read URL) pair, so that if the hub stops corresponding to its read URL, the browser can both update the read URL and prompt/inform the user that it needs to do so on the next sign-in.
Cool, I'm convinced.
As a stepping stone to implementing this, I think it's fine for now if the user can simply change their Gaia hub in the settings page. As long as the user's Gaia hub URL in the apps
field of their profile gets updated and uploaded to their zone file's Gaia hub on their next sign-in, then users can select where their application data lives and multi-reader storage can continue to work. I'll be able to give a proof-of-concept demo in the CLI shortly.
I have this working in the CLI authenticator. You pass your desired hubUrl
on the CLI, and your profile gets updated with the read URL of that hub whenever you sign into an app.
@jcnelson it seems this issue should be closed in favor of https://github.com/blockstack/blockstack.js/issues/540?
TL;DR
Make it so the user's profile object points to both read and write URLs for Gaia hubs on a per-app basis, and pass the write URL as
hubUrl
in theauthResponse
token.Background
Blockstack's promise to users it that they own their own data. Part of that promise means that a user's data gets hosted wherever the user wants. Arguably, this also means the user can do so at the granularity of specific applications, since the nature of the data determines how it is stored. This entails making it so users have the ability to select which Gaia hub an application will use to store its data.
Design and Implementation
I think the shortest-path-to-success is somewhat straightforward: Extend the
apps
object in the user's profile to contain both Gaia read and write URLs. Right now, it only contains the read URL (and even then, it's not honored---see https://github.com/blockstack/blockstack-browser/issues/1488).When the user completes the sign in (in
app/js/auth/index.js
, atcompleteAuthResponse()
), theauthResponse
JWT returned to the application should contain ahubUrl
value that corresponds to the user's chosen Gaia hub for that application.this.props.api.gaiaHubConfig.server
)apps
object exists for this application), then thehubUrl
should be the write URL that corresponds to the read URL in the application's entry in theapps
object in the profile.What is still needed is a way to store the write URL in the profile in a backwards compatible way. I recommend the following scheme. Instead of this:
We have this instead:
The
hubUrls
object encodes the encrypted write URL for an application. It should be encrypted with the app public key because knowledge of the write endpoint is only pertinent to the writer. We can use the usualencryptECIES
method to generate this ciphertext, anddecryptECIES
to decrypt it.If the
hubUrls
object exists in the profile and has an entry for the application, thecompleteAuthResponse()
method should use that instead of the defaultthis.props.api.gaiaHubConfig.server
URL). Otherwise, it uses the defaultthis.props.api.gaiaHubConfig.server
URL.Backwards Compatibility
When the user signs into an app for the first time, then an entry is added to the
hubUrls
in addition to theapps
objects.If the user signs in and they don't have a
hubUrls
entry, they use thethis.props.api.gaiaHubConfig.server
value as before.EDIT: For single-player apps, we do not want to expose either the read or write URLs. To achieve this, when a user signs into a single-player app for the first time, the Browser would insert the following:
Both the origin and the write URL will be encrypted. No read URL will be inserted into the
apps
object (since this information can be obtained from the write URL).Execution
I'm happy to take the lead on all of the above. However, I think someone more versed in non-CLI user experiences should take the lead on adding a GUI for managing your
hubUrls
.Thoughts? @kantai @yknl @larrysalibra