New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adds the ability to add 'scopes' to a gaia auth token #545
Conversation
d2e615d
to
77c6555
Compare
Rebased from develop so that maybe one day we can merge 😄 |
Hey @hstove! I'll try to wrap a review on this in the next couple days |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks great @hstove -- two things I would suggest, though:
-
It'd be great to have unit test coverage for the scopes field. Something like just testing its presence in the outputted JWT from
connectToGaiaHub()
is probably enough. -
We should have JSDocs for the
connectToGaiaHub
function -- it now has enough additional features over just using the Blockstack session's automatic connection that developers may want to be calling it directly.
Awesome, thanks for the updates @hstove -- this looks good to me |
JeHunter commented: Very excited about this one. When it’s merged, will the core blockstack.js documentation be updated to support scoped auth tokens. I looked at Hank’s example in the PR and it wasn’t entirely clear to me how to set the scopes and enforce them. |
Yes, we'll definitely update our docs. I can write up some of that stuff. I'm not sure how we want to move forward with this. @kantai has reviewed an approved. @larrysalibra or @yknl any thoughts or should we move forward? Are we waiting on anything for the user session PR? |
* @param {string} gaiaHubUrl - the Gaia hub URL you want to connect to | ||
* @param {string} challengeSignerHex - a private key used for signing an auth token | ||
* @param {string} associationToken - an optional association token to add to your auth token | ||
* @param {string} scopes - an optional array of scopes to include which will only allow |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could include better documentation on the scopes
array here -- basically saying what the scopes array can be used for. What do you think about including that documentation here versus in the gaia docs?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it'd be best to have them in both places. I'll add more specific notes to the blockstack.js docs here - good idea.
Hmm -- @hstove, it might make sense to include docs on what the scopes array is used for in blockstack.js rather than in gaia -- what do you think about those two options? |
While this is really nice, it does not (yet?) affect the public API. Will the scope be introduced to the UserSession creation? That gives developers the assurance that the app only writes to the right domain/file path. Are the other motivations for this? Could you add them to the PR? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've read through the original github issue thread in the gaia repo and have trouble seeing a use case of this that can't also be solved with gaia inboxes and do so without giving a 3rd party relatively unfettered (beyond a file name/path prefix) write access to your app's storage bucket.
@markmhx asked a similar question and the response he got from @aulneau and @hstove was "we need this for team apps"
Can you expand on this?
Is the idea that in a team app, there would be one owner and all the data would be written in the owner's storage bucket?
@friedger writes
While this is really nice, it does not (yet?) affect the public API.
Will the scope be introduced to the UserSession creation? That gives developers the assurance that the app only writes to the right domain/file path.
To build on @friedger 's comments:
It seems like this functionality for uploading a file using a scoped auth token should be added to the putFile
method instead of pulling in lower-level, non-public (in this library) implementation methods.
Let me walk through what I understand as a typical use case for this feature.
Assume an app example.com with two users Alice and Bob. Alice wants to let Bob upload files to her gaia hub in her example.com storage bucket under the path prefix bobs-stuff/
.
- Alice's instance of example.com generates a scoped gaia auth token with the following data:
const scopes = [
{
scope: 'putFilePrefix',
domain: 'bobs-stuff/',
},
];
-
Alice's instance of the app sends the generated scoped gaia auth token to bob in a secure manner (ie. by encrypting it for bob and storing it in in a known location in alice's gaia storage bucket).
-
Bob's instance of the app uses the scoped gaia auth token to write
bobs-stuff
to Alice's by providing the scoped gaia auth token to theputFile
function.
We're currently missing a developer-friendly API for generating the auth token in step 2 and a way for communicating it to user in another app instance.
Here's how a more developer friendly api might look:
// alice's app instance
import { UserSession } from 'blockstack'
// assume alice has already signed in
const userSession = new UserSession()
userSession.createStorageToken({username: 'bob.id', path: 'bobs-stuff/')
// bob's app instance
import { UserSession } from 'blockstack'
// assume bob has already signed in
const userSession = new UserSession()
const options = { bucket: { username: 'alice.id' }}
const content = { 'stuff': 123 }
userSession.putFile('/bobs-stuff/item.json', content, options)
/**
The above options object implies:
const options = { encrypt: true, encryptToUser: 'alice.id', bucket: {username: 'alice.id', appDomain: 'https://example.com'}, sign: true }
*/
This example adds an additional option bucket
to putFile
to specify in which storage bucket the file should be written.
It also adds a function createStorageToken
that generates the scoped gaia storage token, encrypts it for the given user and stores it a known location.
Specifying a bucket in putFile
retrieves the scoped storage token in the known location, decrypts it and then attempts to write the file content to that location.
The above pseudo code assumes the ability to look up a key for another user ships first: #458
Please let me know if i've misunderstood the use case of this feature. Happy to discuss in more detail.
Yes -- if Alice does not have a Gaia hub at all, Bob can share his storage with her using this feature.
Yes -- in corporate/enterprise settings, it may be the case that employees do not have Gaia hubs at all, but instead share one operated by their department (for example). In this case, the department manager is the data owner.
I consider this to be a feature. We want the easiest way of using Gaia to be assuming the user has their own Gaia hub; we don't want to encourage developers to build apps where most users don't own their own data. But, that said, I think your recommended API changes (e.g. |
Something I think we should add here is the ability to pass a Gaia config object into |
Sure, but when you think about the use case, if you want to do signing or especially encryption with a scoped token, you're probably going to encrypt with a custom group key. Meaning we'd need to change |
It sort of already supports both -- if you set |
Ah, I actually didn't know that. Nice! |
@hstove is still working on this PR |
closing this for now. please re-open if you think this requires attention. if you re-open, please also suggest who could help resolve and carry it to the finish line 🙏🏼 |
This implements the client-side requirements to work with our new 'scoped auth tokens' feature in Gaia.
Essentially, you can create an auth token with a
scopes
parameter in the payload. See stacks-network/gaia#142 (comment) for more info, and stacks-network/gaia#145 for the gaia PR.Here is a code sample that I've tested in a local application, and it works as expected:
Overall I'm extremely excited about the possibilities this opens up for decentralized collaboration.