Skip to content

getSignedUrl requires private_key #211

Description

@stephenplusplus

To generate a signed url, we need a private_key: https://developers.google.com/storage/docs/accesscontrol#Signed-URLs & https://github.com/GoogleCloudPlatform/gcloud-node/blob/v0.6.0/lib/storage/index.js#L267

We get this if a user provides a credentials object or path to a keyfile, but not in GCE or in the future, GAE. Is it going to be possible to get the private key in those environments?

Activity

  1. changed the title [-](storage) getSignedUrl requires `private_key`[/-] [+]storage: getSignedUrl requires `private_key`[/+] on Oct 5, 2014
  2. changed the title [-]storage: getSignedUrl requires `private_key`[/-] [+]getSignedUrl requires `private_key`[/+] on Jan 20, 2015
  3. added this to the Storage Future milestone on Feb 2, 2015
  4. stephenplusplus commented on Apr 30, 2015

    @stephenplusplus
    ContributorAuthor
  5. stephenplusplus commented on Aug 24, 2015

    @stephenplusplus
    ContributorAuthor

    The best solution is to just require private_key as an argument to the function.

  6. jgeewax commented on Aug 24, 2015

    @jgeewax
    Contributor

    Hmm... When I get started I have a credentials.json file -- which has a private key as one of the properties... Could we maybe also accept a credentials file?

  7. stephenplusplus commented on Aug 24, 2015

    @stephenplusplus
    ContributorAuthor

    If they have a keyfile, this will work everywhere:

    var gcs = gcloud.storage({ keyFilename: '...keyfile.json' });
    gcs.bucket('bucket').file('file').getSignedUrl();

    If they don't provide a keyfile, the callback would have received an error. So, I was thinking:

    var gcs = gcloud.storage();
    gcs.bucket('bucket').file('file').getSignedUrl({
      // ...
      client_email: '...',
      private_key: '...'
    }, function() {});

    This is similar to how ruby does it: googleapis/google-cloud-ruby#196

    And this is already quite an edge case, because we're saying "hey, since you didn't provide a credentials object earlier, how about you give us one now? Are you suuuure you don't have one?"

    Any solution really works, as long as we have some way to make it work. Vote?

    @jgeewax

    • config.private_key & config.client_email (string)
    • config.credentials (object)
    • config.keyFilename (string)
    • None! Use docs to say "This method only works with a manually authorized instance of Storage. If you haven't already, please provide a keyFilename or credentials object to Storage."

    @stephenplusplus

    • config.private_key & config.client_email (string)
    • config.credentials (object)
    • config.keyFilename (string)
    • None! Use docs to say "This method only works with a manually authorized instance of Storage. If you haven't already, please provide a keyFilename or credentials object to Storage."

    @callmehiphop

    • config.private_key & config.client_email (string)
    • config.credentials (object)
    • config.keyFilename (string)
    • None! Use docs to say "This method only works with a manually authorized instance of Storage. If you haven't already, please provide a keyFilename or credentials object to Storage."
  8. jgeewax commented on Aug 24, 2015

    @jgeewax
    Contributor

    Shouldn't we then offer the same argument handling that gcloud.storage() accepts?

    var args = <something>
    var gcs = gcloud.storage(args);
    gcs.bucket('bucket').file('file').getSignedUrl();
    gcs.bucket('bucket').file('file').getSignedUrl(args, function() {});

    So any valid value of args for gcloud.storage() calls should also work for .getSignedUrl() calls ...?

  9. stephenplusplus commented on Aug 24, 2015

    @stephenplusplus
    ContributorAuthor

    I think that's weird, since getSignedUrl is a method on a File instance, and just like all of the other methods, it requires a correctly initialized Storage instance to work.

    Storage(auth) -> Bucket -> File -> getSignedUrl
    

    It is just weird to one-off our hierarchy and auth:

    Storage -> Bucket -> File -> getSignedUrl(auth)
    

    I think this maybe changed my mind, though. If a user ever has a credentials object to give, or a keyfile path, we should say "Give it to .storage()". That way, all of the methods will work as expected. For these two methods, we can add a docs note: "Be sure you have provided a keyfile or credentials object, otherwise these methods will not work."

  10. jgeewax commented on Aug 24, 2015

    @jgeewax
    Contributor

    I'm just thinking about what's easiest for me. In most cases, storage already has a credentials file, so I'm good. But what if I want to sign as a separate service account?

    I'd rather not create a new instance of storage just for that, but I could....

    Or I could just pass in whatever would have been valid for storage, but specifically to this specific method -- which is super nice. If I know how to instantiate storage, I know how to sign a URL with the right credentials.


    If I had to vote, I'd say either we accept anything that storage accepts, or nothing at all (raising an Exception saying "yo, you can't sign URLs, cuz storage ain't got no credentials on it... set that up first... kthxbai.")

  11. callmehiphop commented on Aug 24, 2015

    @callmehiphop
    Contributor

    If this is an edge case I think we should just mandate that they create a separate storage instance with the alternative credentials.

  12. stephenplusplus commented on Aug 24, 2015

    @stephenplusplus
    ContributorAuthor

    I'm just thinking about what's easiest for me.
    I'd rather not create a new instance of storage just for that, but I could....

    I get you, and I think we can solve "easy" with intuition. For me, that would be, "Oh, this needs auth to work? I'll go back and give it a keyfile." I wouldn't expect each method to support credentials.

    raising an Exception saying "yo, you can't sign URLs, cuz storage ain't got no credentials on it... set that up first... kthxbai."

    I like this too, but it has to be on the docs level, only because it's an async process to determine if we have the credentials. We can technically see if the properties keyFilename or credentials were given, but we can't know if they're any good or not unless we go through google-auth-library, which means callbacks (async).

    The callback will be invoked with some auth error from google-auth-library that should inspire them to check out the docs. We can return a custom error as well, but I'm not sure which is better there (what if the original error was actually helpful to a user who did provide the right credentials, but something about them is off)

  13. jgeewax commented on Aug 24, 2015

    @jgeewax
    Contributor

    The callback couldn't contain an error saying "we couldn't find any credentials.. you gotta do that!" or "we had credentials, but we tried and they were no good..." ?

    I'm all for the callback coming with an err parameter.

  14. 54 remaining items

  15. added a commit that references this issue on Feb 25, 2026
  16. added a commit that references this issue on Feb 26, 2026
  17. added a commit that references this issue on Mar 5, 2026
  18. added a commit that references this issue on Mar 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

🚨This issue needs some love.api: storageIssues related to the Cloud Storage API.triage meI really want to be triaged.

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions