Signed URLs

This page provides an overview of signed URLs, which you use to give time-limited resource access to anyone in possession of the URL, regardless of whether they have a Google account. To learn how to create a signed URL, see V4 Signing Process with Cloud Storage Tools and V4 Signing Process with Your Own Program. To learn about other ways of controlling access to buckets and objects, see Overview of Access Control.

Overview

A signed URL is a URL that provides limited permission and time to make a request. Signed URLs contain authentication information in their query string, allowing users without credentials to perform specific actions on a resource. When you generate a signed URL, you specify a user or service account which must have sufficient permission to make the request that the signed URL will make. After you generate a signed URL, anyone who possesses it can use the signed URL to perform specified actions, such as reading an object, within a specified period of time.

When should you use a signed URL?

In some scenarios, you might not want to require your users to have a Google account in order to access Cloud Storage, but you still want to control access using your application-specific logic. The typical way to address this use case is to provide a signed URL to a user, which gives the user read, write, or delete access to that resource for a limited time. Anyone who knows the URL can access the resource until the URL expires. You specify the expiration time when you create the signed URL.

Options for generating a signed URL

Cloud Storage supports several methods for generating a signed URL:

  • V4 signing with service account authenticationBETA: This signing mechanism is described below.

  • V2 signing with service account authentication: For more information about this signing mechanism, go here.

  • Signing with HMAC authentication: If you're an Amazon Simple Storage Service (Amazon S3) user, you can use your existing workflows to generate signed URLs for Cloud Storage. Simply specify Cloud Storage resources, point to the host storage.googleapis.com, and use Google HMAC credentials in the process of generating the signed URL.

Signed URL example

The following is an example of signed URL that was created following the V4 signing process with service account authentication:

https://storage.googleapis.com/example-bucket/cat.jpeg?X-Goog-Algorithm=
GOOG4-RSA-SHA256&X-Goog-Credential=example%40example-project.iam.gserviceaccount
.com%2F20181026%2Fus-central-1%2Fstorage%2Fgoog4_request&X-Goog-Date=20181026T18
1309Z&X-Goog-Expires=900&X-Goog-SignedHeaders=host&X-Goog-Signature=247a2aa45f16
9edf4d187d54e7cc46e4731b1e6273242c4f4c39a1d2507a0e58706e25e3a85a7dbb891d62afa849
6def8e260c1db863d9ace85ff0a184b894b117fe46d1225c82f2aa19efd52cf21d3e2022b3b868dc
c1aca2741951ed5bf3bb25a34f5e9316a2841e8ff4c530b22ceaa1c5ce09c7cbb5732631510c2058
0e61723f5594de3aea497f195456a2ff2bdd0d13bad47289d8611b6f9cfeef0c46c91a455b94e90a
66924f722292d21e24d31dcfb38ce0c0f353ffa5a9756fc2a9f2b40bc2113206a81e324fc4fd6823
a29163fa845c8ae7eca1fcf6e5bb48b3200983c56c5ca81fffb151cca7402beddfc4a76b13344703
2ea7abedc098d2eb14a7

This signed URL provided access to read the object cat.jpeg in the bucket example-bucket. The query parameters that make this a signed URL are:

  • X-Goog-Algorithm: The algorithm used to sign the URL.

  • X-Goog-Credential: Information about the credentials used to create the signed URL.

  • X-Goog-Date: The date and time the signed URL became usable, in the ISO 8601 basic format YYYYMMDD'T'HHMMSS'Z'.

  • X-Goog-Expires: The length of time the signed URL remained valid, measured in seconds from the value in X-Goog-Date.

  • X-Goog-SignedHeaders: Headers that had to be included as part of any request that used the signed URL.

  • X-Goog-Signature: The authentication string that allowed requests using this signed URL to access cat.jpeg.

Using signed URLs with resumable uploads

When using signed URLs with resumable uploads to upload objects to your bucket, you only need to use the signed URL in the initial POST request. No data is uploaded in the POST request; instead, the request returns a session URI which is used in subsequent PUT requests to upload data. Since the session URI is, in effect, an authentication token, the PUT requests do not need to use the original signed URL. This behavior allows the POST request to be made by the server, avoiding the need for clients to have to deal with signed URLs themselves.

Resumable uploads are pinned in the region they start in. For example, if you create a resumable upload URL in the US and give it to a client in Asia, the upload still goes through the US. Performing a resumable upload in a region where it wasn't initiated can cause slow uploads. To avoid this, have the initial POST request constructed and signed by the server, but then give the signed URL to the client so that the upload is initiated from their location. Once initiated, the client can use the resulting session URI normally to make PUT requests that do not need to be signed.

Signed URL considerations

When working with signed URLs, keep in mind the following:

  • Signed URLs can generally be made for any XML API request; however, the Node.js Cloud Storage Client Libraries currently can only make signed URLs for individual objects. For example, it cannot be used to make signed URLs for listing objects in a bucket.

  • The Python and Go Cloud Storage Client Libraries do not currently support V4 signed URLs.

  • Query String Parameters like response-content-disposition and response-content-type are not verified by the signature. To force a Content-Disposition or Content-Type in the response, set those parameters in the object metadata.

  • When specifying credentials, it is recommended that you identify your service account by using its email address; however, use of the service account ID is also supported.

Canonical requests

The canonical request defines the request that users must make when they use your signed URL. It includes information such as the HTTP verb, query string parameters, and headers that must be used in a request that uses your signed URL, as well as the object, bucket, or other resource that the signed URL grants access to.

HTTP verbs

Signed URLs can be used with the following HTTP verbs:

Resource path

Included in the canonical request is the path to the resource that the signed URL will apply to. The path to the resource is everything that follows the host name but precedes any query string.

For example, if the Cloud Storage URL is https://storage.googleapis.com/example-bucket/cat-pics/tabby.jpeg?userProject=my-project, then the path to the resource is /example-bucket/cat-pics/tabby.jpeg.

If you use an alternative Cloud Storage URL such as https://example-bucket.storage.googleapis.com/cat-pics/tabby.jpeg?userProject=my-project then the path to the resource is /cat-pics/tabby.jpeg.

For additional URL endpoints that can be used with signed URLs, see XML API request endpoints.

When defining the resource path, you must percent encode the following reserved characters: ?=!#$&'()*+,:;@[]." Any other percent encoding used in the URL should also be included in the resource path.

Query string

Included in the canonical request are the query string parameters that must be part of any request that uses the signed URL. The query string is everything that follows the question mark (?) at the end of the resource path.

For example, if the Cloud Storage URL is https://storage.googleapis.com/example-bucket/cat-pics/tabby.jpeg?userProject=my-project, then the query string is userProject=my-project.

In the canonical request, the query string must sort all parameters by name using a lexicographical sort by code point value, and all parameters should be separated with &.

Required query string parameters

Many query string parameters, such as alt are added as needed, but the following query string parameters are required in every signed URL:

  • X-Goog-Algorithm: The algorithm you used to sign the URL. Valid values are GOOG4-RSA-SHA256 and GOOG4-HMAC-SHA256.
  • X-Goog-Credential: The credentials used to sign the URL. Credentials consist of an authorizer and a credential scope given in the format: [AUTHORIZER]%2F[CREDENTIAL_SCOPE]. The authorizer can be a service account name or an HMAC access key.
  • X-Goog-Date: The current date and time, in the ISO 8601 basic format YYYYMMDD'T'HHMMSS'Z'.
  • X-Goog-Expires: The lifetime of the signed URL, measured in seconds from X-Goog-Date.
  • X-Goog-SignedHeaders: A semicolon-separated list of names of headers that must be included in any request using the signed URL. host must be one of these headers.
  • X-Goog-Signature: The signature authenticating the request.

Headers

Included in the canonical request are the headers that must be part of any request that uses the signed URL, including custom headers and extension headers that begin with x-goog. You specify the headers in several parts of the canonical request:

  1. Specify the header names in the X-Goog-SignedHeaders query string parameter, with each name separated by ;.
  2. Specify header name:value after the query string portion of the canonical request, with each pair separated by a newline (\n).
  3. Specify the header names in a newline following the list of header name:value pairs, with each name separated by ;.

When specifying the name:value pairs for headers, keep in mind the following:

  • Make all header names lowercase.
  • Sort all headers by header name using a lexicographical sort by code point value.
  • Eliminate duplicate header names by creating one header name with a comma-separated list of values. Be sure there is no whitespace between the values, and be sure that the order of the comma-separated list matches the order that the headers appear in your request. For more information, see RFC 7230 section 3.2.
  • Replace any folding whitespace or newlines (CRLF or LF) with a single space. For more information about folding whitespace, see RFC 7230, section 3.2.4..
  • Remove any whitespace around the colon that appears after the header name.

    For example, using the custom header x-goog-acl: private without removing the space after the colon returns a 403 Forbidden error, because the request signature you calculate does not match the signature Google calculates.

For example, if you have the following set of headers:

host: storage.googleapis.com
content-type: text/plain
x-goog-meta-reviewer: jane
x-goog-meta-reviewer: john

The construction in the canonical request would be:

content-type:text/plain
host:storage.googleapis.com
x-goog-meta-reviewer:jane,john

Required headers

Most headers, such as content-type and extension headers are added as needed, but the following header is required in every signed URL:

  • host: The URI used to access Cloud Storage.

Additionally, the following headers cannot be used in requests that use a signed URL unless they are explicitly specified in the canonical request.

  • x-goog-project-id
  • x-goog-copy-source
  • x-goog-metadata-directive
  • x-amz-copy-source
  • x-amz-metadata-directive

Credential scope

The credential scope appears in both the string-to-sign and the X-Goog-Credential query string parameter. It has the following structure:

[DATE]/[LOCATION]/storage/goog4_request
  • [DATE]: Date formatted as YYYYMMDD, which must match the day used in the string-to-sign.
  • [LOCATION]: The region where the resource resides or will be created. For Cloud Storage resources, the value of [LOCATION] is arbitrary: the [LOCATION] parameter exists to maintain compatibility with Amazon Simple Storage Service (Amazon S3).
  • storage: The service name.
  • goog4_request: The type of signed URL.

Example: 20181102/us/storage/goog4_request

Signing strings with Google Cloud Platform tools

When generating a signed URL using a program, one option for signing the string is to use tools provided by GCP.

App Engine App Identity service

Signing within a App Engine application uses the App Engine Identity service, which utilizes App Engine service account credentials. For example, using the Python App Identity API, you can:

  • Use google.appengine.api.app_identity.sign_blob() to sign the bytes from your constructed string, providing the Signature you need when assembling the signed URL.

  • Use google.appengine.api.app_identity.get_service_account_name() to retrieve a service account name, which is the GoogleAccessId you need when assembling the signed URL.

App Engine also provides support in other languages:

The App Identity service rotates the private keys when it signs blobs. Signed URLs generated from the App Identity service are good for at least one hour, and are best used for short-lived access to resources.

IAM signBlob

Signing can be accomplished using the IAM signBlob method.

Was this page helpful? Let us know how we did:

Send feedback about...

Cloud Storage
Need help? Visit our support page.