{"action":"created","comment":{"url":"https://api.github.com/repos/palantir/auth-tokens/pulls/comments/71160142","id":71160142,"diff_hunk":"@@ -0,0 +1,129 @@\n+/*\n+ * Copyright 2016 Palantir Technologies, Inc. All rights reserved.\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+package com.palantir.tokens.auth.http;\n+\n+import com.google.common.base.Preconditions;\n+import com.google.common.io.BaseEncoding;\n+import com.google.common.net.HttpHeaders;\n+import com.palantir.tokens.auth.AuthHeader;\n+import java.io.IOException;\n+import java.nio.charset.StandardCharsets;\n+import java.util.Objects;\n+import javax.servlet.Filter;\n+import javax.servlet.FilterChain;\n+import javax.servlet.FilterConfig;\n+import javax.servlet.ServletException;\n+import javax.servlet.ServletRequest;\n+import javax.servlet.ServletResponse;\n+import javax.servlet.http.HttpServletRequest;\n+import javax.servlet.http.HttpServletRequestWrapper;\n+import org.slf4j.Logger;\n+import org.slf4j.LoggerFactory;\n+\n+/**\n+ * A {@link Filter} that replaces basic auth with a bearer token.\n+ *\n+ * <p>It assumes that the bearer token is held in the password field of the basic auth credentials, and that it is\n+ * base-64 encoded.\n+ */\n+public class BasicAuthToBearerTokenFilter implements Filter {\n+    private static final Logger log = LoggerFactory.getLogger(BasicAuthToBearerTokenFilter.class);\n+\n+    private static final String BASIC_AUTH_STR = \"Basic\";\n+    private static final BaseEncoding BASE_64_ENCODING = BaseEncoding.base64Url();\n+\n+    @Override\n+    public void init(FilterConfig filterConfig) throws ServletException {\n+    }\n+\n+    @Override\n+    public final void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)\n+            throws IOException, ServletException {\n+        ServletRequest updatedRequest;\n+        try {\n+            updatedRequest = getRequestWithToken(request);\n+        } catch (IllegalArgumentException e) {\n+            updatedRequest = request;\n+        }\n+        chain.doFilter(updatedRequest, response);\n+    }\n+\n+    @Override\n+    public void destroy() {\n+    }\n+\n+    private ServletRequest getRequestWithToken(ServletRequest request) {\n+        if (request instanceof HttpServletRequest) {\n+            HttpServletRequest httpRequest = (HttpServletRequest) request;\n+            String rawAuthHeader = httpRequest.getHeader(HttpHeaders.AUTHORIZATION);\n+            return getRequestWithTokenFromRawAuthHeader(rawAuthHeader, httpRequest);\n+        } else {\n+            String message = \"Request is not an HttpServletRequest.\";\n+            log.warn(message);\n+            throw new IllegalArgumentException(message);\n+        }\n+    }\n+\n+    private ServletRequest getRequestWithTokenFromRawAuthHeader(String rawAuthHeader, HttpServletRequest request) {\n+        Preconditions.checkNotNull(rawAuthHeader, \"null rawAuthHeader\");\n+        if (isBasicAuth(rawAuthHeader)) {\n+            AuthHeader authHeader = base64DecodePassword(rawAuthHeader);\n+            return getRequestWithTokenFromAuthHeader(authHeader, request);\n+        } else {\n+            String message = \"Auth header is not basic auth.\";\n+            log.warn(message);\n+            throw new IllegalArgumentException(message);\n+        }\n+    }\n+\n+    private ServletRequest getRequestWithTokenFromAuthHeader(final AuthHeader authHeader, HttpServletRequest request) {\n+        return new HttpServletRequestWrapper(request) {\n+            @Override\n+            public String getHeader(String name) {\n+                if (Objects.equals(name, HttpHeaders.AUTHORIZATION)) {","path":"auth-tokens-filter/src/main/java/com/palantir/tokens/auth/http/BasicAuthToBearerTokenFilter.java","position":97,"original_position":97,"commit_id":"96ae87102659fc2af41595c4a2ff77e9787dc5d1","original_commit_id":"96ae87102659fc2af41595c4a2ff77e9787dc5d1","user":{"login":"qinfchen","id":8294715,"avatar_url":"https://avatars.githubusercontent.com/u/8294715?v=3","gravatar_id":"","url":"https://api.github.com/users/qinfchen","html_url":"https://github.com/qinfchen","followers_url":"https://api.github.com/users/qinfchen/followers","following_url":"https://api.github.com/users/qinfchen/following{/other_user}","gists_url":"https://api.github.com/users/qinfchen/gists{/gist_id}","starred_url":"https://api.github.com/users/qinfchen/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/qinfchen/subscriptions","organizations_url":"https://api.github.com/users/qinfchen/orgs","repos_url":"https://api.github.com/users/qinfchen/repos","events_url":"https://api.github.com/users/qinfchen/events{/privacy}","received_events_url":"https://api.github.com/users/qinfchen/received_events","type":"User","site_admin":false},"body":"Strings.equals? object.equals compares memory reference, right?","created_at":"2016-07-18T14:44:19Z","updated_at":"2016-07-18T14:44:19Z","html_url":"https://github.com/palantir/auth-tokens/pull/14#discussion_r71160142","pull_request_url":"https://api.github.com/repos/palantir/auth-tokens/pulls/14","_links":{"self":{"href":"https://api.github.com/repos/palantir/auth-tokens/pulls/comments/71160142"},"html":{"href":"https://github.com/palantir/auth-tokens/pull/14#discussion_r71160142"},"pull_request":{"href":"https://api.github.com/repos/palantir/auth-tokens/pulls/14"}}},"pull_request":{"url":"https://api.github.com/repos/palantir/auth-tokens/pulls/14","id":77162948,"html_url":"https://github.com/palantir/auth-tokens/pull/14","diff_url":"https://github.com/palantir/auth-tokens/pull/14.diff","patch_url":"https://github.com/palantir/auth-tokens/pull/14.patch","issue_url":"https://api.github.com/repos/palantir/auth-tokens/issues/14","number":14,"state":"open","locked":false,"title":"BasicAuthToBearerTokenFilter","user":{"login":"ags799","id":2957581,"avatar_url":"https://avatars.githubusercontent.com/u/2957581?v=3","gravatar_id":"","url":"https://api.github.com/users/ags799","html_url":"https://github.com/ags799","followers_url":"https://api.github.com/users/ags799/followers","following_url":"https://api.github.com/users/ags799/following{/other_user}","gists_url":"https://api.github.com/users/ags799/gists{/gist_id}","starred_url":"https://api.github.com/users/ags799/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ags799/subscriptions","organizations_url":"https://api.github.com/users/ags799/orgs","repos_url":"https://api.github.com/users/ags799/repos","events_url":"https://api.github.com/users/ags799/events{/privacy}","received_events_url":"https://api.github.com/users/ags799/received_events","type":"User","site_admin":false},"body":"WIP","created_at":"2016-07-12T17:59:20Z","updated_at":"2016-07-18T14:44:19Z","closed_at":null,"merged_at":null,"merge_commit_sha":"00b825428391995403ba98ba13f0f53a017684e8","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/palantir/auth-tokens/pulls/14/commits","review_comments_url":"https://api.github.com/repos/palantir/auth-tokens/pulls/14/comments","review_comment_url":"https://api.github.com/repos/palantir/auth-tokens/pulls/comments{/number}","comments_url":"https://api.github.com/repos/palantir/auth-tokens/issues/14/comments","statuses_url":"https://api.github.com/repos/palantir/auth-tokens/statuses/96ae87102659fc2af41595c4a2ff77e9787dc5d1","head":{"label":"ags799:asharp/basic-auth-to-bearer-token","ref":"asharp/basic-auth-to-bearer-token","sha":"96ae87102659fc2af41595c4a2ff77e9787dc5d1","user":{"login":"ags799","id":2957581,"avatar_url":"https://avatars.githubusercontent.com/u/2957581?v=3","gravatar_id":"","url":"https://api.github.com/users/ags799","html_url":"https://github.com/ags799","followers_url":"https://api.github.com/users/ags799/followers","following_url":"https://api.github.com/users/ags799/following{/other_user}","gists_url":"https://api.github.com/users/ags799/gists{/gist_id}","starred_url":"https://api.github.com/users/ags799/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ags799/subscriptions","organizations_url":"https://api.github.com/users/ags799/orgs","repos_url":"https://api.github.com/users/ags799/repos","events_url":"https://api.github.com/users/ags799/events{/privacy}","received_events_url":"https://api.github.com/users/ags799/received_events","type":"User","site_admin":false},"repo":{"id":63180706,"name":"auth-tokens","full_name":"ags799/auth-tokens","owner":{"login":"ags799","id":2957581,"avatar_url":"https://avatars.githubusercontent.com/u/2957581?v=3","gravatar_id":"","url":"https://api.github.com/users/ags799","html_url":"https://github.com/ags799","followers_url":"https://api.github.com/users/ags799/followers","following_url":"https://api.github.com/users/ags799/following{/other_user}","gists_url":"https://api.github.com/users/ags799/gists{/gist_id}","starred_url":"https://api.github.com/users/ags799/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ags799/subscriptions","organizations_url":"https://api.github.com/users/ags799/orgs","repos_url":"https://api.github.com/users/ags799/repos","events_url":"https://api.github.com/users/ags799/events{/privacy}","received_events_url":"https://api.github.com/users/ags799/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/ags799/auth-tokens","description":null,"fork":true,"url":"https://api.github.com/repos/ags799/auth-tokens","forks_url":"https://api.github.com/repos/ags799/auth-tokens/forks","keys_url":"https://api.github.com/repos/ags799/auth-tokens/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ags799/auth-tokens/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ags799/auth-tokens/teams","hooks_url":"https://api.github.com/repos/ags799/auth-tokens/hooks","issue_events_url":"https://api.github.com/repos/ags799/auth-tokens/issues/events{/number}","events_url":"https://api.github.com/repos/ags799/auth-tokens/events","assignees_url":"https://api.github.com/repos/ags799/auth-tokens/assignees{/user}","branches_url":"https://api.github.com/repos/ags799/auth-tokens/branches{/branch}","tags_url":"https://api.github.com/repos/ags799/auth-tokens/tags","blobs_url":"https://api.github.com/repos/ags799/auth-tokens/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ags799/auth-tokens/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ags799/auth-tokens/git/refs{/sha}","trees_url":"https://api.github.com/repos/ags799/auth-tokens/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ags799/auth-tokens/statuses/{sha}","languages_url":"https://api.github.com/repos/ags799/auth-tokens/languages","stargazers_url":"https://api.github.com/repos/ags799/auth-tokens/stargazers","contributors_url":"https://api.github.com/repos/ags799/auth-tokens/contributors","subscribers_url":"https://api.github.com/repos/ags799/auth-tokens/subscribers","subscription_url":"https://api.github.com/repos/ags799/auth-tokens/subscription","commits_url":"https://api.github.com/repos/ags799/auth-tokens/commits{/sha}","git_commits_url":"https://api.github.com/repos/ags799/auth-tokens/git/commits{/sha}","comments_url":"https://api.github.com/repos/ags799/auth-tokens/comments{/number}","issue_comment_url":"https://api.github.com/repos/ags799/auth-tokens/issues/comments{/number}","contents_url":"https://api.github.com/repos/ags799/auth-tokens/contents/{+path}","compare_url":"https://api.github.com/repos/ags799/auth-tokens/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ags799/auth-tokens/merges","archive_url":"https://api.github.com/repos/ags799/auth-tokens/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ags799/auth-tokens/downloads","issues_url":"https://api.github.com/repos/ags799/auth-tokens/issues{/number}","pulls_url":"https://api.github.com/repos/ags799/auth-tokens/pulls{/number}","milestones_url":"https://api.github.com/repos/ags799/auth-tokens/milestones{/number}","notifications_url":"https://api.github.com/repos/ags799/auth-tokens/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ags799/auth-tokens/labels{/name}","releases_url":"https://api.github.com/repos/ags799/auth-tokens/releases{/id}","deployments_url":"https://api.github.com/repos/ags799/auth-tokens/deployments","created_at":"2016-07-12T17:57:47Z","updated_at":"2016-07-12T17:57:47Z","pushed_at":"2016-07-18T14:41:14Z","git_url":"git://github.com/ags799/auth-tokens.git","ssh_url":"git@github.com:ags799/auth-tokens.git","clone_url":"https://github.com/ags799/auth-tokens.git","svn_url":"https://github.com/ags799/auth-tokens","homepage":null,"size":235,"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":"develop"}},"base":{"label":"palantir:develop","ref":"develop","sha":"a83a033903085182eecfeb11cc56cf102ed01b1a","user":{"login":"palantir","id":303157,"avatar_url":"https://avatars.githubusercontent.com/u/303157?v=3","gravatar_id":"","url":"https://api.github.com/users/palantir","html_url":"https://github.com/palantir","followers_url":"https://api.github.com/users/palantir/followers","following_url":"https://api.github.com/users/palantir/following{/other_user}","gists_url":"https://api.github.com/users/palantir/gists{/gist_id}","starred_url":"https://api.github.com/users/palantir/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/palantir/subscriptions","organizations_url":"https://api.github.com/users/palantir/orgs","repos_url":"https://api.github.com/users/palantir/repos","events_url":"https://api.github.com/users/palantir/events{/privacy}","received_events_url":"https://api.github.com/users/palantir/received_events","type":"Organization","site_admin":false},"repo":{"id":55093069,"name":"auth-tokens","full_name":"palantir/auth-tokens","owner":{"login":"palantir","id":303157,"avatar_url":"https://avatars.githubusercontent.com/u/303157?v=3","gravatar_id":"","url":"https://api.github.com/users/palantir","html_url":"https://github.com/palantir","followers_url":"https://api.github.com/users/palantir/followers","following_url":"https://api.github.com/users/palantir/following{/other_user}","gists_url":"https://api.github.com/users/palantir/gists{/gist_id}","starred_url":"https://api.github.com/users/palantir/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/palantir/subscriptions","organizations_url":"https://api.github.com/users/palantir/orgs","repos_url":"https://api.github.com/users/palantir/repos","events_url":"https://api.github.com/users/palantir/events{/privacy}","received_events_url":"https://api.github.com/users/palantir/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/palantir/auth-tokens","description":"","fork":false,"url":"https://api.github.com/repos/palantir/auth-tokens","forks_url":"https://api.github.com/repos/palantir/auth-tokens/forks","keys_url":"https://api.github.com/repos/palantir/auth-tokens/keys{/key_id}","collaborators_url":"https://api.github.com/repos/palantir/auth-tokens/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/palantir/auth-tokens/teams","hooks_url":"https://api.github.com/repos/palantir/auth-tokens/hooks","issue_events_url":"https://api.github.com/repos/palantir/auth-tokens/issues/events{/number}","events_url":"https://api.github.com/repos/palantir/auth-tokens/events","assignees_url":"https://api.github.com/repos/palantir/auth-tokens/assignees{/user}","branches_url":"https://api.github.com/repos/palantir/auth-tokens/branches{/branch}","tags_url":"https://api.github.com/repos/palantir/auth-tokens/tags","blobs_url":"https://api.github.com/repos/palantir/auth-tokens/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/palantir/auth-tokens/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/palantir/auth-tokens/git/refs{/sha}","trees_url":"https://api.github.com/repos/palantir/auth-tokens/git/trees{/sha}","statuses_url":"https://api.github.com/repos/palantir/auth-tokens/statuses/{sha}","languages_url":"https://api.github.com/repos/palantir/auth-tokens/languages","stargazers_url":"https://api.github.com/repos/palantir/auth-tokens/stargazers","contributors_url":"https://api.github.com/repos/palantir/auth-tokens/contributors","subscribers_url":"https://api.github.com/repos/palantir/auth-tokens/subscribers","subscription_url":"https://api.github.com/repos/palantir/auth-tokens/subscription","commits_url":"https://api.github.com/repos/palantir/auth-tokens/commits{/sha}","git_commits_url":"https://api.github.com/repos/palantir/auth-tokens/git/commits{/sha}","comments_url":"https://api.github.com/repos/palantir/auth-tokens/comments{/number}","issue_comment_url":"https://api.github.com/repos/palantir/auth-tokens/issues/comments{/number}","contents_url":"https://api.github.com/repos/palantir/auth-tokens/contents/{+path}","compare_url":"https://api.github.com/repos/palantir/auth-tokens/compare/{base}...{head}","merges_url":"https://api.github.com/repos/palantir/auth-tokens/merges","archive_url":"https://api.github.com/repos/palantir/auth-tokens/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/palantir/auth-tokens/downloads","issues_url":"https://api.github.com/repos/palantir/auth-tokens/issues{/number}","pulls_url":"https://api.github.com/repos/palantir/auth-tokens/pulls{/number}","milestones_url":"https://api.github.com/repos/palantir/auth-tokens/milestones{/number}","notifications_url":"https://api.github.com/repos/palantir/auth-tokens/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/palantir/auth-tokens/labels{/name}","releases_url":"https://api.github.com/repos/palantir/auth-tokens/releases{/id}","deployments_url":"https://api.github.com/repos/palantir/auth-tokens/deployments","created_at":"2016-03-30T19:49:02Z","updated_at":"2016-04-01T00:43:12Z","pushed_at":"2016-07-18T14:41:15Z","git_url":"git://github.com/palantir/auth-tokens.git","ssh_url":"git@github.com:palantir/auth-tokens.git","clone_url":"https://github.com/palantir/auth-tokens.git","svn_url":"https://github.com/palantir/auth-tokens","homepage":null,"size":221,"stargazers_count":0,"watchers_count":0,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":3,"mirror_url":null,"open_issues_count":5,"forks":3,"open_issues":5,"watchers":0,"default_branch":"develop"}},"_links":{"self":{"href":"https://api.github.com/repos/palantir/auth-tokens/pulls/14"},"html":{"href":"https://github.com/palantir/auth-tokens/pull/14"},"issue":{"href":"https://api.github.com/repos/palantir/auth-tokens/issues/14"},"comments":{"href":"https://api.github.com/repos/palantir/auth-tokens/issues/14/comments"},"review_comments":{"href":"https://api.github.com/repos/palantir/auth-tokens/pulls/14/comments"},"review_comment":{"href":"https://api.github.com/repos/palantir/auth-tokens/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/palantir/auth-tokens/pulls/14/commits"},"statuses":{"href":"https://api.github.com/repos/palantir/auth-tokens/statuses/96ae87102659fc2af41595c4a2ff77e9787dc5d1"}}}}
{"actor":{"display_login":"qinfchen"}}