{"action":"created","comment":{"url":"https://api.github.com/repos/scribejava/scribejava/pulls/comments/50900023","id":50900023,"diff_hunk":"@@ -15,28 +15,31 @@\n \n     private static final String NETWORK_NAME = \"G+\";\n     private static final String PROTECTED_RESOURCE_URL = \"https://www.googleapis.com/plus/v1/people/me\";\n-    private static final Token EMPTY_TOKEN = null;\n \n-    public static void main(final String... args) {\n-        // Replace these with your client id and secret\n-        final String clientId = \"your client id\";\n-        final String clientSecret = \"your client secret\";\n-        final String secretState = \"secret\" + new Random().nextInt(999_999);\n+    public static void main(final String[] args) {\n+        final Scanner in = new Scanner(System.in, \"UTF-8\");\n+\n+        System.out.println(\"=== \" + NETWORK_NAME + \"'s OAuth Workflow ===\");\n+        System.out.println();\n+        \n+        System.out.println(\"Enter your Google API client key\");\n+        System.out.print(\">>\");\n+        final String clientId = in.nextLine();\n+        System.out.println(\"Enter your Google API client secret\");\n+        System.out.print(\">>\");\n+        final String clientSecret = in.nextLine();\n+        final String secretState = \"state_\" + new Random().nextInt(999_999);\n         final OAuth20Service service = new ServiceBuilder()\n                 .apiKey(clientId)\n                 .apiSecret(clientSecret)\n                 .scope(\"profile\") // replace with desired scope\n                 .state(secretState)\n-                .callback(\"http://example.com/callback\")\n+                //.callback(\"http://example.com/callback\")","path":"scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Google20Example.java","position":41,"original_position":41,"commit_id":"838b43c8ff44b3a93c9d74fecd0d913815f25b43","original_commit_id":"838b43c8ff44b3a93c9d74fecd0d913815f25b43","user":{"login":"pdtyreus","id":2000040,"avatar_url":"https://avatars.githubusercontent.com/u/2000040?v=3","gravatar_id":"","url":"https://api.github.com/users/pdtyreus","html_url":"https://github.com/pdtyreus","followers_url":"https://api.github.com/users/pdtyreus/followers","following_url":"https://api.github.com/users/pdtyreus/following{/other_user}","gists_url":"https://api.github.com/users/pdtyreus/gists{/gist_id}","starred_url":"https://api.github.com/users/pdtyreus/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pdtyreus/subscriptions","organizations_url":"https://api.github.com/users/pdtyreus/orgs","repos_url":"https://api.github.com/users/pdtyreus/repos","events_url":"https://api.github.com/users/pdtyreus/events{/privacy}","received_events_url":"https://api.github.com/users/pdtyreus/received_events","type":"User","site_admin":false},"body":"It was just easier to test as an OOB call. We can add the callback back if you prefer to have it that way.","created_at":"2016-01-26T21:07:53Z","updated_at":"2016-01-26T21:07:53Z","html_url":"https://github.com/scribejava/scribejava/pull/600#discussion_r50900023","pull_request_url":"https://api.github.com/repos/scribejava/scribejava/pulls/600","_links":{"self":{"href":"https://api.github.com/repos/scribejava/scribejava/pulls/comments/50900023"},"html":{"href":"https://github.com/scribejava/scribejava/pull/600#discussion_r50900023"},"pull_request":{"href":"https://api.github.com/repos/scribejava/scribejava/pulls/600"}}},"pull_request":{"url":"https://api.github.com/repos/scribejava/scribejava/pulls/600","id":56111344,"html_url":"https://github.com/scribejava/scribejava/pull/600","diff_url":"https://github.com/scribejava/scribejava/pull/600.diff","patch_url":"https://github.com/scribejava/scribejava/pull/600.patch","issue_url":"https://api.github.com/repos/scribejava/scribejava/issues/600","number":600,"state":"open","locked":false,"title":"Support OAuth2 refresh tokens","user":{"login":"pdtyreus","id":2000040,"avatar_url":"https://avatars.githubusercontent.com/u/2000040?v=3","gravatar_id":"","url":"https://api.github.com/users/pdtyreus","html_url":"https://github.com/pdtyreus","followers_url":"https://api.github.com/users/pdtyreus/followers","following_url":"https://api.github.com/users/pdtyreus/following{/other_user}","gists_url":"https://api.github.com/users/pdtyreus/gists{/gist_id}","starred_url":"https://api.github.com/users/pdtyreus/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pdtyreus/subscriptions","organizations_url":"https://api.github.com/users/pdtyreus/orgs","repos_url":"https://api.github.com/users/pdtyreus/repos","events_url":"https://api.github.com/users/pdtyreus/events{/privacy}","received_events_url":"https://api.github.com/users/pdtyreus/received_events","type":"User","site_admin":false},"body":"The existing code was using the same base class for OAuth1 and OAuth2 request and access tokens. While nice for the API, this was a bit limiting for functionality. It was also confusing because OAuth2 does not have request tokens, and OAuth2 access tokens do not hold a secret. Since the secret was a required field in the token, we ended up passing in a lot of empty strings in places where users may not know this was correct to do.\r\n\r\nI created the concept of RequestTokens and AccessTokens and refactored the code to be able to use the correct type depending on the API.\r\n\r\nI modified the `OAuthService` class quite a bit to support the new version-specific functionality. However, *no existing APIs were broken.* I took pains to retain backwards compatibility even though it makes the API a bit uglier.\r\n\r\nThere are some new `Token` types:\r\n\r\n * `RequestToken` and `AccessToken` are interfaces for the service to use.\r\n * `OAuth1Token` - basically the same as the previous `Token` class. Only applies to OAuth1. Implements both `RequestToken` and `AccessToken`.\r\n * `OAuth2AccessToken` - new class that holds OAuth 2 concerns like `refresh_token`, `expires_in`, and `token_type`. Implements `AccessToken`.\r\n\r\nI introduced a few new classes to help with parsing these tokens\r\n\r\n * `OAuth1RequestTokenExtractorImpl`\r\n * `OAuth2AccessTokenExtractorImpl`\r\n * `OAuth2JsonAccessTokenExtractorImpl`\r\n\r\nAll test cases pass and all the examples still run without changes.\r\n\r\nThe `OAuth20ServiceImpl` class now has a new method \r\n```\r\npublic OAuth2AccessToken refreshOAuth2AccessToken(final OAuth2AccessToken refreshToken)\r\n```\r\nthat will exchange a short-lived token for a longer one. *I modified the Facebook and Google20 examples to show how to use the new refresh token functionality.*\r\n\r\nRight now the only way to get an instance of an `OAuth20ServiceImpl` is to cast the response from `ServiceBuilder.build()`. We may want to consider adding methods like `.buildOAuth1Service()` or `.buildOAuth2Service()` that would automatically validate the type of the API and not require the end user to cast.\r\n\r\nThis is currently working for us as-in, but I'm very open to suggestions for improvement.\r\n\r\nsee issue #596","created_at":"2016-01-14T23:41:42Z","updated_at":"2016-01-26T21:07:53Z","closed_at":null,"merged_at":null,"merge_commit_sha":"66074ca8cc181a63a86c2ade4d7baf36516392c0","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/scribejava/scribejava/pulls/600/commits","review_comments_url":"https://api.github.com/repos/scribejava/scribejava/pulls/600/comments","review_comment_url":"https://api.github.com/repos/scribejava/scribejava/pulls/comments{/number}","comments_url":"https://api.github.com/repos/scribejava/scribejava/issues/600/comments","statuses_url":"https://api.github.com/repos/scribejava/scribejava/statuses/838b43c8ff44b3a93c9d74fecd0d913815f25b43","head":{"label":"pdtyreus:support_refresh_tokens","ref":"support_refresh_tokens","sha":"838b43c8ff44b3a93c9d74fecd0d913815f25b43","user":{"login":"pdtyreus","id":2000040,"avatar_url":"https://avatars.githubusercontent.com/u/2000040?v=3","gravatar_id":"","url":"https://api.github.com/users/pdtyreus","html_url":"https://github.com/pdtyreus","followers_url":"https://api.github.com/users/pdtyreus/followers","following_url":"https://api.github.com/users/pdtyreus/following{/other_user}","gists_url":"https://api.github.com/users/pdtyreus/gists{/gist_id}","starred_url":"https://api.github.com/users/pdtyreus/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pdtyreus/subscriptions","organizations_url":"https://api.github.com/users/pdtyreus/orgs","repos_url":"https://api.github.com/users/pdtyreus/repos","events_url":"https://api.github.com/users/pdtyreus/events{/privacy}","received_events_url":"https://api.github.com/users/pdtyreus/received_events","type":"User","site_admin":false},"repo":{"id":49444403,"name":"scribejava","full_name":"pdtyreus/scribejava","owner":{"login":"pdtyreus","id":2000040,"avatar_url":"https://avatars.githubusercontent.com/u/2000040?v=3","gravatar_id":"","url":"https://api.github.com/users/pdtyreus","html_url":"https://github.com/pdtyreus","followers_url":"https://api.github.com/users/pdtyreus/followers","following_url":"https://api.github.com/users/pdtyreus/following{/other_user}","gists_url":"https://api.github.com/users/pdtyreus/gists{/gist_id}","starred_url":"https://api.github.com/users/pdtyreus/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pdtyreus/subscriptions","organizations_url":"https://api.github.com/users/pdtyreus/orgs","repos_url":"https://api.github.com/users/pdtyreus/repos","events_url":"https://api.github.com/users/pdtyreus/events{/privacy}","received_events_url":"https://api.github.com/users/pdtyreus/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/pdtyreus/scribejava","description":"Simple OAuth library for Java","fork":true,"url":"https://api.github.com/repos/pdtyreus/scribejava","forks_url":"https://api.github.com/repos/pdtyreus/scribejava/forks","keys_url":"https://api.github.com/repos/pdtyreus/scribejava/keys{/key_id}","collaborators_url":"https://api.github.com/repos/pdtyreus/scribejava/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/pdtyreus/scribejava/teams","hooks_url":"https://api.github.com/repos/pdtyreus/scribejava/hooks","issue_events_url":"https://api.github.com/repos/pdtyreus/scribejava/issues/events{/number}","events_url":"https://api.github.com/repos/pdtyreus/scribejava/events","assignees_url":"https://api.github.com/repos/pdtyreus/scribejava/assignees{/user}","branches_url":"https://api.github.com/repos/pdtyreus/scribejava/branches{/branch}","tags_url":"https://api.github.com/repos/pdtyreus/scribejava/tags","blobs_url":"https://api.github.com/repos/pdtyreus/scribejava/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/pdtyreus/scribejava/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/pdtyreus/scribejava/git/refs{/sha}","trees_url":"https://api.github.com/repos/pdtyreus/scribejava/git/trees{/sha}","statuses_url":"https://api.github.com/repos/pdtyreus/scribejava/statuses/{sha}","languages_url":"https://api.github.com/repos/pdtyreus/scribejava/languages","stargazers_url":"https://api.github.com/repos/pdtyreus/scribejava/stargazers","contributors_url":"https://api.github.com/repos/pdtyreus/scribejava/contributors","subscribers_url":"https://api.github.com/repos/pdtyreus/scribejava/subscribers","subscription_url":"https://api.github.com/repos/pdtyreus/scribejava/subscription","commits_url":"https://api.github.com/repos/pdtyreus/scribejava/commits{/sha}","git_commits_url":"https://api.github.com/repos/pdtyreus/scribejava/git/commits{/sha}","comments_url":"https://api.github.com/repos/pdtyreus/scribejava/comments{/number}","issue_comment_url":"https://api.github.com/repos/pdtyreus/scribejava/issues/comments{/number}","contents_url":"https://api.github.com/repos/pdtyreus/scribejava/contents/{+path}","compare_url":"https://api.github.com/repos/pdtyreus/scribejava/compare/{base}...{head}","merges_url":"https://api.github.com/repos/pdtyreus/scribejava/merges","archive_url":"https://api.github.com/repos/pdtyreus/scribejava/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/pdtyreus/scribejava/downloads","issues_url":"https://api.github.com/repos/pdtyreus/scribejava/issues{/number}","pulls_url":"https://api.github.com/repos/pdtyreus/scribejava/pulls{/number}","milestones_url":"https://api.github.com/repos/pdtyreus/scribejava/milestones{/number}","notifications_url":"https://api.github.com/repos/pdtyreus/scribejava/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/pdtyreus/scribejava/labels{/name}","releases_url":"https://api.github.com/repos/pdtyreus/scribejava/releases{/id}","deployments_url":"https://api.github.com/repos/pdtyreus/scribejava/deployments","created_at":"2016-01-11T18:08:38Z","updated_at":"2016-01-11T18:08:39Z","pushed_at":"2016-01-21T18:00:31Z","git_url":"git://github.com/pdtyreus/scribejava.git","ssh_url":"git@github.com:pdtyreus/scribejava.git","clone_url":"https://github.com/pdtyreus/scribejava.git","svn_url":"https://github.com/pdtyreus/scribejava","homepage":"https://github.com/scribejava/scribejava","size":1896,"stargazers_count":0,"watchers_count":0,"language":"Java","has_issues":false,"has_downloads":true,"has_wiki":true,"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":"scribejava:master","ref":"master","sha":"f9aa6a8ac9e87d02cc2c927cf44864e897319e75","user":{"login":"scribejava","id":15140551,"avatar_url":"https://avatars.githubusercontent.com/u/15140551?v=3","gravatar_id":"","url":"https://api.github.com/users/scribejava","html_url":"https://github.com/scribejava","followers_url":"https://api.github.com/users/scribejava/followers","following_url":"https://api.github.com/users/scribejava/following{/other_user}","gists_url":"https://api.github.com/users/scribejava/gists{/gist_id}","starred_url":"https://api.github.com/users/scribejava/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/scribejava/subscriptions","organizations_url":"https://api.github.com/users/scribejava/orgs","repos_url":"https://api.github.com/users/scribejava/repos","events_url":"https://api.github.com/users/scribejava/events{/privacy}","received_events_url":"https://api.github.com/users/scribejava/received_events","type":"Organization","site_admin":false},"repo":{"id":889932,"name":"scribejava","full_name":"scribejava/scribejava","owner":{"login":"scribejava","id":15140551,"avatar_url":"https://avatars.githubusercontent.com/u/15140551?v=3","gravatar_id":"","url":"https://api.github.com/users/scribejava","html_url":"https://github.com/scribejava","followers_url":"https://api.github.com/users/scribejava/followers","following_url":"https://api.github.com/users/scribejava/following{/other_user}","gists_url":"https://api.github.com/users/scribejava/gists{/gist_id}","starred_url":"https://api.github.com/users/scribejava/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/scribejava/subscriptions","organizations_url":"https://api.github.com/users/scribejava/orgs","repos_url":"https://api.github.com/users/scribejava/repos","events_url":"https://api.github.com/users/scribejava/events{/privacy}","received_events_url":"https://api.github.com/users/scribejava/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/scribejava/scribejava","description":"Simple OAuth library for Java","fork":false,"url":"https://api.github.com/repos/scribejava/scribejava","forks_url":"https://api.github.com/repos/scribejava/scribejava/forks","keys_url":"https://api.github.com/repos/scribejava/scribejava/keys{/key_id}","collaborators_url":"https://api.github.com/repos/scribejava/scribejava/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/scribejava/scribejava/teams","hooks_url":"https://api.github.com/repos/scribejava/scribejava/hooks","issue_events_url":"https://api.github.com/repos/scribejava/scribejava/issues/events{/number}","events_url":"https://api.github.com/repos/scribejava/scribejava/events","assignees_url":"https://api.github.com/repos/scribejava/scribejava/assignees{/user}","branches_url":"https://api.github.com/repos/scribejava/scribejava/branches{/branch}","tags_url":"https://api.github.com/repos/scribejava/scribejava/tags","blobs_url":"https://api.github.com/repos/scribejava/scribejava/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/scribejava/scribejava/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/scribejava/scribejava/git/refs{/sha}","trees_url":"https://api.github.com/repos/scribejava/scribejava/git/trees{/sha}","statuses_url":"https://api.github.com/repos/scribejava/scribejava/statuses/{sha}","languages_url":"https://api.github.com/repos/scribejava/scribejava/languages","stargazers_url":"https://api.github.com/repos/scribejava/scribejava/stargazers","contributors_url":"https://api.github.com/repos/scribejava/scribejava/contributors","subscribers_url":"https://api.github.com/repos/scribejava/scribejava/subscribers","subscription_url":"https://api.github.com/repos/scribejava/scribejava/subscription","commits_url":"https://api.github.com/repos/scribejava/scribejava/commits{/sha}","git_commits_url":"https://api.github.com/repos/scribejava/scribejava/git/commits{/sha}","comments_url":"https://api.github.com/repos/scribejava/scribejava/comments{/number}","issue_comment_url":"https://api.github.com/repos/scribejava/scribejava/issues/comments{/number}","contents_url":"https://api.github.com/repos/scribejava/scribejava/contents/{+path}","compare_url":"https://api.github.com/repos/scribejava/scribejava/compare/{base}...{head}","merges_url":"https://api.github.com/repos/scribejava/scribejava/merges","archive_url":"https://api.github.com/repos/scribejava/scribejava/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/scribejava/scribejava/downloads","issues_url":"https://api.github.com/repos/scribejava/scribejava/issues{/number}","pulls_url":"https://api.github.com/repos/scribejava/scribejava/pulls{/number}","milestones_url":"https://api.github.com/repos/scribejava/scribejava/milestones{/number}","notifications_url":"https://api.github.com/repos/scribejava/scribejava/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/scribejava/scribejava/labels{/name}","releases_url":"https://api.github.com/repos/scribejava/scribejava/releases{/id}","deployments_url":"https://api.github.com/repos/scribejava/scribejava/deployments","created_at":"2010-09-05T19:11:40Z","updated_at":"2016-01-26T09:41:13Z","pushed_at":"2016-01-26T17:11:28Z","git_url":"git://github.com/scribejava/scribejava.git","ssh_url":"git@github.com:scribejava/scribejava.git","clone_url":"https://github.com/scribejava/scribejava.git","svn_url":"https://github.com/scribejava/scribejava","homepage":"https://github.com/scribejava/scribejava","size":4589,"stargazers_count":3027,"watchers_count":3027,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":1196,"mirror_url":null,"open_issues_count":42,"forks":1196,"open_issues":42,"watchers":3027,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/scribejava/scribejava/pulls/600"},"html":{"href":"https://github.com/scribejava/scribejava/pull/600"},"issue":{"href":"https://api.github.com/repos/scribejava/scribejava/issues/600"},"comments":{"href":"https://api.github.com/repos/scribejava/scribejava/issues/600/comments"},"review_comments":{"href":"https://api.github.com/repos/scribejava/scribejava/pulls/600/comments"},"review_comment":{"href":"https://api.github.com/repos/scribejava/scribejava/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/scribejava/scribejava/pulls/600/commits"},"statuses":{"href":"https://api.github.com/repos/scribejava/scribejava/statuses/838b43c8ff44b3a93c9d74fecd0d913815f25b43"}}}}