title: Google Cloud Storage with a service account in Java - 403 Caller does not have storage.objects.list access to bucket
body: <p>We want to download files from Google Storage in our application server. It is important to have read-only restricted access to a single bucket and nothing else.</p>
  
  <p>At first I used a regular user account (not a service account) which have permissions to access all buckets in our Google Cloud project, and everything worked fine - my Java code opened buckets and downloaded files without problems.</p>
  
  <pre><code>Storage storage = StorageOptions.getDefaultInstance().getService();
  Bucket b = storage.get( "mybucketname" );
  </code></pre>
  
  <p>Then I wanted to switch to use a specially created service account which has access to a single bucket only. So I created a service account, gave permissions to read a single bucket, and downloaded its key file. The permissions in Google Cloud Console are named as:</p>
  
  <blockquote>
    <p>Storage Object Viewer (3 members) Read access to GCS objects.</p>
  </blockquote>
  
  <p>gsutil command line utility works fine with this account - from the command line it allows accessing this bucket but not the others. </p>
  
  <p>The initialization from the command line is done using the following command:</p>
  
  <pre><code>gcloud --project myprojectname auth activate-service-account files-viewer2@myprojectname.iam.gserviceaccount.com --key-file=/.../keyfilename.json
  </code></pre>
  
  <p>I even tried two different service accounts which have access to different buckets, and from the command line I can switch between them and gsutil gives access to a relevant bucket only, and for any other it returns the error: </p>
  
  <blockquote>
    <p>"AccessDeniedException: 403 Caller does not have storage.objects.list access to bucket xxxxxxxxxx."</p>
  </blockquote>
  
  <p>So, from the command line everything worked fine.
  But in Java there is some problem with the authentication.</p>
  
  <p>The default authentication I previously used with a regular user account stopped working - it reports the error:</p>
  
  <blockquote>
    <p>com.google.cloud.storage.StorageException: Anonymous users does not have storage.buckets.get access to bucket xxxxxxxxxx.</p>
  </blockquote>
  
  <p>Then I've tried the following code (this is the simplest variant because it relies on the key json file, but I've already tried a number of other variants found in various forums, with no success):</p>
  
  <pre><code>FileInputStream fis = new FileInputStream( "/path/to/the/key-file.json" );
  ServiceAccountCredentials credentials = ServiceAccountCredentials.fromStream( fis );
  Storage storage = StorageOptions.newBuilder().setCredentials( credentials )
      .setProjectId( "myprojectid" ).build().getService();
  Bucket b = storage.get( "mybucketname" );
  </code></pre>
  
  <p>And all I receive is this error:</p>
  
  <blockquote>
    <p>com.google.cloud.storage.StorageException: Caller does not have storage.buckets.get access to bucket mybucketname.
    Caused by: com.google.api.client.googleapis.json.GoogleJsonResponseException: 403 Forbidden</p>
  </blockquote>
  
  <p>The same error is returned no matter to what buckets I'm trying to access (even non-existing).
  What confuses me is that the same service account, initialized with the same JSON key file, works fine from the command line.
  So I think something is missing in Java code that ensures correct authentication.</p>