{"action":"created","comment":{"url":"https://api.github.com/repos/google/google-api-dotnet-client/pulls/comments/36231133","id":36231133,"diff_hunk":"@@ -0,0 +1,307 @@\n+﻿/*\n+Copyright 2015 Google Inc\n+\n+Licensed under the Apache License, Version 2.0 (the \"License\");\n+you may not use this file except in compliance with the License.\n+You may obtain a copy of the License at\n+\n+    http://www.apache.org/licenses/LICENSE-2.0\n+\n+Unless required by applicable law or agreed to in writing, software\n+distributed under the License is distributed on an \"AS IS\" BASIS,\n+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n+See the License for the specific language governing permissions and\n+limitations under the License.\n+*/\n+\n+using System;\n+using System.Collections.Generic;\n+using System.IO;\n+using System.Linq;\n+using System.Net.Http;\n+using System.Threading;\n+using System.Threading.Tasks;\n+\n+using Google.Apis.Auth.OAuth2.Responses;\n+using Google.Apis.Http;\n+\n+namespace Google.Apis.Auth.OAuth2\n+{\n+    /// <summary>\n+    /// Credential for authorizing calls using OAuth 2.0.\n+    /// It is a convenience wrapper that allows handling of different types of \n+    /// credentials (like <see cref=\"ServiceAccountCredential\"/>, <see cref=\"ComputeCredential\"/>\n+    /// or <see cref=\"UserCredential\"/>) in a unified way.\n+    /// <para>\n+    /// See <see cref=\"GetApplicationDefaultCredential\"/>.\n+    /// </para>\n+    /// </summary>\n+    public abstract class GoogleCredential : IConfigurableHttpClientInitializer, ITokenAccess\n+    {\n+        private static DefaultCredentialProvider defaultCredentialProvider = new DefaultCredentialProvider();\n+\n+        /// <summary>\n+        /// <para>Returns the Application Default Credentials which are ambient credentials that identify and authorize \n+        /// the whole application.</para>\n+        /// <para>The ambient credentials are determined as following order:</para>\n+        /// <list type=\"number\">\n+        /// <item> \n+        /// <description>The environment variable GOOGLE_APPLICATION_CREDENTIALS is checked. If this variable is specified, it \n+        /// should point to a file that defines the credentials. The simplest way to get a credential for this purpose is to \n+        /// create a service account using the <a href=\"https://console.developers.google.com\">Google Developers Console</a> in \n+        /// the section APIs &amp; Auth, in the sub-section Credentials. Create a service account or choose an existing one and \n+        /// select Generate new JSON key. Set the environment variable to the path of the JSON file downloaded.</description> \n+        /// </item> \n+        /// <item> \n+        /// <description>If you have installed the Google Cloud SDK on your machine and have run the command \n+        /// <a href=\"https://cloud.google.com/sdk/gcloud/reference/auth/login\">gcloud auth login</a>, your identity can be used as \n+        /// a proxy to test code calling APIs from that machine.</description> \n+        /// </item> \n+        /// <item> \n+        /// <description>If you are running in Google Compute Engine production, the built-in service account associated with the \n+        /// virtual machine instance will be used.</description> \n+        /// </item> \n+        /// </list>\n+        /// </summary>\n+        public static Task<GoogleCredential> GetApplicationDefaultAsync()\n+        {\n+            return defaultCredentialProvider.GetDefaultCredentialAsync();\n+        }\n+\n+        /// <summary>\n+        /// Load credential from stream containing JSON credential data.\n+        /// <para>\n+        /// The stream can contain a Service Account key file in JSON format from the Google Developers\n+        /// Console or a stored user credential using the format supported by the Cloud SDK.\n+        /// </para>\n+        /// </summary>\n+        public static GoogleCredential FromStream(Stream stream)\n+        {\n+            return defaultCredentialProvider.CreateDefaultCredentialFromStream(stream);\n+        }\n+\n+        /// <summary>\n+        /// <para>Returns true only if this credential type has no scopes by default and requires ","path":"Src/GoogleApis.Auth.DotNet4/OAuth2/GoogleCredential.cs","position":84,"original_position":84,"commit_id":"93b6bffa49be799ad7b6bb67f1723615f2fa240c","original_commit_id":"93b6bffa49be799ad7b6bb67f1723615f2fa240c","user":{"login":"jtattermusch","id":9939684,"avatar_url":"https://avatars.githubusercontent.com/u/9939684?v=3","gravatar_id":"","url":"https://api.github.com/users/jtattermusch","html_url":"https://github.com/jtattermusch","followers_url":"https://api.github.com/users/jtattermusch/followers","following_url":"https://api.github.com/users/jtattermusch/following{/other_user}","gists_url":"https://api.github.com/users/jtattermusch/gists{/gist_id}","starred_url":"https://api.github.com/users/jtattermusch/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jtattermusch/subscriptions","organizations_url":"https://api.github.com/users/jtattermusch/orgs","repos_url":"https://api.github.com/users/jtattermusch/repos","events_url":"https://api.github.com/users/jtattermusch/events{/privacy}","received_events_url":"https://api.github.com/users/jtattermusch/received_events","type":"User","site_admin":false},"body":"Done","created_at":"2015-08-04T19:31:02Z","updated_at":"2015-08-04T19:31:02Z","html_url":"https://github.com/google/google-api-dotnet-client/pull/564#discussion_r36231133","pull_request_url":"https://api.github.com/repos/google/google-api-dotnet-client/pulls/564","_links":{"self":{"href":"https://api.github.com/repos/google/google-api-dotnet-client/pulls/comments/36231133"},"html":{"href":"https://github.com/google/google-api-dotnet-client/pull/564#discussion_r36231133"},"pull_request":{"href":"https://api.github.com/repos/google/google-api-dotnet-client/pulls/564"}}},"pull_request":{"url":"https://api.github.com/repos/google/google-api-dotnet-client/pulls/564","id":40382354,"html_url":"https://github.com/google/google-api-dotnet-client/pull/564","diff_url":"https://github.com/google/google-api-dotnet-client/pull/564.diff","patch_url":"https://github.com/google/google-api-dotnet-client/pull/564.patch","issue_url":"https://api.github.com/repos/google/google-api-dotnet-client/issues/564","number":564,"state":"open","locked":false,"title":"Application Default Credentials after API polishing","user":{"login":"jtattermusch","id":9939684,"avatar_url":"https://avatars.githubusercontent.com/u/9939684?v=3","gravatar_id":"","url":"https://api.github.com/users/jtattermusch","html_url":"https://github.com/jtattermusch","followers_url":"https://api.github.com/users/jtattermusch/followers","following_url":"https://api.github.com/users/jtattermusch/following{/other_user}","gists_url":"https://api.github.com/users/jtattermusch/gists{/gist_id}","starred_url":"https://api.github.com/users/jtattermusch/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jtattermusch/subscriptions","organizations_url":"https://api.github.com/users/jtattermusch/orgs","repos_url":"https://api.github.com/users/jtattermusch/repos","events_url":"https://api.github.com/users/jtattermusch/events{/privacy}","received_events_url":"https://api.github.com/users/jtattermusch/received_events","type":"User","site_admin":false},"body":"This PR contains code from #553, with the latest changes from upstream/master merged.\r\nI originally created this branch just to facilitate cleaning up the git history and to fix some of the style nits in the code.\r\n\r\nNevertheless, once I started editing the code, I realized there were some major issues with the API in the original pull request (perhaps introduced while addressing review comments)  - for example the object returned from GoogleAuth.GetApplicationDefaultCredentials() didn't expose the IsCreateScopedRequired property and accessing that property required guessing that the default credential is a service account credential in fact, explicitly typecasting it and only after that, you were able to access the IsCreateScopedRequired property - which makes no sense at all. I found other problems as well (those that are hard to catch in review until you actually start modifying the code).\r\n\r\nSo, because there were some concerns about the API in the past, i decided to take the app default credentials code (I haven't changed most of the code that implements the actual logic) and adjust the API layout.\r\n\r\nThe new API introduces a new type GoogleCredential (returned by GetApplicationDefaultCredentials()), which acts as a very thin wrapper for other credential types. That way, the API of the existing credential types could stay intact and GoogleCredential can still provide all the functionality needed. Arguably, the new design is cleaner and possibly allows more tweaking in the future if necessary.\r\n\r\nThe code is still not 100% finished, but I believe it is in good shape for an initial review (of the API and high level changes I've made).\r\n\r\n@vsubramani  @peleyal  for review","created_at":"2015-07-20T18:31:32Z","updated_at":"2015-08-04T19:31:02Z","closed_at":null,"merged_at":null,"merge_commit_sha":"8712822053aeda448a9c4f635ec40a15b8873348","assignee":{"login":"peleyal","id":3082873,"avatar_url":"https://avatars.githubusercontent.com/u/3082873?v=3","gravatar_id":"","url":"https://api.github.com/users/peleyal","html_url":"https://github.com/peleyal","followers_url":"https://api.github.com/users/peleyal/followers","following_url":"https://api.github.com/users/peleyal/following{/other_user}","gists_url":"https://api.github.com/users/peleyal/gists{/gist_id}","starred_url":"https://api.github.com/users/peleyal/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/peleyal/subscriptions","organizations_url":"https://api.github.com/users/peleyal/orgs","repos_url":"https://api.github.com/users/peleyal/repos","events_url":"https://api.github.com/users/peleyal/events{/privacy}","received_events_url":"https://api.github.com/users/peleyal/received_events","type":"User","site_admin":false},"milestone":null,"commits_url":"https://api.github.com/repos/google/google-api-dotnet-client/pulls/564/commits","review_comments_url":"https://api.github.com/repos/google/google-api-dotnet-client/pulls/564/comments","review_comment_url":"https://api.github.com/repos/google/google-api-dotnet-client/pulls/comments{/number}","comments_url":"https://api.github.com/repos/google/google-api-dotnet-client/issues/564/comments","statuses_url":"https://api.github.com/repos/google/google-api-dotnet-client/statuses/93b6bffa49be799ad7b6bb67f1723615f2fa240c","head":{"label":"jtattermusch:AppDefaultProgress","ref":"AppDefaultProgress","sha":"93b6bffa49be799ad7b6bb67f1723615f2fa240c","user":{"login":"jtattermusch","id":9939684,"avatar_url":"https://avatars.githubusercontent.com/u/9939684?v=3","gravatar_id":"","url":"https://api.github.com/users/jtattermusch","html_url":"https://github.com/jtattermusch","followers_url":"https://api.github.com/users/jtattermusch/followers","following_url":"https://api.github.com/users/jtattermusch/following{/other_user}","gists_url":"https://api.github.com/users/jtattermusch/gists{/gist_id}","starred_url":"https://api.github.com/users/jtattermusch/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jtattermusch/subscriptions","organizations_url":"https://api.github.com/users/jtattermusch/orgs","repos_url":"https://api.github.com/users/jtattermusch/repos","events_url":"https://api.github.com/users/jtattermusch/events{/privacy}","received_events_url":"https://api.github.com/users/jtattermusch/received_events","type":"User","site_admin":false},"repo":{"id":38863126,"name":"google-api-dotnet-client","full_name":"jtattermusch/google-api-dotnet-client","owner":{"login":"jtattermusch","id":9939684,"avatar_url":"https://avatars.githubusercontent.com/u/9939684?v=3","gravatar_id":"","url":"https://api.github.com/users/jtattermusch","html_url":"https://github.com/jtattermusch","followers_url":"https://api.github.com/users/jtattermusch/followers","following_url":"https://api.github.com/users/jtattermusch/following{/other_user}","gists_url":"https://api.github.com/users/jtattermusch/gists{/gist_id}","starred_url":"https://api.github.com/users/jtattermusch/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jtattermusch/subscriptions","organizations_url":"https://api.github.com/users/jtattermusch/orgs","repos_url":"https://api.github.com/users/jtattermusch/repos","events_url":"https://api.github.com/users/jtattermusch/events{/privacy}","received_events_url":"https://api.github.com/users/jtattermusch/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/jtattermusch/google-api-dotnet-client","description":"Google APIs Client Library for .NET","fork":true,"url":"https://api.github.com/repos/jtattermusch/google-api-dotnet-client","forks_url":"https://api.github.com/repos/jtattermusch/google-api-dotnet-client/forks","keys_url":"https://api.github.com/repos/jtattermusch/google-api-dotnet-client/keys{/key_id}","collaborators_url":"https://api.github.com/repos/jtattermusch/google-api-dotnet-client/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/jtattermusch/google-api-dotnet-client/teams","hooks_url":"https://api.github.com/repos/jtattermusch/google-api-dotnet-client/hooks","issue_events_url":"https://api.github.com/repos/jtattermusch/google-api-dotnet-client/issues/events{/number}","events_url":"https://api.github.com/repos/jtattermusch/google-api-dotnet-client/events","assignees_url":"https://api.github.com/repos/jtattermusch/google-api-dotnet-client/assignees{/user}","branches_url":"https://api.github.com/repos/jtattermusch/google-api-dotnet-client/branches{/branch}","tags_url":"https://api.github.com/repos/jtattermusch/google-api-dotnet-client/tags","blobs_url":"https://api.github.com/repos/jtattermusch/google-api-dotnet-client/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/jtattermusch/google-api-dotnet-client/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/jtattermusch/google-api-dotnet-client/git/refs{/sha}","trees_url":"https://api.github.com/repos/jtattermusch/google-api-dotnet-client/git/trees{/sha}","statuses_url":"https://api.github.com/repos/jtattermusch/google-api-dotnet-client/statuses/{sha}","languages_url":"https://api.github.com/repos/jtattermusch/google-api-dotnet-client/languages","stargazers_url":"https://api.github.com/repos/jtattermusch/google-api-dotnet-client/stargazers","contributors_url":"https://api.github.com/repos/jtattermusch/google-api-dotnet-client/contributors","subscribers_url":"https://api.github.com/repos/jtattermusch/google-api-dotnet-client/subscribers","subscription_url":"https://api.github.com/repos/jtattermusch/google-api-dotnet-client/subscription","commits_url":"https://api.github.com/repos/jtattermusch/google-api-dotnet-client/commits{/sha}","git_commits_url":"https://api.github.com/repos/jtattermusch/google-api-dotnet-client/git/commits{/sha}","comments_url":"https://api.github.com/repos/jtattermusch/google-api-dotnet-client/comments{/number}","issue_comment_url":"https://api.github.com/repos/jtattermusch/google-api-dotnet-client/issues/comments{/number}","contents_url":"https://api.github.com/repos/jtattermusch/google-api-dotnet-client/contents/{+path}","compare_url":"https://api.github.com/repos/jtattermusch/google-api-dotnet-client/compare/{base}...{head}","merges_url":"https://api.github.com/repos/jtattermusch/google-api-dotnet-client/merges","archive_url":"https://api.github.com/repos/jtattermusch/google-api-dotnet-client/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/jtattermusch/google-api-dotnet-client/downloads","issues_url":"https://api.github.com/repos/jtattermusch/google-api-dotnet-client/issues{/number}","pulls_url":"https://api.github.com/repos/jtattermusch/google-api-dotnet-client/pulls{/number}","milestones_url":"https://api.github.com/repos/jtattermusch/google-api-dotnet-client/milestones{/number}","notifications_url":"https://api.github.com/repos/jtattermusch/google-api-dotnet-client/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/jtattermusch/google-api-dotnet-client/labels{/name}","releases_url":"https://api.github.com/repos/jtattermusch/google-api-dotnet-client/releases{/id}","created_at":"2015-07-10T05:41:46Z","updated_at":"2015-07-10T05:41:47Z","pushed_at":"2015-08-03T23:13:14Z","git_url":"git://github.com/jtattermusch/google-api-dotnet-client.git","ssh_url":"git@github.com:jtattermusch/google-api-dotnet-client.git","clone_url":"https://github.com/jtattermusch/google-api-dotnet-client.git","svn_url":"https://github.com/jtattermusch/google-api-dotnet-client","homepage":"https://developers.google.com/api-client-library/dotnet","size":8850,"stargazers_count":0,"watchers_count":0,"language":"C#","has_issues":false,"has_downloads":false,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"google:master","ref":"master","sha":"591ea827922ef4f5a2b32f5aad18a823bbfc0286","user":{"login":"google","id":1342004,"avatar_url":"https://avatars.githubusercontent.com/u/1342004?v=3","gravatar_id":"","url":"https://api.github.com/users/google","html_url":"https://github.com/google","followers_url":"https://api.github.com/users/google/followers","following_url":"https://api.github.com/users/google/following{/other_user}","gists_url":"https://api.github.com/users/google/gists{/gist_id}","starred_url":"https://api.github.com/users/google/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/google/subscriptions","organizations_url":"https://api.github.com/users/google/orgs","repos_url":"https://api.github.com/users/google/repos","events_url":"https://api.github.com/users/google/events{/privacy}","received_events_url":"https://api.github.com/users/google/received_events","type":"Organization","site_admin":false},"repo":{"id":33947900,"name":"google-api-dotnet-client","full_name":"google/google-api-dotnet-client","owner":{"login":"google","id":1342004,"avatar_url":"https://avatars.githubusercontent.com/u/1342004?v=3","gravatar_id":"","url":"https://api.github.com/users/google","html_url":"https://github.com/google","followers_url":"https://api.github.com/users/google/followers","following_url":"https://api.github.com/users/google/following{/other_user}","gists_url":"https://api.github.com/users/google/gists{/gist_id}","starred_url":"https://api.github.com/users/google/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/google/subscriptions","organizations_url":"https://api.github.com/users/google/orgs","repos_url":"https://api.github.com/users/google/repos","events_url":"https://api.github.com/users/google/events{/privacy}","received_events_url":"https://api.github.com/users/google/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/google/google-api-dotnet-client","description":"Google APIs Client Library for .NET","fork":false,"url":"https://api.github.com/repos/google/google-api-dotnet-client","forks_url":"https://api.github.com/repos/google/google-api-dotnet-client/forks","keys_url":"https://api.github.com/repos/google/google-api-dotnet-client/keys{/key_id}","collaborators_url":"https://api.github.com/repos/google/google-api-dotnet-client/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/google/google-api-dotnet-client/teams","hooks_url":"https://api.github.com/repos/google/google-api-dotnet-client/hooks","issue_events_url":"https://api.github.com/repos/google/google-api-dotnet-client/issues/events{/number}","events_url":"https://api.github.com/repos/google/google-api-dotnet-client/events","assignees_url":"https://api.github.com/repos/google/google-api-dotnet-client/assignees{/user}","branches_url":"https://api.github.com/repos/google/google-api-dotnet-client/branches{/branch}","tags_url":"https://api.github.com/repos/google/google-api-dotnet-client/tags","blobs_url":"https://api.github.com/repos/google/google-api-dotnet-client/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/google/google-api-dotnet-client/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/google/google-api-dotnet-client/git/refs{/sha}","trees_url":"https://api.github.com/repos/google/google-api-dotnet-client/git/trees{/sha}","statuses_url":"https://api.github.com/repos/google/google-api-dotnet-client/statuses/{sha}","languages_url":"https://api.github.com/repos/google/google-api-dotnet-client/languages","stargazers_url":"https://api.github.com/repos/google/google-api-dotnet-client/stargazers","contributors_url":"https://api.github.com/repos/google/google-api-dotnet-client/contributors","subscribers_url":"https://api.github.com/repos/google/google-api-dotnet-client/subscribers","subscription_url":"https://api.github.com/repos/google/google-api-dotnet-client/subscription","commits_url":"https://api.github.com/repos/google/google-api-dotnet-client/commits{/sha}","git_commits_url":"https://api.github.com/repos/google/google-api-dotnet-client/git/commits{/sha}","comments_url":"https://api.github.com/repos/google/google-api-dotnet-client/comments{/number}","issue_comment_url":"https://api.github.com/repos/google/google-api-dotnet-client/issues/comments{/number}","contents_url":"https://api.github.com/repos/google/google-api-dotnet-client/contents/{+path}","compare_url":"https://api.github.com/repos/google/google-api-dotnet-client/compare/{base}...{head}","merges_url":"https://api.github.com/repos/google/google-api-dotnet-client/merges","archive_url":"https://api.github.com/repos/google/google-api-dotnet-client/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/google/google-api-dotnet-client/downloads","issues_url":"https://api.github.com/repos/google/google-api-dotnet-client/issues{/number}","pulls_url":"https://api.github.com/repos/google/google-api-dotnet-client/pulls{/number}","milestones_url":"https://api.github.com/repos/google/google-api-dotnet-client/milestones{/number}","notifications_url":"https://api.github.com/repos/google/google-api-dotnet-client/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/google/google-api-dotnet-client/labels{/name}","releases_url":"https://api.github.com/repos/google/google-api-dotnet-client/releases{/id}","created_at":"2015-04-14T17:56:22Z","updated_at":"2015-08-03T01:27:22Z","pushed_at":"2015-08-03T23:13:15Z","git_url":"git://github.com/google/google-api-dotnet-client.git","ssh_url":"git@github.com:google/google-api-dotnet-client.git","clone_url":"https://github.com/google/google-api-dotnet-client.git","svn_url":"https://github.com/google/google-api-dotnet-client","homepage":"https://developers.google.com/api-client-library/dotnet","size":12722,"stargazers_count":49,"watchers_count":49,"language":"C#","has_issues":true,"has_downloads":false,"has_wiki":false,"has_pages":false,"forks_count":28,"mirror_url":null,"open_issues_count":97,"forks":28,"open_issues":97,"watchers":49,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/google/google-api-dotnet-client/pulls/564"},"html":{"href":"https://github.com/google/google-api-dotnet-client/pull/564"},"issue":{"href":"https://api.github.com/repos/google/google-api-dotnet-client/issues/564"},"comments":{"href":"https://api.github.com/repos/google/google-api-dotnet-client/issues/564/comments"},"review_comments":{"href":"https://api.github.com/repos/google/google-api-dotnet-client/pulls/564/comments"},"review_comment":{"href":"https://api.github.com/repos/google/google-api-dotnet-client/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/google/google-api-dotnet-client/pulls/564/commits"},"statuses":{"href":"https://api.github.com/repos/google/google-api-dotnet-client/statuses/93b6bffa49be799ad7b6bb67f1723615f2fa240c"}}}}