Edit on GitHub
Report issue
Page history

Authenticated browser downloads with audit logging

Author(s): @ianmaddox ,   Published: 2020-10-06

Ian Maddox | Solutions Architect | Google

Contributed by Google employees.

The code that accompanies this document provides an example means of serving images, documents, and other files stored in Cloud Storage while requiring the user to be authenticated with Google. This solution is useful because the Cloud Storage authenticated browser downloads feature does not currently work with internal logging.

This example uses Identity-Aware Proxy, App Engine standard environment, and Cloud Storage:

  1. A web user makes a request to your file server.
  2. If the user is not authenticated, they are redirected to a Google login page by Identity-Aware Proxy.
  3. After authentication, the user's request is forwarded to App Engine.
  4. App Engine validates the request and retrieves the file from Cloud Storage.
  5. If a watermark or other transformation is required, it is processed.
  6. The file is then returned to the web user.

Requests from users who aren't authenticated or who aren't authorized to access the files don't reach App Engine. Requests that don't match an object in Cloud Storage return a 404 File not found error. Requests with no filename or with a missing filename extension receive a 400 Bad request error.

Deploying the code

  1. Download the code in this repository.
  2. Modify app.yaml to identify the Cloud Storage bucket that holds the assets.
  3. Set up and configure the Cloud SDK, including the gcloud tool.
  4. Deploy the application:

    gcloud app deploy
  5. Enable Identity-Aware Proxy for the App Engine app that you created.

  6. Lock down the permissions of the App Engine service account.

Request format

When your service is deployed, it is available at a URL similar to the following:


Filenames and paths requested from this host map to object addresses in Cloud Storage. For example, a request to https://my-authenticated-fileserver.appspot.com/assets/heroimage.png maps to this object: gs://my-asset-bucket/assets/heroimage.png

A request for a missing file returns a 404 File not found error.

The application deduces the MIME type based on the filename extension. Therefore, requests without a filename extension return a 400 Bad Request error. Ensure that all of the files that you want to serve have an appropriate filename extension.

Opportunities for customization

This code provides a plain authenticated file server. Often, you might have requirements for transforming files before delivering them to the user. Here are a few ways that this code can be modified to fit more specific needs:

  • Image or document watermarking
  • Image resizing and other alterations
  • Data loss prevention (DLP) redaction to hide sensitive information from users not authorized to view those parts
  • Pub/Sub event triggers
  • Object request tallying and object deletion, for objects that can only be downloaded a specific number of times

Submit a tutorial

Share step-by-step guides

Submit a tutorial

Request a tutorial

Ask for community help

Submit a request

View tutorials

Search Google Cloud tutorials

View tutorials

Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 4.0 License, and code samples are licensed under the Apache 2.0 License. For details, see our Site Policies. Java is a registered trademark of Oracle and/or its affiliates.