title: Update google cloud storage object meta with .net api failed with forbidden error
body: <p>I'm trying to update the meta data of a existing google cloud storage object, with .net client. However, I always got a Fobidden error. The error message is:</p>
  
  <pre><code>Google.Apis.Requests.RequestError
  Forbidden [403]
  Errors [
      Message[Forbidden] Location[ - ] Reason[forbidden] Domain[global]
  ]
  </code></pre>
  
  <p>The code I'm using is:</p>
  
  <pre><code>    private void UpdateMeta(string key)
      {
          var service = Connect();
          var req = service.Objects.Get(bucketName, key);
          GCSObject readobj = req.Execute();
          readobj.Bucket = bucketName;
          if (readobj.Metadata == null)
          {
              readobj.Metadata = new Dictionary&lt;string, string&gt;();
          }
          readobj.Metadata["x-goog-meta-test"] = DateTime.Now.ToString();
          service.Objects.Patch(readobj, readobj.Bucket, key).Execute();
      }
  </code></pre>
  
  <p>Is there anything wrong with my code?</p>
  
  <p>The connect method is:</p>
  
  <pre><code>    private StorageService Connect()
      {
          string serviceAccountEmail = "account_id@developer.gserviceaccount.com";
          var certificate = GetGCSCertificate(); // retrive the x509 certificate file
          ServiceAccountCredential credential = new ServiceAccountCredential(
             new ServiceAccountCredential.Initializer(serviceAccountEmail)
             {
                 Scopes = new[] { StorageService.Scope.DevstorageReadWrite }
             }.FromCertificate(certificate));
          var service = new StorageService(new BaseClientService.Initializer()
          {
              HttpClientInitializer = credential,
              ApplicationName = "GCS Sample",
          });
          return service;
      }
  </code></pre>
  
  <p>Here is the http request sent by gsutil command. It updated the metadata successfully.</p>
  
  <pre><code>PATCH https://www.googleapis.com/storage/v1/b/BUCKETNAME/o/OBJECTNAME?ifMetagenerationMatch=1&amp;ifGenerationMatch=1429863183870000&amp;projection=full&amp;prettyPrint=True&amp;alt=json HTTP/1.1
  Host: www.googleapis.com
  Content-length: 128
  Accept-encoding: gzip, deflate
  Accept: application/json
  User-agent: apitools gsutil/4.11 (win32)
  Content-type: application/json
  Authorization: Bearer xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  
  {"generation": "1429863183870000", "metageneration": "1", "metadata": {"test": "2015- sdf2", "key2": "4/24/2015 8:12:58 AM"}}
  </code></pre>
  
  <p>And here is the http request sent by c# client. It failed.</p>
  
  <pre><code>PATCH https://www.googleapis.com/storage/v1/b/BUCKETNAME/o/OBJECTNAME?ifMetagenerationMatch=2&amp;ifGenerationMatch=1429863183870000&amp;projection=full&amp;prettyPrint=True HTTP/1.1
  User-Agent: GCS Sample google-api-dotnet-client/1.9.0.26010 (gzip)
  Authorization: Bearer xxxxxxxxxxxxxxxxxxxxxxxxxxxx
  Content-Type: application/json; charset=utf-8
  Host: www.googleapis.com
  Content-Length: 116
  Accept-Encoding: gzip
  
  {"generation":1429863183870000,"metadata":{"key2":"4/24/2015 8:23:52 AM","test":"2015- sdf2"},"metageneration":2}
  </code></pre>
  
  <p>I don't see much difference between these two http requests.</p>
  
  <hr>
  
  <p>I figured out the root cause of the forbidden error. It's because I used a wrong scope setting. In Connect method, instead of</p>
  
  <pre><code>           Scopes = new[] { StorageService.Scope.DevstorageReadWrite }
  </code></pre>
  
  <p>we should use</p>
  
  <pre><code>           Scopes = new[] { StorageService.Scope.DevstorageFullControl }
  </code></pre>