Merge branch 'stable-2.10' into stable-2.11

* stable-2.10:
  Avoid NPE when getting groups for anonymous users
  Identify the OAuth provider as simply "GitHub"
  Implementation of Gerrit OAuthServiceProvider


A merge was done with change I45d085503 but that was not a merge commit
so git does not know about it and conflicts will occur when trying to
merge.

This merge is done with the 'ours' strategy which keeps everthing from
the stable-2.11 branch.  In other words the content of the branch is the
same as before. The only difference is that now git is aware of the merge
and will not attempt to merge those commits again next time.

Change-Id: I4c96ea6cdeacb8abc7b6e31e36fe09e098c29014
diff --git a/README.md b/README.md
index 8ce043c..5392da8 100644
--- a/README.md
+++ b/README.md
@@ -142,3 +142,24 @@
 * ClientId []: <provided client id from previous step>
 * ClientSecret []: <provided client secret from previous step>
 
+### Contributing to the GitHub plugin
+
+The GitHub plugin uses the lombok library, which provides a set of
+annotations to reduce the amount of boilerplate code that has to be
+written.
+
+To build the plugin in Eclipse, the Lombok Eclipse integration must be
+installed.
+
+Download lombok.jar from http://projectlombok.org/ and install:
+
+
+```
+  java -jar lombok.jar
+```
+
+Follow the instructions to select your Eclipse installation if the
+installer cannot detect it automatically.
+
+After the installation, Eclipse must be restarted and compilation
+errors should disappear.
diff --git a/github-oauth/pom.xml b/github-oauth/pom.xml
index b900a3a..b4e9a2b 100644
--- a/github-oauth/pom.xml
+++ b/github-oauth/pom.xml
@@ -21,7 +21,7 @@
   <parent>
     <groupId>com.googlesource.gerrit.plugins.github</groupId>
     <artifactId>github-parent</artifactId>
-    <version>2.10.3</version>
+    <version>2.11</version>
   </parent>
   <artifactId>github-oauth</artifactId>
   <name>Gerrit Code Review - GitHub OAuth login</name>
@@ -107,12 +107,12 @@
     <dependency>
       <groupId>org.kohsuke</groupId>
       <artifactId>github-api</artifactId>
-      <version>1.57</version>
+      <version>1.62</version>
     </dependency>
     <dependency>
       <groupId>org.apache.httpcomponents</groupId>
       <artifactId>httpclient</artifactId>
-      <version>4.2.5</version>
+      <version>4.4</version>
     </dependency>
   </dependencies>
 </project>
diff --git a/github-oauth/src/main/java/com/google/gerrit/httpd/XGerritAuth.java b/github-oauth/src/main/java/com/google/gerrit/httpd/XGerritAuth.java
index 69a40ca..4fd0734 100644
--- a/github-oauth/src/main/java/com/google/gerrit/httpd/XGerritAuth.java
+++ b/github-oauth/src/main/java/com/google/gerrit/httpd/XGerritAuth.java
@@ -13,14 +13,14 @@
 // limitations under the License.
 package com.google.gerrit.httpd;
 
-import javax.servlet.http.Cookie;
-
 import com.google.common.cache.Cache;
 import com.google.gerrit.httpd.WebSessionManager.Val;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
 import com.google.inject.name.Named;
 
+import javax.servlet.http.Cookie;
+
 @Singleton
 public class XGerritAuth {
   public static final String X_GERRIT_AUTH = "X-Gerrit-Auth";
diff --git a/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/AuthenticatedHttpRequest.java b/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/AuthenticatedHttpRequest.java
index 46f6ea9..d13ba3f 100644
--- a/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/AuthenticatedHttpRequest.java
+++ b/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/AuthenticatedHttpRequest.java
@@ -13,6 +13,8 @@
 // limitations under the License.
 package com.googlesource.gerrit.plugins.github.oauth;
 
+import com.google.common.collect.Iterators;
+
 import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -20,8 +22,6 @@
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletRequestWrapper;
 
-import com.google.common.collect.Iterators;
-
 public class AuthenticatedHttpRequest extends HttpServletRequestWrapper {
   private HashMap<String, String> headers = new HashMap<String, String>();
 
diff --git a/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/AuthenticatedLoginHttpResponse.java b/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/AuthenticatedLoginHttpResponse.java
index 5e4b586..e9bd369 100644
--- a/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/AuthenticatedLoginHttpResponse.java
+++ b/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/AuthenticatedLoginHttpResponse.java
@@ -15,6 +15,7 @@
 
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
+import java.io.OutputStreamWriter;
 import java.io.PrintWriter;
 import java.util.Collection;
 import java.util.Collections;
@@ -174,7 +175,8 @@
 
   @Override
   public PrintWriter getWriter() throws IOException {
-    return new PrintWriter(outputStream);
+    return new PrintWriter(new OutputStreamWriter(outputStream,
+        characterEncoding));
   }
 
   @Override
diff --git a/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/GitHubHttpProvider.java b/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/GitHubHttpProvider.java
deleted file mode 100644
index 4892476..0000000
--- a/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/GitHubHttpProvider.java
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-package com.googlesource.gerrit.plugins.github.oauth;
-
-import org.apache.http.HttpHost;
-import org.apache.http.client.HttpClient;
-import org.apache.http.conn.routing.HttpRoute;
-import org.apache.http.conn.scheme.PlainSocketFactory;
-import org.apache.http.conn.scheme.Scheme;
-import org.apache.http.conn.scheme.SchemeRegistry;
-import org.apache.http.conn.ssl.SSLSocketFactory;
-import org.apache.http.impl.client.DefaultHttpClient;
-import org.apache.http.impl.conn.PoolingClientConnectionManager;
-
-import com.google.inject.Provider;
-import com.google.inject.Singleton;
-
-@Singleton
-public class GitHubHttpProvider implements Provider<HttpClient> {
-  private static final int MAX_TOTAL_CONN = 1024;
-  private static final int MAX_CONN_PER_ROUTE = 10;
-  private static final int MAX_LOCALHOST_CONN = 512;
-  private final PoolingClientConnectionManager connectionManager;
-
-  public GitHubHttpProvider() {
-    SchemeRegistry schemeRegistry = new SchemeRegistry();
-    schemeRegistry.register(new Scheme("http", 80, PlainSocketFactory
-        .getSocketFactory()));
-    schemeRegistry.register(new Scheme("https", 443, SSLSocketFactory
-        .getSocketFactory()));
-
-    connectionManager = new PoolingClientConnectionManager(schemeRegistry);
-    connectionManager.setMaxTotal(MAX_TOTAL_CONN);
-    connectionManager.setDefaultMaxPerRoute(MAX_CONN_PER_ROUTE);
-    HttpHost localhost = new HttpHost("locahost", 80);
-    connectionManager.setMaxPerRoute(new HttpRoute(localhost),
-        MAX_LOCALHOST_CONN);
-  }
-
-  @Override
-  public HttpClient get() {
-    return new DefaultHttpClient(connectionManager);
-  }
-
-}
diff --git a/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/GitHubLogin.java b/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/GitHubLogin.java
index 79cd552..081d6c1 100644
--- a/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/GitHubLogin.java
+++ b/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/GitHubLogin.java
@@ -17,6 +17,7 @@
 import static java.util.concurrent.TimeUnit.DAYS;
 
 import java.io.IOException;
+import java.io.Serializable;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashSet;
@@ -25,33 +26,30 @@
 import java.util.SortedSet;
 import java.util.TreeSet;
 
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
 import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
 import lombok.Getter;
 
-import org.apache.http.HttpStatus;
 import org.kohsuke.github.GHMyself;
 import org.kohsuke.github.GitHub;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Objects;
+import com.google.common.base.MoreObjects;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
 import com.googlesource.gerrit.plugins.github.oauth.OAuthProtocol.AccessToken;
 import com.googlesource.gerrit.plugins.github.oauth.OAuthProtocol.Scope;
 
-public class GitHubLogin {
+public class GitHubLogin implements Serializable {
+  private static final long serialVersionUID = 1L;
   private static final Logger log = LoggerFactory.getLogger(GitHubLogin.class);
   private static final List<Scope> DEFAULT_SCOPES = Arrays.asList(
       Scope.PUBLIC_REPO, Scope.USER_EMAIL);
-  private static final int YEARS = 365;
   private static final long SCOPE_COOKIE_NEVER_EXPIRES = DAYS
-      .toSeconds(50 * YEARS);
+      .toSeconds(50 * 365);
 
   @Singleton
   public static class Provider extends HttpSessionProvider<GitHubLogin> {
@@ -62,21 +60,16 @@
   }
 
   @Getter
-  protected AccessToken token;
+  private AccessToken token;
 
-  @Getter
-  protected GitHub hub;
-
-  protected GHMyself myself;
-
-  private transient OAuthProtocol oauth;
+  private String state;
 
   private SortedSet<Scope> loginScopes;
   private final GitHubOAuthConfig config;
 
-  public GHMyself getMyself() {
+  public GHMyself getMyself() throws IOException {
     if (isLoggedIn()) {
-      return myself;
+      return getHub().getMyself();
     } else {
       return null;
     }
@@ -84,92 +77,68 @@
 
   public Set<String> getMyOrganisationsLogins() throws IOException {
     if (isLoggedIn()) {
-      return hub.getMyOrganizations().keySet();
+      return getHub().getMyOrganizations().keySet();
     } else {
       return Collections.emptySet();
     }
   }
 
   @Inject
-  public GitHubLogin(final OAuthProtocol oauth, final GitHubOAuthConfig config) {
-    this.oauth = oauth;
+  public GitHubLogin(final GitHubOAuthConfig config) {
     this.config = config;
   }
 
   public boolean isLoggedIn() {
-    boolean loggedIn = token != null && hub != null;
-    if (loggedIn && myself == null) {
-      try {
-        myself = hub.getMyself();
-      } catch (Throwable e) {
-        log.error("Connection to GitHub broken: logging out", e);
-        logout();
-        loggedIn = false;
-      }
-    }
-    return loggedIn;
-  }
-
-  public boolean login(ServletRequest request, ServletResponse response,
-      Scope... scopes) throws IOException {
-    return login((HttpServletRequest) request, (HttpServletResponse) response,
-        scopes);
+    return token != null;
   }
 
   public boolean login(HttpServletRequest request,
-      HttpServletResponse response, Scope... scopes) throws IOException {
+      HttpServletResponse response, OAuthProtocol oauth, Scope... scopes) throws IOException {
     if (isLoggedIn()) {
       return true;
     }
 
     log.debug("Login " + this);
-
     if (OAuthProtocol.isOAuthFinal(request)) {
       log.debug("Login-FINAL " + this);
-      AccessToken loginAccessToken = oauth.loginPhase2(request, response);
-      if(loginAccessToken != null && !loginAccessToken.isError()) {
-        login(loginAccessToken);
-      }
+      login(oauth.loginPhase2(request, response, state));
+      this.state = ""; // Make sure state is used only once
 
       if (isLoggedIn()) {
         log.debug("Login-SUCCESS " + this);
         response.sendRedirect(OAuthProtocol.getTargetUrl(request));
         return true;
       } else {
-        response.sendError(HttpStatus.SC_UNAUTHORIZED);
         return false;
       }
     } else {
       this.loginScopes = getScopes(getScopesKey(request, response), scopes);
       log.debug("Login-PHASE1 " + this);
-      oauth.loginPhase1(request, response, loginScopes);
+      state = oauth.loginPhase1(request, response, loginScopes);
       return false;
     }
   }
 
   public void logout() {
-    hub = null;
     token = null;
   }
 
-  public OAuthProtocol getOAuthProtocol() {
-    return oauth;
-  }
-
   public GitHub login(AccessToken authToken) throws IOException {
     log.debug("Logging in using access token {}", authToken.accessToken);
     this.token = authToken;
-    this.hub = GitHub.connectUsingOAuth(authToken.accessToken);
-    this.myself = hub.getMyself();
-    return this.hub;
+    return getHub();
   }
 
   @Override
   public String toString() {
-    return "GitHubLogin [token=" + token + ", myself=" + myself + ", scopes="
+    return "GitHubLogin [token=" + token + ", scopes="
         + loginScopes + "]";
   }
 
+  public GitHub getHub() throws IOException {
+    return GitHub.connectUsingOAuth(this.token.accessToken);
+  }
+
   private String getScopesKey(HttpServletRequest request,
       HttpServletResponse response) {
     String scopeRequested = request.getParameter("scope");
@@ -184,7 +153,7 @@
       response.addCookie(scopeCookie);
     }
 
-    return Objects.firstNonNull(scopeRequested, "scopes");
+    return MoreObjects.firstNonNull(scopeRequested, "scopes");
   }
 
   private String getScopesKeyFromCookie(HttpServletRequest request) {
@@ -209,7 +178,7 @@
   }
 
   private List<Scope> scopesForKey(String baseScopeKey) {
-    return Objects
+    return MoreObjects
         .firstNonNull(config.scopes.get(baseScopeKey), DEFAULT_SCOPES);
   }
 }
diff --git a/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/GitHubLogoutServletResponse.java b/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/GitHubLogoutServletResponse.java
index a2ee754..9f4709e 100644
--- a/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/GitHubLogoutServletResponse.java
+++ b/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/GitHubLogoutServletResponse.java
@@ -13,13 +13,13 @@
 // limitations under the License.
 package com.googlesource.gerrit.plugins.github.oauth;
 
+import com.google.common.base.MoreObjects;
+
 import java.io.IOException;
 
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpServletResponseWrapper;
 
-import com.google.common.base.Objects;
-
 public class GitHubLogoutServletResponse extends HttpServletResponseWrapper {
   private String redirectUrl;
 
@@ -30,6 +30,6 @@
 
   @Override
   public void sendRedirect(String location) throws IOException {
-    super.sendRedirect(Objects.firstNonNull(redirectUrl, location));
+    super.sendRedirect(MoreObjects.firstNonNull(redirectUrl, location));
   }
 }
diff --git a/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/GitHubOAuthConfig.java b/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/GitHubOAuthConfig.java
index 14cce5c..7d30d19 100644
--- a/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/GitHubOAuthConfig.java
+++ b/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/GitHubOAuthConfig.java
@@ -13,36 +13,42 @@
 // limitations under the License.
 package com.googlesource.gerrit.plugins.github.oauth;
 
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.eclipse.jgit.lib.Config;
-
-import com.google.common.base.Objects;
+import com.google.common.base.MoreObjects;
+import com.google.common.base.CharMatcher;
+import com.google.common.base.Preconditions;
 import com.google.common.base.Strings;
 import com.google.common.collect.Maps;
 import com.google.gerrit.reviewdb.client.AuthType;
+import com.google.gerrit.server.config.AuthConfig;
+import com.google.gerrit.server.config.CanonicalWebUrl;
 import com.google.gerrit.server.config.GerritServerConfig;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
 import com.googlesource.gerrit.plugins.github.oauth.OAuthProtocol.Scope;
 
+import org.eclipse.jgit.lib.Config;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
 @Singleton
-public class GitHubOAuthConfig {
-  protected static final String CONF_SECTION = "github";
-  private static final String LOGIN_OAUTH_AUTHORIZE = "/login/oauth/authorize";
-  private static final String GITHUB_URL = "https://github.com";
-  public static final String OAUTH_FINAL = "oauth";
-  public static final String LOGIN_OAUTH_ACCESS_TOKEN =
+public
+class GitHubOAuthConfig {
+  public static final String CONF_SECTION = "github";
+  public static final String GITHUB_OAUTH_AUTHORIZE = "/login/oauth/authorize";
+  public static final String GITHUB_OAUTH_ACCESS_TOKEN =
       "/login/oauth/access_token";
-  public static final String OAUTH_LOGIN = "/login";
-  public static final String OAUTH_LOGOUT = "/logout";
+  public static final String GITHUB_GET_USER = "/user";
+  public static final String GERRIT_OAUTH_FINAL = "/oauth";
+  public static final String GITHUB_URL_DEFAULT = "https://github.com";
+  public static final String GITHUB_API_URL_DEFAULT = "https://api.github.com";
+  public static final String GERRIT_LOGIN = "/login";
+  public static final String GERRIT_LOGOUT = "/logout";
 
   public final String gitHubUrl;
+  public final String gitHubApiUrl;
   public final String gitHubClientId;
   public final String gitHubClientSecret;
   public final String logoutRedirectUrl;
@@ -54,34 +60,49 @@
   public final Map<String, List<OAuthProtocol.Scope>> scopes;
   public final int fileUpdateMaxRetryCount;
   public final int fileUpdateMaxRetryIntervalMsec;
-  public final Config gerritConfig;
   public final String oauthHttpHeader;
 
   @Inject
-  public GitHubOAuthConfig(@GerritServerConfig Config config)
-      throws MalformedURLException {
-    this.gerritConfig = config;
+  protected
+  GitHubOAuthConfig(@GerritServerConfig Config config,
+      @CanonicalWebUrl String canonicalWebUrl, AuthConfig authConfig) {
+    httpHeader =
+        Preconditions.checkNotNull(
+            config.getString("auth", null, "httpHeader"),
+            "HTTP Header for GitHub user must be provided");
+    gitHubUrl =
+        trimTrailingSlash(MoreObjects.firstNonNull(
+            config.getString(CONF_SECTION, null, "url"), GITHUB_URL_DEFAULT));
+    gitHubApiUrl =
+        trimTrailingSlash(MoreObjects.firstNonNull(
+            config.getString(CONF_SECTION, null, "apiUrl"),
+            GITHUB_API_URL_DEFAULT));
+    gitHubClientId =
+        Preconditions.checkNotNull(
+            config.getString(CONF_SECTION, null, "clientId"),
+            "GitHub `clientId` must be provided");
+    gitHubClientSecret =
+        Preconditions.checkNotNull(
+            config.getString(CONF_SECTION, null, "clientSecret"),
+            "GitHub `clientSecret` must be provided");
 
-    httpHeader = config.getString("auth", null, "httpHeader");
     oauthHttpHeader = config.getString("auth", null, "httpExternalIdHeader");
-    gitHubUrl = dropTrailingSlash(
-        Objects.firstNonNull(config.getString(CONF_SECTION, null, "url"),
-            GITHUB_URL));
-    gitHubClientId = config.getString(CONF_SECTION, null, "clientId");
-    gitHubClientSecret = config.getString(CONF_SECTION, null, "clientSecret");
-    gitHubOAuthUrl = getUrl(gitHubUrl, LOGIN_OAUTH_AUTHORIZE);
-    gitHubOAuthAccessTokenUrl = getUrl(gitHubUrl, LOGIN_OAUTH_ACCESS_TOKEN);
-    logoutRedirectUrl = config.getString(CONF_SECTION, null, "logoutRedirectUrl");
+    gitHubOAuthUrl = gitHubUrl + GITHUB_OAUTH_AUTHORIZE;
+    gitHubOAuthAccessTokenUrl = gitHubUrl + GITHUB_OAUTH_ACCESS_TOKEN;
+    logoutRedirectUrl =
+        config.getString(CONF_SECTION, null, "logoutRedirectUrl");
     oAuthFinalRedirectUrl =
-        getUrl(config.getString("gerrit", null, "canonicalWebUrl"), OAUTH_FINAL);
+        trimTrailingSlash(canonicalWebUrl) + GERRIT_OAUTH_FINAL;
 
     enabled =
         config.getString("auth", null, "type").equalsIgnoreCase(
             AuthType.HTTP.toString());
     scopes = getScopes(config);
 
-    fileUpdateMaxRetryCount = config.getInt(CONF_SECTION, "fileUpdateMaxRetryCount", 3);
-    fileUpdateMaxRetryIntervalMsec = config.getInt(CONF_SECTION, "fileUpdateMaxRetryIntervalMsec", 3000);
+    fileUpdateMaxRetryCount =
+        config.getInt(CONF_SECTION, "fileUpdateMaxRetryCount", 3);
+    fileUpdateMaxRetryIntervalMsec =
+        config.getInt(CONF_SECTION, "fileUpdateMaxRetryIntervalMsec", 3000);
   }
 
   private Map<String, List<Scope>> getScopes(Config config) {
@@ -96,13 +117,13 @@
     return scopes;
   }
 
-  private String dropTrailingSlash(String url) {
-    return (url.endsWith("/") ? url.substring(0, url.length()-1):url);
+  private String trimTrailingSlash(String url) {
+    return CharMatcher.is('/').trimTrailingFrom(url);
   }
 
   private List<Scope> parseScopesString(String scopesString) {
     ArrayList<Scope> scopes = new ArrayList<OAuthProtocol.Scope>();
-    if(Strings.emptyToNull(scopesString) != null) {
+    if (Strings.emptyToNull(scopesString) != null) {
       String[] scopesStrings = scopesString.split(",");
       for (String scope : scopesStrings) {
         scopes.add(Enum.valueOf(Scope.class, scope));
@@ -112,11 +133,6 @@
     return scopes;
   }
 
-  private static String getUrl(String baseUrl, String path)
-      throws MalformedURLException {
-      return new URL(new URL(baseUrl), path).toExternalForm();
-  }
-
   public Scope[] getDefaultScopes() {
     if (scopes == null || scopes.get("scopes") == null) {
       return new Scope[0];
diff --git a/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/HttpSessionProvider.java b/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/HttpSessionProvider.java
index 649bd6d..79fdbc0 100644
--- a/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/HttpSessionProvider.java
+++ b/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/HttpSessionProvider.java
@@ -13,12 +13,12 @@
 // limitations under the License.
 package com.googlesource.gerrit.plugins.github.oauth;
 
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpSession;
-
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
 public abstract class HttpSessionProvider<T> implements ScopedProvider<T> {
 
   @Inject
diff --git a/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/IdentifiedUserGitHubLoginProvider.java b/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/IdentifiedUserGitHubLoginProvider.java
index bffb7a1..646b602 100644
--- a/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/IdentifiedUserGitHubLoginProvider.java
+++ b/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/IdentifiedUserGitHubLoginProvider.java
@@ -33,22 +33,20 @@
 @Singleton
 public class IdentifiedUserGitHubLoginProvider implements
     UserScopedProvider<GitHubLogin> {
-  private static final Logger log = LoggerFactory.getLogger(IdentifiedUserGitHubLoginProvider.class);
+  private static final Logger log = LoggerFactory
+      .getLogger(IdentifiedUserGitHubLoginProvider.class);
   private static final String EXTERNAL_ID_PREFIX = "external:"
       + OAuthWebFilter.GITHUB_EXT_ID;
 
   private final Provider<IdentifiedUser> userProvider;
-  private OAuthProtocol oauth;
   private GitHubOAuthConfig config;
   private AccountCache accountCache;
 
   @Inject
   public IdentifiedUserGitHubLoginProvider(
       final Provider<IdentifiedUser> identifiedUserProvider,
-      final OAuthProtocol oauth, final GitHubOAuthConfig config,
-      final AccountCache accountCache) {
+      final GitHubOAuthConfig config, final AccountCache accountCache) {
     this.userProvider = identifiedUserProvider;
-    this.oauth = oauth;
     this.config = config;
     this.accountCache = accountCache;
   }
@@ -65,15 +63,14 @@
     try {
       AccessToken accessToken = newAccessTokenFromUser(username);
       if (accessToken != null) {
-        GitHubLogin login = new GitHubLogin(oauth, config);
+        GitHubLogin login = new GitHubLogin(config);
         login.login(accessToken);
         return login;
       } else {
         return null;
       }
     } catch (IOException e) {
-      log.error("Cannot login to GitHub as '" + username
-          + "'", e);
+      log.error("Cannot login to GitHub as '" + username + "'", e);
       return null;
     }
   }
diff --git a/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/OAuthCache.java b/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/OAuthCache.java
index f751763..7cdc825 100644
--- a/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/OAuthCache.java
+++ b/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/OAuthCache.java
@@ -13,8 +13,6 @@
 // limitations under the License.
 package com.googlesource.gerrit.plugins.github.oauth;
 
-import java.util.concurrent.ExecutionException;
-
 import com.google.common.cache.CacheLoader;
 import com.google.common.cache.LoadingCache;
 import com.google.gerrit.server.cache.CacheModule;
@@ -22,8 +20,11 @@
 import com.google.inject.Module;
 import com.google.inject.Singleton;
 import com.google.inject.name.Named;
+
 import com.googlesource.gerrit.plugins.github.oauth.OAuthProtocol.AccessToken;
 
+import java.util.concurrent.ExecutionException;
+
 @Singleton
 public class OAuthCache {
   private static final String CACHE_NAME = "github_oauth";
diff --git a/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/OAuthFilter.java b/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/OAuthFilter.java
index adc5e58..978fd34 100644
--- a/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/OAuthFilter.java
+++ b/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/OAuthFilter.java
@@ -13,6 +13,16 @@
 // limitations under the License.
 package com.googlesource.gerrit.plugins.github.oauth;
 
+import com.google.common.collect.Sets;
+import com.google.gerrit.httpd.GitOverHttpServlet;
+import com.google.gerrit.httpd.XGerritAuth;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Singleton;
+
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.LoggerFactory;
+
 import java.io.IOException;
 import java.util.Arrays;
 import java.util.Set;
@@ -26,16 +36,6 @@
 import javax.servlet.ServletResponse;
 import javax.servlet.http.HttpServletRequest;
 
-import org.apache.commons.lang.StringUtils;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.collect.Sets;
-import com.google.gerrit.httpd.GitOverHttpServlet;
-import com.google.gerrit.httpd.XGerritAuth;
-import com.google.inject.Inject;
-import com.google.inject.Injector;
-import com.google.inject.Singleton;
-
 @Singleton
 public class OAuthFilter implements Filter {
   private static final org.slf4j.Logger log = LoggerFactory
diff --git a/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/OAuthGitFilter.java b/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/OAuthGitFilter.java
index cd8b32e..c0f3897 100644
--- a/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/OAuthGitFilter.java
+++ b/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/OAuthGitFilter.java
@@ -16,6 +16,26 @@
 import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN;
 import static javax.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;
 
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Strings;
+import com.google.common.collect.Iterators;
+import com.google.gerrit.httpd.XGerritAuth;
+import com.google.gerrit.server.account.AccountCache;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.Singleton;
+import com.googlesource.gerrit.plugins.github.oauth.OAuthProtocol.AccessToken;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.lang.StringUtils;
+import org.apache.http.HttpResponse;
+import org.apache.http.HttpStatus;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpPut;
+import org.apache.http.entity.ContentType;
+import org.apache.http.entity.StringEntity;
+import org.slf4j.LoggerFactory;
+
 import java.io.IOException;
 import java.io.UnsupportedEncodingException;
 import java.net.MalformedURLException;
@@ -37,24 +57,6 @@
 import javax.servlet.http.HttpServletRequestWrapper;
 import javax.servlet.http.HttpServletResponse;
 
-import org.apache.commons.codec.binary.Base64;
-import org.apache.commons.lang.StringUtils;
-import org.apache.http.HttpResponse;
-import org.apache.http.HttpStatus;
-import org.apache.http.client.methods.HttpPut;
-import org.apache.http.entity.ContentType;
-import org.apache.http.entity.StringEntity;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Objects;
-import com.google.common.base.Strings;
-import com.google.common.collect.Iterators;
-import com.google.gerrit.httpd.XGerritAuth;
-import com.google.gerrit.server.account.AccountCache;
-import com.google.inject.Inject;
-import com.google.inject.Singleton;
-import com.googlesource.gerrit.plugins.github.oauth.OAuthProtocol.AccessToken;
-
 @Singleton
 public class OAuthGitFilter implements Filter {
   private static final String GITHUB_X_OAUTH_BASIC = "x-oauth-basic";
@@ -67,7 +69,7 @@
 
   private final OAuthCache oauthCache;
   private final AccountCache accountCache;
-  private final GitHubHttpProvider httpClientProvider;
+  private final Provider<HttpClient> httpClientProvider;
   private final GitHubOAuthConfig config;
   private final XGerritAuth xGerritAuth;
   private ScopedProvider<GitHubLogin> ghLoginProvider;
@@ -114,7 +116,7 @@
 
   @Inject
   public OAuthGitFilter(OAuthCache oauthCache, AccountCache accountCache,
-      GitHubHttpProvider httpClientProvider, GitHubOAuthConfig config,
+      PooledHttpClientProvider httpClientProvider, GitHubOAuthConfig config,
       XGerritAuth xGerritAuth, GitHubLogin.Provider ghLoginProvider) {
     this.oauthCache = oauthCache;
     this.accountCache = accountCache;
@@ -150,7 +152,12 @@
         gerritPassword =
             generateRandomGerritPassword(username, httpRequest, httpResponse,
                 chain);
-        httpResponse.sendRedirect(getRequestPathWithQueryString(httpRequest));
+        if (Strings.isNullOrEmpty(gerritPassword)) {
+          httpResponse.sendError(SC_FORBIDDEN,
+              "Unable to generate Gerrit password for Git Basic-Auth");
+        } else {
+          httpResponse.sendRedirect(getRequestPathWithQueryString(httpRequest));
+        }
         return;
       }
 
@@ -275,7 +282,7 @@
   }
 
   static String encoding(HttpServletRequest req) {
-    return Objects.firstNonNull(req.getCharacterEncoding(), "UTF-8");
+    return MoreObjects.firstNonNull(req.getCharacterEncoding(), "UTF-8");
   }
 
   private String getHttpBasicAuthenticationHeader(final HttpServletRequest req)
diff --git a/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/OAuthProtocol.java b/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/OAuthProtocol.java
index 74712bd..70eb514 100644
--- a/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/OAuthProtocol.java
+++ b/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/OAuthProtocol.java
@@ -1,19 +1,13 @@
 package com.googlesource.gerrit.plugins.github.oauth;
 
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.UnsupportedEncodingException;
-import java.net.HttpURLConnection;
-import java.net.URLEncoder;
-import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-
-import javax.servlet.ServletRequest;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import com.google.common.base.Charsets;
+import com.google.common.base.Strings;
+import com.google.common.io.BaseEncoding;
+import com.google.common.io.CharStreams;
+import com.google.gson.Gson;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.Singleton;
 
 import org.apache.http.HttpResponse;
 import org.apache.http.NameValuePair;
@@ -25,12 +19,24 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Charsets;
-import com.google.common.base.Strings;
-import com.google.common.io.CharStreams;
-import com.google.gson.Gson;
-import com.google.inject.Inject;
-import com.google.inject.Singleton;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+import java.net.HttpURLConnection;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+
+import javax.servlet.ServletRequest;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
 import com.google.gerrit.extensions.auth.oauth.OAuthToken;
 import com.google.gerrit.extensions.auth.oauth.OAuthVerifier;
 
@@ -46,7 +52,8 @@
     REPO_STATUS("repo_status"),
     DELETE_REPO("delete_repo"),
     NOTIFICATIONS("notifications"),
-    GIST("gist");
+    GIST("gist"),
+    READ_ORG("read:org");
 
     private final String value;
 
@@ -59,12 +66,13 @@
     }
   }
   private static final String ME_SEPARATOR = ",";
-  private static final Logger LOG = LoggerFactory
+  private static final Logger log = LoggerFactory
       .getLogger(OAuthProtocol.class);
+  private static SecureRandom randomState = newRandomGenerator();
 
   private final GitHubOAuthConfig config;
-  private final HttpClient http;
   private final Gson gson;
+  private final Provider<HttpClient> httpProvider;
 
   public static class AccessToken {
     public String accessToken;
@@ -100,29 +108,13 @@
 
     @Override
     public int hashCode() {
-      final int prime = 31;
-      int result = 1;
-      result =
-          prime * result
-              + ((accessToken == null) ? 0 : accessToken.hashCode());
-      result =
-          prime * result + ((tokenType == null) ? 0 : tokenType.hashCode());
-      return result;
+      return Objects.hash(accessToken, tokenType, error, errorDescription,
+          errorUri);
     }
 
     @Override
     public boolean equals(Object obj) {
-      if (this == obj) return true;
-      if (obj == null) return false;
-      if (getClass() != obj.getClass()) return false;
-      AccessToken other = (AccessToken) obj;
-      if (accessToken == null) {
-        if (other.accessToken != null) return false;
-      } else if (!accessToken.equals(other.accessToken)) return false;
-      if (tokenType == null) {
-        if (other.tokenType != null) return false;
-      } else if (!tokenType.equals(other.tokenType)) return false;
-      return true;
+      return Objects.deepEquals(this, obj);
     }
 
     public boolean isError() {
@@ -143,16 +135,28 @@
   }
 
   @Inject
-  public OAuthProtocol(GitHubOAuthConfig config, GitHubHttpProvider httpClientProvider,
-      /* We need to explicitly tell Guice which Provider<> we need as this class may be
-         instantiated outside the standard Guice Module set-up (e.g. initial Servlet login
-         filter) */
+  public OAuthProtocol(GitHubOAuthConfig config,
+      PooledHttpClientProvider httpClientProvider,
+      /*
+       * We need to explicitly tell Guice which Provider<> we need as this class
+       * may be instantiated outside the standard Guice Module set-up (e.g.
+       * initial Servlet login filter)
+       */
       GsonProvider gsonProvider) {
     this.config = config;
-    this.http = httpClientProvider.get();
+    this.httpProvider = httpClientProvider;
     this.gson = gsonProvider.get();
   }
 
+  private static SecureRandom newRandomGenerator() {
+    try {
+      return SecureRandom.getInstance("SHA1PRNG");
+    } catch (NoSuchAlgorithmException e) {
+      throw new IllegalArgumentException(
+          "No SecureRandom available for GitHub authentication", e);
+    }
+  }
+
   public String getAuthorizationUrl(String scopesString, String state) {
     return config.gitHubOAuthUrl + "?client_id=" + config.gitHubClientId
         + getURLEncodedParameter("&scope=", scopesString)
@@ -160,13 +164,15 @@
         + getURLEncodedParameter("&state=", state);
   }
 
-  public void loginPhase1(HttpServletRequest request,
+  public String loginPhase1(HttpServletRequest request,
       HttpServletResponse response, Set<Scope> scopes) throws IOException {
-
     String scopesString = getScope(scopes);
-    LOG.debug("Initiating GitHub Login for ClientId=" + config.gitHubClientId + " Scopes=" + scopesString);
-    response.sendRedirect(getAuthorizationUrl(scopesString, 
-        me() + request.getRequestURI().toString()));
+    log.debug("Initiating GitHub Login for ClientId=" + config.gitHubClientId
+        + " Scopes=" + scopesString);
+    String state = newRandomState(request.getRequestURI().toString());
+    log.debug("Initiating GitHub Login for ClientId=" + config.gitHubClientId + " Scopes=" + scopesString);
+    response.sendRedirect(getAuthorizationUrl(scopesString, state));
+    return state;
   }
 
   public String getScope(Set<Scope> scopes) {
@@ -176,7 +182,7 @@
 
     StringBuilder out = new StringBuilder();
     for (Scope scope : scopes) {
-      if(out.length() > 0) {
+      if (out.length() > 0) {
         out.append(",");
       }
       out.append(scope.getValue());
@@ -197,16 +203,18 @@
     return Strings.emptyToNull(request.getParameter("code")) != null;
   }
 
-  public String me() {
-    return "" + hashCode() + ME_SEPARATOR;
+  public String newRandomState(String redirectUrl) {
+    byte[] stateBin = new byte[20]; // SHA-1 size
+    randomState.nextBytes(stateBin);
+    return BaseEncoding.base64Url().encode(stateBin) + ME_SEPARATOR + redirectUrl;
   }
 
   public static boolean isOAuthLogin(HttpServletRequest request) {
-    return request.getRequestURI().indexOf(GitHubOAuthConfig.OAUTH_LOGIN) >= 0;
+    return request.getRequestURI().indexOf(GitHubOAuthConfig.GERRIT_LOGIN) >= 0;
   }
 
   public static boolean isOAuthLogout(HttpServletRequest request) {
-    return request.getRequestURI().indexOf(GitHubOAuthConfig.OAUTH_LOGOUT) >= 0;
+    return request.getRequestURI().indexOf(GitHubOAuthConfig.GERRIT_LOGOUT) >= 0;
   }
 
   public static boolean isOAuthRequest(HttpServletRequest httpRequest) {
@@ -214,7 +222,12 @@
   }
 
   public AccessToken loginPhase2(HttpServletRequest request,
-      HttpServletResponse response) throws IOException {
+      HttpServletResponse response, String state) throws IOException {
+    String requestState = request.getParameter("state");
+    if (!Objects.equals(state, requestState)) {
+      throw new IOException("Invalid authentication state");
+    }
+
     return getAccessToken(new OAuthVerifier(request.getParameter("code")));
   }
 
@@ -227,13 +240,13 @@
     nvps.add(new BasicNameValuePair("code", code.getValue()));
     post.setEntity(new UrlEncodedFormEntity(nvps, Charsets.UTF_8));
 
-    HttpResponse postResponse = http.execute(post);
+    HttpResponse postResponse = httpProvider.get().execute(post);
     if (postResponse.getStatusLine().getStatusCode() != HttpURLConnection.HTTP_OK) {
-      LOG.error("POST " + config.gitHubOAuthAccessTokenUrl
+      log.error("POST " + config.gitHubOAuthAccessTokenUrl
           + " request for access token failed with status "
           + postResponse.getStatusLine());
       EntityUtils.consume(postResponse.getEntity());
-      return null;
+      throw new IOException("GitHub OAuth request failed");
     }
 
     InputStream content = postResponse.getEntity().getContent();
@@ -241,13 +254,12 @@
         CharStreams.toString(new InputStreamReader(content,
             StandardCharsets.UTF_8));
     AccessToken token = gson.fromJson(tokenJsonString, AccessToken.class);
-    token.setRaw(tokenJsonString);
     if (token.isError()) {
-      LOG.error("POST " + config.gitHubOAuthAccessTokenUrl
+      log.error("POST " + config.gitHubOAuthAccessTokenUrl
           + " returned an error token: " + token);
       throw new IOException("Invalid GitHub OAuth token");
     }
-    
+
     return token;
   }
 
@@ -256,15 +268,14 @@
       return Strings.isNullOrEmpty(url) ? 
           "" : (prefix + URLEncoder.encode(url,"UTF-8"));
     } catch (UnsupportedEncodingException e) {
-      // UTF-8 is hardcoded, cannot fail
-      return null;
+      throw new IllegalStateException("Cannot find UTF-8 encoding", e);
     }
   }
 
   public static String getTargetUrl(ServletRequest request) {
     int meEnd = state(request).indexOf(ME_SEPARATOR);
     if (meEnd > 0) {
-      return state(request).substring(meEnd+1);
+      return state(request).substring(meEnd + 1);
     } else {
       return "";
     }
diff --git a/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/OAuthWebFilter.java b/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/OAuthWebFilter.java
index a8823a9..6929d16 100644
--- a/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/OAuthWebFilter.java
+++ b/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/OAuthWebFilter.java
@@ -14,6 +14,17 @@
 package com.googlesource.gerrit.plugins.github.oauth;
 
 
+import com.google.gerrit.server.config.SitePaths;
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+
+import org.apache.commons.lang.StringUtils;
+import org.eclipse.jgit.errors.ConfigInvalidException;
+import org.eclipse.jgit.storage.file.FileBasedConfig;
+import org.eclipse.jgit.util.FS;
+import org.kohsuke.github.GHMyself;
+import org.slf4j.LoggerFactory;
+
 import java.io.IOException;
 import java.text.SimpleDateFormat;
 import java.util.Date;
@@ -31,17 +42,6 @@
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpSession;
 
-import org.apache.commons.lang.StringUtils;
-import org.eclipse.jgit.errors.ConfigInvalidException;
-import org.eclipse.jgit.storage.file.FileBasedConfig;
-import org.eclipse.jgit.util.FS;
-import org.kohsuke.github.GHMyself;
-import org.slf4j.LoggerFactory;
-
-import com.google.gerrit.server.config.SitePaths;
-import com.google.inject.Inject;
-import com.google.inject.Singleton;
-
 @Singleton
 public class OAuthWebFilter implements Filter {
   private static final org.slf4j.Logger log = LoggerFactory
@@ -51,16 +51,20 @@
 
   private final GitHubOAuthConfig config;
   private final Random retryRandom = new Random(System.currentTimeMillis());
-  private SitePaths sites;
-  private ScopedProvider<GitHubLogin> loginProvider;
+  private final SitePaths sites;
+  private final ScopedProvider<GitHubLogin> loginProvider;
+  private final OAuthProtocol oauth;
 
   @Inject
-  public OAuthWebFilter(GitHubOAuthConfig config, SitePaths sites,
+  public OAuthWebFilter(GitHubOAuthConfig config, 
+      SitePaths sites,
+      OAuthProtocol oauth,
   // We need to explicitly tell Guice the correct implementation
   // as this filter is instantiated with a standard Gerrit WebModule
       GitHubLogin.Provider loginProvider) {
     this.config = config;
     this.sites = sites;
+    this.oauth = oauth;
     this.loginProvider = loginProvider;
   }
 
@@ -120,12 +124,12 @@
 
   private void login(ServletRequest request, HttpServletRequest httpRequest,
       HttpServletResponse httpResponse, GitHubLogin ghLogin) throws IOException {
-    if (ghLogin.login(httpRequest, httpResponse)) {
+    if (ghLogin.login(httpRequest, httpResponse, oauth)) {
       GHMyself myself = ghLogin.getMyself();
       String user = myself.getLogin();
 
-      updateSecureConfigWithRetry(ghLogin.hub.getMyOrganizations().keySet(),
-          user, ghLogin.token.accessToken);
+      updateSecureConfigWithRetry(ghLogin.getHub().getMyOrganizations().keySet(),
+          user, ghLogin.getToken().accessToken);
     }
   }
 
diff --git a/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/PooledHttpClientProvider.java b/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/PooledHttpClientProvider.java
new file mode 100644
index 0000000..0263877
--- /dev/null
+++ b/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/PooledHttpClientProvider.java
@@ -0,0 +1,75 @@
+// Copyright (C) 2013 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.googlesource.gerrit.plugins.github.oauth;
+
+import com.google.common.base.Strings;
+import com.google.gerrit.httpd.ProxyProperties;
+import com.google.gerrit.server.config.GerritServerConfig;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+
+import org.apache.http.HttpHost;
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.http.client.CredentialsProvider;
+import org.apache.http.client.HttpClient;
+import org.apache.http.impl.client.BasicCredentialsProvider;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.impl.client.ProxyAuthenticationStrategy;
+import org.eclipse.jgit.lib.Config;
+
+import java.net.URL;
+
+public class PooledHttpClientProvider implements Provider<HttpClient> {
+  private final int maxTotalConnection;
+  private final int maxConnectionPerRoute;
+  private final ProxyProperties proxy;
+
+  @Inject
+  PooledHttpClientProvider(@GerritServerConfig Config config,
+      ProxyProperties proxyProperties) {
+    this.proxy = proxyProperties;
+    maxConnectionPerRoute = config.getInt("http", null,
+        "pooledMaxConnectionsPerRoute", 16);
+    maxTotalConnection = config.getInt("http", null,
+        "pooledMaxTotalConnections", 32);
+  }
+
+  @Override
+  public HttpClient get() {
+    HttpClientBuilder builder = HttpClientBuilder
+        .create()
+        .setMaxConnPerRoute(maxConnectionPerRoute)
+        .setMaxConnTotal(maxTotalConnection);
+
+    if (proxy.getProxyUrl() != null) {
+      URL url = proxy.getProxyUrl();
+      builder.setProxy(new HttpHost(url.getHost(), url.getPort()));
+      if (!Strings.isNullOrEmpty(proxy.getUsername())
+          && !Strings.isNullOrEmpty(proxy.getPassword())) {
+        UsernamePasswordCredentials creds = new UsernamePasswordCredentials(
+            proxy.getUsername(), proxy.getPassword());
+        CredentialsProvider credsProvider = new BasicCredentialsProvider();
+        credsProvider.setCredentials(new AuthScope(url.getHost(),
+            url.getPort()), creds);
+        builder.setDefaultCredentialsProvider(credsProvider);
+        builder.setProxyAuthenticationStrategy(
+            new ProxyAuthenticationStrategy());
+      }
+    }
+
+    return builder.build();
+  }
+}
diff --git a/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/ScopedProvider.java b/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/ScopedProvider.java
index 8ebde44..9cc4f3a 100644
--- a/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/ScopedProvider.java
+++ b/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/ScopedProvider.java
@@ -13,10 +13,10 @@
 // limitations under the License.
 package com.googlesource.gerrit.plugins.github.oauth;
 
-import javax.servlet.http.HttpServletRequest;
-
 import com.google.inject.Provider;
 
+import javax.servlet.http.HttpServletRequest;
+
 
 public interface ScopedProvider<T> extends Provider<T>{
   T get(HttpServletRequest request);
diff --git a/github-plugin/pom.xml b/github-plugin/pom.xml
index 2a923b0..e8a1daa 100644
--- a/github-plugin/pom.xml
+++ b/github-plugin/pom.xml
@@ -20,7 +20,7 @@
   <parent>
     <artifactId>github-parent</artifactId>
     <groupId>com.googlesource.gerrit.plugins.github</groupId>
-    <version>2.10.3</version>
+    <version>2.11</version>
   </parent>
 
   <artifactId>github-plugin</artifactId>
@@ -136,7 +136,7 @@
     <dependency>
       <groupId>org.apache.httpcomponents</groupId>
       <artifactId>httpclient</artifactId>
-      <version>4.0</version>
+      <version>4.4</version>
     </dependency>
     <dependency>
       <groupId>javax.mail</groupId>
diff --git a/github-plugin/src/main/java/com/google/gerrit/server/account/AccountImporter.java b/github-plugin/src/main/java/com/google/gerrit/server/account/AccountImporter.java
index 44322e5..57cd1a3 100644
--- a/github-plugin/src/main/java/com/google/gerrit/server/account/AccountImporter.java
+++ b/github-plugin/src/main/java/com/google/gerrit/server/account/AccountImporter.java
@@ -13,12 +13,8 @@
 // limitations under the License.
 package com.google.gerrit.server.account;
 
-import java.io.IOException;
-import java.util.Arrays;
-
-import org.apache.http.HttpStatus;
-
-import com.google.common.base.Objects;
+import com.google.common.base.MoreObjects;
+import com.google.gerrit.extensions.common.AccountInfo;
 import com.google.gerrit.extensions.restapi.BadRequestException;
 import com.google.gerrit.extensions.restapi.ResourceConflictException;
 import com.google.gerrit.extensions.restapi.Response;
@@ -33,6 +29,11 @@
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
+import org.apache.http.HttpStatus;
+
+import java.io.IOException;
+import java.util.Arrays;
+
 public class AccountImporter {
   private final Factory createAccountFactory;
   private final Provider<ReviewDb> schema;
@@ -52,12 +53,12 @@
     CreateAccount.Input accountInput = new CreateAccount.Input();
     accountInput.email = email;
     accountInput.username = login;
-    accountInput.name = Objects.firstNonNull(name, login);
+    accountInput.name = MoreObjects.firstNonNull(name, login);
     Response<AccountInfo> accountResponse =
         (Response<AccountInfo>) createAccount.apply(TopLevelResource.INSTANCE,
             accountInput);
     if (accountResponse.statusCode() == HttpStatus.SC_CREATED) {
-      Id accountId = accountResponse.value()._id;
+      Id accountId = new Account.Id(accountResponse.value()._accountId);
       db.accountExternalIds().insert(
           Arrays
               .asList(new AccountExternalId(accountId,
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/GitHubConfig.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/GitHubConfig.java
index ff00469..17c3b9e 100644
--- a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/GitHubConfig.java
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/GitHubConfig.java
@@ -13,21 +13,23 @@
 // limitations under the License.
 package com.googlesource.gerrit.plugins.github;
 
-import java.io.File;
-import java.net.MalformedURLException;
-import java.util.HashMap;
-
-import org.eclipse.jgit.lib.Config;
-
-import com.google.common.base.Objects;
+import com.google.common.base.MoreObjects;
 import com.google.common.collect.Maps;
 import com.google.gerrit.server.config.AllProjectsNameProvider;
+import com.google.gerrit.server.config.AuthConfig;
+import com.google.gerrit.server.config.CanonicalWebUrl;
 import com.google.gerrit.server.config.GerritServerConfig;
 import com.google.gerrit.server.config.SitePaths;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
 import com.googlesource.gerrit.plugins.github.oauth.GitHubOAuthConfig;
 
+import org.eclipse.jgit.lib.Config;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.util.HashMap;
+
 @Singleton
 public class GitHubConfig extends GitHubOAuthConfig {
 
@@ -68,9 +70,13 @@
 
 
   @Inject
-  public GitHubConfig(@GerritServerConfig Config config, final SitePaths site, AllProjectsNameProvider allProjectsNameProvider)
+  public GitHubConfig(@GerritServerConfig Config config, 
+      final SitePaths site, 
+      AllProjectsNameProvider allProjectsNameProvider,
+      @CanonicalWebUrl String canonicalWebUrl, 
+      AuthConfig authConfig)
       throws MalformedURLException {
-    super(config);
+    super(config, canonicalWebUrl, authConfig);
     String[] wizardFlows =
         config.getStringList(CONF_SECTION, null, CONF_WIZARD_FLOW);
     for (String fromTo : wizardFlows) {
@@ -123,7 +129,7 @@
   }
 
   public String getBaseProject(boolean isPrivateProject) {
-    return Objects.firstNonNull(isPrivateProject ? privateBaseProject
+    return MoreObjects.firstNonNull(isPrivateProject ? privateBaseProject
         : publicBaseProject, allProjectsName);
   }
 }
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/GitHubOAuthServiceProvider.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/GitHubOAuthServiceProvider.java
index 575ea11..0a617fc 100644
--- a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/GitHubOAuthServiceProvider.java
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/GitHubOAuthServiceProvider.java
@@ -22,7 +22,6 @@
 import org.slf4j.LoggerFactory;
 
 import com.google.common.collect.Sets;
-import com.google.gerrit.extensions.annotations.PluginName;
 import com.google.gerrit.extensions.auth.oauth.OAuthServiceProvider;
 import com.google.gerrit.extensions.auth.oauth.OAuthToken;
 import com.google.gerrit.extensions.auth.oauth.OAuthUserInfo;
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/GitHubTopMenu.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/GitHubTopMenu.java
index 4b97fad..20696ee 100644
--- a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/GitHubTopMenu.java
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/GitHubTopMenu.java
@@ -13,10 +13,6 @@
 // limitations under the License.
 package com.googlesource.gerrit.plugins.github;
 
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
 import com.google.gerrit.extensions.annotations.Listen;
 import com.google.gerrit.extensions.annotations.PluginName;
 import com.google.gerrit.extensions.webui.TopMenu;
@@ -28,6 +24,10 @@
 import com.google.inject.Provider;
 import com.google.inject.Singleton;
 
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
 @Listen
 @Singleton
 public class GitHubTopMenu implements TopMenu {
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/GitHubURL.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/GitHubURL.java
index 44875e4..a53c76e 100644
--- a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/GitHubURL.java
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/GitHubURL.java
@@ -13,13 +13,13 @@
 // limitations under the License.
 package com.googlesource.gerrit.plugins.github;
 
+import com.google.inject.BindingAnnotation;
+
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
 
-import com.google.inject.BindingAnnotation;
-
 @Target({ElementType.PARAMETER, ElementType.FIELD})
 @Retention(RetentionPolicy.RUNTIME)
 @BindingAnnotation
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/GuiceHttpModule.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/GuiceHttpModule.java
index 00f8201..97bc6be 100644
--- a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/GuiceHttpModule.java
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/GuiceHttpModule.java
@@ -23,26 +23,26 @@
 import com.google.inject.name.Names;
 import com.google.inject.servlet.ServletModule;
 import com.googlesource.gerrit.plugins.github.filters.GitHubOAuthFilter;
-import com.googlesource.gerrit.plugins.github.oauth.GitHubHttpProvider;
-import com.googlesource.gerrit.plugins.github.oauth.GitHubLogin;
-import com.googlesource.gerrit.plugins.github.oauth.ScopedProvider;
-import com.googlesource.gerrit.plugins.github.replication.RemoteSiteUser;
-import com.googlesource.gerrit.plugins.github.velocity.PluginVelocityRuntimeProvider;
-import com.googlesource.gerrit.plugins.github.velocity.VelocityStaticServlet;
-import com.googlesource.gerrit.plugins.github.velocity.VelocityViewServlet;
-import com.googlesource.gerrit.plugins.github.wizard.VelocityControllerServlet;
 import com.googlesource.gerrit.plugins.github.git.CreateProjectStep;
 import com.googlesource.gerrit.plugins.github.git.GitCloneStep;
 import com.googlesource.gerrit.plugins.github.git.GitHubRepository;
 import com.googlesource.gerrit.plugins.github.git.GitImporter;
 import com.googlesource.gerrit.plugins.github.git.PullRequestImportJob;
 import com.googlesource.gerrit.plugins.github.git.ReplicateProjectStep;
+import com.googlesource.gerrit.plugins.github.oauth.GitHubLogin;
+import com.googlesource.gerrit.plugins.github.oauth.PooledHttpClientProvider;
+import com.googlesource.gerrit.plugins.github.oauth.ScopedProvider;
+import com.googlesource.gerrit.plugins.github.replication.RemoteSiteUser;
+import com.googlesource.gerrit.plugins.github.velocity.PluginVelocityRuntimeProvider;
+import com.googlesource.gerrit.plugins.github.velocity.VelocityStaticServlet;
+import com.googlesource.gerrit.plugins.github.velocity.VelocityViewServlet;
+import com.googlesource.gerrit.plugins.github.wizard.VelocityControllerServlet;
 
 public class GuiceHttpModule extends ServletModule {
 
   @Override
   protected void configureServlets() {
-    bind(HttpClient.class).toProvider(GitHubHttpProvider.class);
+    bind(HttpClient.class).toProvider(PooledHttpClientProvider.class);
 
     bind(new TypeLiteral<ScopedProvider<GitHubLogin>>() {}).to(GitHubLogin.Provider.class);
     bind(new TypeLiteral<ScopedProvider<GitImporter>>() {}).to(GitImporter.Provider.class);
@@ -72,9 +72,9 @@
 
     serve("*.css", "*.js", "*.png", "*.jpg", "*.woff", "*.gif", "*.ttf").with(
         VelocityStaticServlet.class);
-    serve("*.html").with(VelocityViewServlet.class);
     serve("*.gh").with(VelocityControllerServlet.class);
 
+    serve("/static/*").with(VelocityViewServlet.class);
     filter("*").through(GitHubOAuthFilter.class);
   }
 }
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/GuiceModule.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/GuiceModule.java
index 21926c4..2b37e5e 100644
--- a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/GuiceModule.java
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/GuiceModule.java
@@ -20,6 +20,7 @@
 import com.google.inject.AbstractModule;
 import com.google.inject.TypeLiteral;
 import com.google.inject.assistedinject.FactoryModuleBuilder;
+
 import com.googlesource.gerrit.plugins.github.group.GitHubGroupBackend;
 import com.googlesource.gerrit.plugins.github.group.GitHubGroupMembership;
 import com.googlesource.gerrit.plugins.github.group.GitHubGroupsCache;
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/InitGitHub.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/InitGitHub.java
index cb48f34..907f73d 100644
--- a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/InitGitHub.java
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/InitGitHub.java
@@ -13,16 +13,25 @@
 // limitations under the License.
 package com.googlesource.gerrit.plugins.github;
 
-import com.google.gerrit.pgm.init.InitStep;
-import com.google.gerrit.pgm.init.Section;
-import com.google.gerrit.pgm.util.ConsoleUI;
+import java.net.URISyntaxException;
+
+import com.google.gerrit.pgm.init.api.ConsoleUI;
+import com.google.gerrit.pgm.init.api.InitStep;
+import com.google.gerrit.pgm.init.api.InitUtil;
+import com.google.gerrit.pgm.init.api.Section;
 import com.google.inject.Inject;
 
 public class InitGitHub implements InitStep {
+  private static final String GITHUB_URL = "https://github.com";
+  private static final String GITHUB_API_URL = "https://api.github.com";
+  private static final String GITHUB_REGISTER_APPLICATION_PATH = "/settings/applications/new";
+  private static final String GERRIT_OAUTH_CALLBACK_PATH = "oauth";
+  
   private final ConsoleUI ui;
   private final Section auth;
   private final Section httpd;
   private final Section github;
+  private final Section gerrit;
   
   public enum OAuthType {
     /* Legacy Gerrit/HTTP authentication for GitHub through HTTP Header enrichment */
@@ -38,21 +47,30 @@
     this.github = sections.get("github", null);
     this.httpd = sections.get("httpd", null);
     this.auth = sections.get("auth", null);
+    this.gerrit = sections.get("gerrit", null);
   }
 
   @Override
   public void run() throws Exception {
     ui.header("GitHub Integration");
 
-    github.string("GitHub URL", "url", "https://github.com");
+    github.string("GitHub URL", "url", GITHUB_URL);
+    github.string("GitHub API URL", "apiUrl", GITHUB_API_URL);
+    ui.message("\nNOTE: You might need to configure a proxy using http.proxy"
+        + " if you run Gerrit behind a firewall.\n");
 
-    boolean gitHubAuth = ui.yesno(true, "Use GitHub for Gerrit login ?");
-    if(gitHubAuth) {
-      configureAuth();
-    }
-  }
+    String gerritUrl = getAssumedCanonicalWebUrl();
+    ui.header("GitHub OAuth registration and credentials");
+    ui.message(
+        "Register Gerrit as GitHub application on:\n" +
+        "%s%s\n\n",
+        github.get("url"), GITHUB_REGISTER_APPLICATION_PATH);
+    ui.message("Settings (assumed Gerrit URL: %s)\n", gerritUrl);
+    ui.message("* Application name: Gerrit Code Review\n");
+    ui.message("* Homepage URL: %s\n", gerritUrl);
+    ui.message("* Authorization callback URL: %s%s\n\n", gerritUrl, GERRIT_OAUTH_CALLBACK_PATH);
+    ui.message("After registration is complete, enter the generated OAuth credentials:\n");
 
-  private void configureAuth() {
     github.string("GitHub Client ID", "clientId", null);
     github.passwordForKey("GitHub Client Secret", "clientSecret");
     
@@ -61,12 +79,33 @@
       auth.string("HTTP Authentication Header", "httpHeader", "GITHUB_USER");
       httpd.set("filterClass",
           "com.googlesource.gerrit.plugins.github.oauth.OAuthFilter");
+      auth.set("httpExternalIdHeader", "GITHUB_OAUTH_TOKEN");
+      auth.set("loginUrl","/login");
+      auth.set("loginText", "Sign-in with GitHub");
+      auth.set("registerPageUrl", "/#/register");
     } else {
       httpd.unset("filterClass");
       httpd.unset("httpHeader");
     }
   }
 
+  private String getAssumedCanonicalWebUrl() {
+    String url = gerrit.get("canonicalWebUrl");
+    if (url != null) {
+      return url;
+    }
+
+    String httpListen = httpd.get("listenUrl");
+    if (httpListen != null) {
+      try {
+        return InitUtil.toURI(httpListen).toString();
+      } catch (URISyntaxException e) {
+      }
+    }
+
+    return String.format("http://%s:8080/", InitUtil.hostname());
+  }
+
   @Override
   public void postRun() throws Exception {
   }
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/OnStartStop.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/OnStartStop.java
index 26512fd..ee55271 100644
--- a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/OnStartStop.java
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/OnStartStop.java
@@ -14,13 +14,13 @@
 
 package com.googlesource.gerrit.plugins.github;
 
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
 import com.google.gerrit.extensions.events.LifecycleListener;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 @Singleton
 public class OnStartStop implements LifecycleListener {
   private static final Logger LOG = LoggerFactory.getLogger(OnStartStop.class);
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/filters/GitHubOAuthFilter.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/filters/GitHubOAuthFilter.java
index 0c27d0f..59ceb46 100644
--- a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/filters/GitHubOAuthFilter.java
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/filters/GitHubOAuthFilter.java
@@ -13,6 +13,18 @@
 // limitations under the License.
 package com.googlesource.gerrit.plugins.github.filters;
 
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+
+import com.googlesource.gerrit.plugins.github.oauth.GitHubLogin;
+import com.googlesource.gerrit.plugins.github.oauth.GitHubOAuthConfig;
+import com.googlesource.gerrit.plugins.github.oauth.OAuthProtocol;
+import com.googlesource.gerrit.plugins.github.oauth.OAuthProtocol.Scope;
+import com.googlesource.gerrit.plugins.github.oauth.ScopedProvider;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import java.io.IOException;
 
 import javax.servlet.Filter;
@@ -22,16 +34,7 @@
 import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
 import javax.servlet.http.HttpServletRequest;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.inject.Inject;
-import com.google.inject.Singleton;
-import com.googlesource.gerrit.plugins.github.oauth.GitHubLogin;
-import com.googlesource.gerrit.plugins.github.oauth.GitHubOAuthConfig;
-import com.googlesource.gerrit.plugins.github.oauth.OAuthProtocol.Scope;
-import com.googlesource.gerrit.plugins.github.oauth.ScopedProvider;
+import javax.servlet.http.HttpServletResponse;
 
 @Singleton
 public class GitHubOAuthFilter implements Filter {
@@ -39,12 +42,14 @@
 
   private final ScopedProvider<GitHubLogin> loginProvider;
   private final Scope[] authScopes;
+  private final OAuthProtocol oauth;
 
   @Inject
-  public GitHubOAuthFilter(final ScopedProvider<GitHubLogin> loginProvider,
-      final GitHubOAuthConfig githubOAuthConfig) {
+  public GitHubOAuthFilter(ScopedProvider<GitHubLogin> loginProvider,
+      GitHubOAuthConfig githubOAuthConfig, OAuthProtocol oauth) {
     this.loginProvider = loginProvider;
     this.authScopes = githubOAuthConfig.getDefaultScopes();
+    this.oauth = oauth;
   }
 
   @Override
@@ -57,7 +62,8 @@
     GitHubLogin hubLogin = loginProvider.get((HttpServletRequest) request);
     LOG.debug("GitHub login: " + hubLogin);
     if (!hubLogin.isLoggedIn()) {
-      hubLogin.login(request, response, authScopes);
+      hubLogin.login((HttpServletRequest) request,
+          (HttpServletResponse) response, oauth, authScopes);
       return;
     } else {
       chain.doFilter(request, response);
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/AbstractCloneJob.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/AbstractCloneJob.java
index 86e60b8..16fefc9 100644
--- a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/AbstractCloneJob.java
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/AbstractCloneJob.java
@@ -13,11 +13,11 @@
 // limitations under the License.
 package com.googlesource.gerrit.plugins.github.git;
 
+import com.google.inject.ProvisionException;
+
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.inject.ProvisionException;
-
 public class AbstractCloneJob {
   private static final Logger LOG = LoggerFactory.getLogger(AbstractCloneJob.class);
 
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/BatchImporter.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/BatchImporter.java
index e028979..92cd9c9 100644
--- a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/BatchImporter.java
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/BatchImporter.java
@@ -13,11 +13,11 @@
 // limitations under the License.
 package com.googlesource.gerrit.plugins.github.git;
 
+import com.google.gerrit.server.IdentifiedUser;
+
 import java.util.Collection;
 import java.util.concurrent.ConcurrentHashMap;
 
-import com.google.gerrit.server.IdentifiedUser;
-
 public class BatchImporter {
 
   private final ConcurrentHashMap<Integer, GitJob> jobs = new ConcurrentHashMap<Integer, GitJob>();
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/CreateProjectStep.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/CreateProjectStep.java
index 8202be5..c409da7 100644
--- a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/CreateProjectStep.java
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/CreateProjectStep.java
@@ -13,17 +13,13 @@
 // limitations under the License.
 package com.googlesource.gerrit.plugins.github.git;
 
-import org.eclipse.jgit.lib.ProgressMonitor;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
 import com.google.gerrit.common.data.AccessSection;
 import com.google.gerrit.common.data.GroupDescription;
 import com.google.gerrit.common.data.GroupReference;
 import com.google.gerrit.common.data.Permission;
 import com.google.gerrit.common.data.PermissionRule;
-import com.google.gerrit.extensions.common.InheritableBoolean;
-import com.google.gerrit.extensions.common.SubmitType;
+import com.google.gerrit.extensions.client.InheritableBoolean;
+import com.google.gerrit.extensions.client.SubmitType;
 import com.google.gerrit.reviewdb.client.AccountGroup;
 import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.reviewdb.client.Project.NameKey;
@@ -34,9 +30,14 @@
 import com.google.gerrit.server.project.ProjectCache;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
+
 import com.googlesource.gerrit.plugins.github.GitHubConfig;
 import com.googlesource.gerrit.plugins.github.GitHubURL;
 
+import org.eclipse.jgit.lib.ProgressMonitor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 public class CreateProjectStep extends ImportStep {
   private static final Logger LOG = LoggerFactory.getLogger(CreateProjectStep.class);
   private static final String CODE_REVIEW_REFS = "refs/for/refs/*";
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/GitCloneStep.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/GitCloneStep.java
index 464f252..4b6cfb7 100644
--- a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/GitCloneStep.java
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/GitCloneStep.java
@@ -13,8 +13,13 @@
 // limitations under the License.
 package com.googlesource.gerrit.plugins.github.git;
 
-import java.io.File;
-import java.io.IOException;
+import com.google.gerrit.server.account.GroupBackend;
+import com.google.gerrit.server.git.MetaDataUpdate;
+import com.google.gerrit.server.project.ProjectCache;
+import com.google.inject.Inject;
+import com.google.inject.assistedinject.Assisted;
+
+import com.googlesource.gerrit.plugins.github.GitHubConfig;
 
 import org.apache.commons.io.FileUtils;
 import org.eclipse.jgit.api.CloneCommand;
@@ -22,12 +27,8 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.gerrit.server.account.GroupBackend;
-import com.google.gerrit.server.git.MetaDataUpdate;
-import com.google.gerrit.server.project.ProjectCache;
-import com.google.inject.Inject;
-import com.google.inject.assistedinject.Assisted;
-import com.googlesource.gerrit.plugins.github.GitHubConfig;
+import java.io.File;
+import java.io.IOException;
 
 public class GitCloneStep extends ImportStep {
   private static final Logger LOG = LoggerFactory.getLogger(GitImporter.class);
@@ -79,6 +80,7 @@
   public void doImport(ProgressMonitor progress) throws GitCloneFailedException,
       GitDestinationAlreadyExistsException, GitDestinationNotWritableException {
     CloneCommand clone = new CloneCommand();
+    clone.setCredentialsProvider(getRepository().getCredentialsProvider());
     String sourceUri = getSourceUri();
     clone.setURI(sourceUri);
     clone.setBare(true);
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/GitHubRepository.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/GitHubRepository.java
index a677958..c5cf07a 100644
--- a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/GitHubRepository.java
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/GitHubRepository.java
@@ -13,18 +13,24 @@
 // limitations under the License.
 package com.googlesource.gerrit.plugins.github.git;
 
-import java.io.IOException;
-
-import lombok.experimental.Delegate;
-
-import org.kohsuke.github.GHRepository;
-
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
+
 import com.googlesource.gerrit.plugins.github.GitHubURL;
 import com.googlesource.gerrit.plugins.github.oauth.GitHubLogin;
 import com.googlesource.gerrit.plugins.github.oauth.ScopedProvider;
 
+import org.eclipse.jgit.errors.UnsupportedCredentialItem;
+import org.eclipse.jgit.transport.CredentialItem;
+import org.eclipse.jgit.transport.CredentialsProvider;
+import org.eclipse.jgit.transport.URIish;
+import org.kohsuke.github.GHRepository;
+import org.kohsuke.github.GitHub;
+
+import java.io.IOException;
+
+import lombok.experimental.Delegate;
+
 public class GitHubRepository extends GHRepository {
   public interface Factory {
     GitHubRepository create(@Assisted("organisation") String organisation,
@@ -34,15 +40,15 @@
 
   private final String organisation;
   private final String repository;
-  private final GitHubLogin ghLogin;
   private final String cloneUrl;
+  private final String username;
+  private final String password;
 
   @Delegate
   private GHRepository ghRepository;
 
   public String getCloneUrl() {
-    return cloneUrl.replace("://", "://" + ghLogin.getMyself().getLogin() + ":"
-        + ghLogin.getToken().accessToken + "@");
+    return cloneUrl.replace("://", "://" + username + "@");
   }
 
   public String getOrganisation() {
@@ -61,8 +67,63 @@
     this.cloneUrl = gitHubUrl + "/" + organisation + "/" + repository + ".git";
     this.organisation = organisation;
     this.repository = repository;
-    this.ghLogin = ghLoginProvider.get();
+    GitHubLogin ghLogin = ghLoginProvider.get();
+    GitHub gh = ghLogin.getHub();
+    this.username = ghLogin.getMyself().getLogin();
+    this.password = ghLogin.getToken().accessToken;
     this.ghRepository =
-        ghLogin.getHub().getRepository(organisation + "/" + repository);
+        gh.getRepository(organisation + "/" + repository);
+  }
+
+  public CredentialsProvider getCredentialsProvider() {
+    return new CredentialsProvider() {
+
+      @Override
+      public boolean supports(CredentialItem... items) {
+        for (CredentialItem i : items) {
+          if (i instanceof CredentialItem.Username) {
+            continue;
+          } else if (i instanceof CredentialItem.Password) {
+            continue;
+          } else {
+            return false;
+          }
+        }
+        return true;
+      }
+
+      @Override
+      public boolean isInteractive() {
+        return false;
+      }
+
+      @Override
+      public boolean get(URIish uri, CredentialItem... items)
+          throws UnsupportedCredentialItem {
+        String username = uri.getUser();
+        if (username == null) {
+          username = GitHubRepository.this.username;
+        }
+        if (username == null) {
+          return false;
+        }
+
+        String password = GitHubRepository.this.password;
+        if (password == null) {
+          return false;
+        }
+
+        for (CredentialItem i : items) {
+          if (i instanceof CredentialItem.Username) {
+            ((CredentialItem.Username) i).setValue(username);
+          } else if (i instanceof CredentialItem.Password) {
+            ((CredentialItem.Password) i).setValue(password.toCharArray());
+          } else {
+            throw new UnsupportedCredentialItem(uri, i.getPromptText());
+          }
+        }
+        return true;
+      }
+    };
   }
 }
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/GitHubUser.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/GitHubUser.java
index 0cfdd5a..f929e62 100644
--- a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/GitHubUser.java
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/GitHubUser.java
@@ -14,13 +14,13 @@
 
 package com.googlesource.gerrit.plugins.github.git;
 
-import java.io.IOException;
+import com.google.common.base.Optional;
+import com.google.common.base.Strings;
 
 import org.kohsuke.github.GHUser;
 import org.kohsuke.github.GitUser;
 
-import com.google.common.base.Optional;
-import com.google.common.base.Strings;
+import java.io.IOException;
 
 import lombok.Getter;
 
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/GitImportJob.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/GitImportJob.java
index 0535539..fac0579 100644
--- a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/GitImportJob.java
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/GitImportJob.java
@@ -13,10 +13,10 @@
 // limitations under the License.
 package com.googlesource.gerrit.plugins.github.git;
 
-import org.eclipse.jgit.lib.ProgressMonitor;
-
 import com.googlesource.gerrit.plugins.github.git.GitJobStatus.Code;
 
+import org.eclipse.jgit.lib.ProgressMonitor;
+
 public class GitImportJob extends AbstractCloneJob implements Runnable,
     ProgressMonitor, GitJob {
   private int currTask;
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/GitImporter.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/GitImporter.java
index 4c192a7..6d2fb3a 100644
--- a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/GitImporter.java
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/GitImporter.java
@@ -13,14 +13,15 @@
 // limitations under the License.
 package com.googlesource.gerrit.plugins.github.git;
 
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
+
 import com.googlesource.gerrit.plugins.github.oauth.HttpSessionProvider;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 public class GitImporter extends BatchImporter {
 
   @Singleton
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/GitJobStatus.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/GitJobStatus.java
index 0401409..1ae4f30 100644
--- a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/GitJobStatus.java
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/GitJobStatus.java
@@ -13,11 +13,11 @@
 // limitations under the License.
 package com.googlesource.gerrit.plugins.github.git;
 
-import java.io.PrintWriter;
-
 import com.google.gson.Gson;
 import com.google.gson.stream.JsonWriter;
 
+import java.io.PrintWriter;
+
 
 public class GitJobStatus {
 
@@ -26,7 +26,7 @@
 
     public String toString() {
       return name().toLowerCase();
-    };
+    }
   }
 
   public final int index;
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/ImportStep.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/ImportStep.java
index 9348a16..71a1869 100644
--- a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/ImportStep.java
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/ImportStep.java
@@ -13,10 +13,10 @@
 // limitations under the License.
 package com.googlesource.gerrit.plugins.github.git;
 
-import org.eclipse.jgit.lib.ProgressMonitor;
-
 import com.googlesource.gerrit.plugins.github.GitHubURL;
 
+import org.eclipse.jgit.lib.ProgressMonitor;
+
 public abstract class ImportStep {
   private final GitHubRepository gitHubRepository;
 
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/JobExecutor.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/JobExecutor.java
index 731f2c8..67dae23 100644
--- a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/JobExecutor.java
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/JobExecutor.java
@@ -13,16 +13,17 @@
 // limitations under the License.
 package com.googlesource.gerrit.plugins.github.git;
 
+import com.google.gerrit.server.util.RequestScopePropagator;
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+
+import com.googlesource.gerrit.plugins.github.GitHubConfig;
+
 import java.util.Random;
 import java.util.concurrent.Executors;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.TimeUnit;
 
-import com.google.gerrit.server.util.RequestScopePropagator;
-import com.google.inject.Inject;
-import com.google.inject.Singleton;
-import com.googlesource.gerrit.plugins.github.GitHubConfig;
-
 @Singleton
 public class JobExecutor {
   private final ScheduledExecutorService executor;
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/PullRequestCreateChange.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/PullRequestCreateChange.java
index 5d3b929..d6a7213 100644
--- a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/PullRequestCreateChange.java
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/PullRequestCreateChange.java
@@ -14,24 +14,7 @@
 
 package com.googlesource.gerrit.plugins.github.git;
 
-import java.io.IOException;
-import java.util.Iterator;
-import java.util.List;
-
-import org.eclipse.jgit.errors.IncorrectObjectTypeException;
-import org.eclipse.jgit.errors.MissingObjectException;
-import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.Ref;
-import org.eclipse.jgit.lib.RefUpdate;
-import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.revwalk.FooterKey;
-import org.eclipse.jgit.revwalk.RevCommit;
-import org.eclipse.jgit.revwalk.RevWalk;
-import org.eclipse.jgit.transport.ReceiveCommand;
-import org.eclipse.jgit.util.ChangeIdUtil;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
+import com.google.gerrit.common.TimeUtil;
 import com.google.gerrit.common.errors.EmailException;
 import com.google.gerrit.reviewdb.client.Account;
 import com.google.gerrit.reviewdb.client.Branch;
@@ -58,11 +41,31 @@
 import com.google.gerrit.server.project.NoSuchProjectException;
 import com.google.gerrit.server.project.ProjectControl;
 import com.google.gerrit.server.project.RefControl;
+import com.google.gerrit.server.query.change.ChangeData;
+import com.google.gerrit.server.query.change.InternalChangeQuery;
 import com.google.gerrit.server.ssh.NoSshInfo;
-import com.google.gerrit.server.util.TimeUtil;
 import com.google.gwtorm.server.OrmException;
 import com.google.gwtorm.server.ResultSet;
 import com.google.inject.Inject;
+import com.google.inject.Provider;
+
+import org.eclipse.jgit.errors.IncorrectObjectTypeException;
+import org.eclipse.jgit.errors.MissingObjectException;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.lib.RefUpdate;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.FooterKey;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevWalk;
+import org.eclipse.jgit.transport.ReceiveCommand;
+import org.eclipse.jgit.util.ChangeIdUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.List;
 
 public class PullRequestCreateChange {
   private static final Logger LOG = LoggerFactory
@@ -75,21 +78,23 @@
   private final PatchSetInserter.Factory patchSetInserterFactory;
   private final ProjectControl.Factory projectControlFactory;
   private final GenericFactory userFactory;
-
+  private final Provider<InternalChangeQuery> queryProvider;
 
   @Inject
-  PullRequestCreateChange(final IdentifiedUser currentUser,
-      final CommitValidators.Factory commitValidatorsFactory,
-      final ChangeInserter.Factory changeInserterFactory,
-      final PatchSetInserter.Factory patchSetInserterFactory,
-      final ProjectControl.Factory projectControlFactory,
-      final IdentifiedUser.GenericFactory userFactory) {
+  PullRequestCreateChange(IdentifiedUser currentUser,
+      CommitValidators.Factory commitValidatorsFactory,
+      ChangeInserter.Factory changeInserterFactory,
+      PatchSetInserter.Factory patchSetInserterFactory,
+      ProjectControl.Factory projectControlFactory,
+      IdentifiedUser.GenericFactory userFactory,
+      Provider<InternalChangeQuery> queryProvider) {
     this.currentUser = currentUser;
     this.commitValidatorsFactory = commitValidatorsFactory;
     this.changeInserterFactory = changeInserterFactory;
     this.patchSetInserterFactory = patchSetInserterFactory;
     this.projectControlFactory = projectControlFactory;
     this.userFactory = userFactory;
+    this.queryProvider = queryProvider;
   }
 
   public Change.Id addCommitToChange(final ReviewDb db, final Project project,
@@ -109,8 +114,7 @@
         projectControlFactory.controlFor(project.getNameKey()).controlForRef(
             destinationBranch);
 
-    try {
-      RevWalk revWalk = new RevWalk(git);
+    try (RevWalk revWalk = new RevWalk(git)) {
       try {
         Ref destRef = git.getRef(destinationBranch);
         if (destRef == null) {
@@ -144,11 +148,10 @@
           changeKey = new Change.Key("I" + computedChangeId.name());
         }
 
-        List<Change> destChanges =
-            db.changes()
-                .byBranchKey(
-                    new Branch.NameKey(project.getNameKey(), destRef.getName()),
-                    changeKey).toList();
+        List<ChangeData> destChanges =
+            queryProvider.get().byBranchKey(
+                new Branch.NameKey(project.getNameKey(), destRef.getName()),
+                changeKey);
 
         if (destChanges.size() > 1) {
           throw new InvalidChangeOperationException(
@@ -159,7 +162,7 @@
         } else if (destChanges.size() == 1) {
           // The change key exists on the destination branch: adding a new
           // patch-set
-          Change destChange = destChanges.get(0);
+          Change destChange = destChanges.get(0).change();
 
           ChangeControl changeControl =
               projectControlFactory.controlFor(project.getNameKey()).controlFor(
@@ -177,7 +180,6 @@
                   doValidation));
         }
       } finally {
-        revWalk.release();
         if (newChange == null) {
           db.rollback();
         }
@@ -218,8 +220,8 @@
     if (topic != null) {
       change.setTopic(topic);
     }
-    ChangeInserter ins =
-        changeInserterFactory.create(refControl, change, pullRequestCommit);
+    ChangeInserter ins = changeInserterFactory.create(
+        refControl.getProjectControl(), change, pullRequestCommit);
     PatchSet newPatchSet = ins.getPatchSet();
 
     if (doValidation) {
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/PullRequestImportJob.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/PullRequestImportJob.java
index 3f199be..174de06 100644
--- a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/PullRequestImportJob.java
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/PullRequestImportJob.java
@@ -13,8 +13,30 @@
 // limitations under the License.
 package com.googlesource.gerrit.plugins.github.git;
 
-import java.io.IOException;
-import java.util.List;
+import com.google.common.collect.Lists;
+import com.google.gerrit.extensions.restapi.BadRequestException;
+import com.google.gerrit.extensions.restapi.ResourceConflictException;
+import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountExternalId;
+import com.google.gerrit.reviewdb.client.Change.Id;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.client.Project.NameKey;
+import com.google.gerrit.reviewdb.server.AccountExternalIdAccess;
+import com.google.gerrit.reviewdb.server.ReviewDb;
+import com.google.gerrit.server.account.AccountImporter;
+import com.google.gerrit.server.git.GitRepositoryManager;
+import com.google.gerrit.server.project.ProjectCache;
+import com.google.gerrit.server.project.ProjectState;
+import com.google.gwtorm.server.OrmException;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.assistedinject.Assisted;
+
+import com.googlesource.gerrit.plugins.github.GitHubURL;
+import com.googlesource.gerrit.plugins.github.git.GitJobStatus.Code;
+import com.googlesource.gerrit.plugins.github.oauth.GitHubLogin;
+import com.googlesource.gerrit.plugins.github.oauth.ScopedProvider;
 
 import org.eclipse.jgit.api.FetchCommand;
 import org.eclipse.jgit.api.Git;
@@ -36,29 +58,8 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.collect.Lists;
-import com.google.gerrit.extensions.restapi.BadRequestException;
-import com.google.gerrit.extensions.restapi.ResourceConflictException;
-import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
-import com.google.gerrit.reviewdb.client.Change.Id;
-import com.google.gerrit.reviewdb.client.Account;
-import com.google.gerrit.reviewdb.client.AccountExternalId;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gerrit.reviewdb.client.Project.NameKey;
-import com.google.gerrit.reviewdb.server.AccountExternalIdAccess;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.account.AccountImporter;
-import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.project.ProjectCache;
-import com.google.gerrit.server.project.ProjectState;
-import com.google.gwtorm.server.OrmException;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import com.google.inject.assistedinject.Assisted;
-import com.googlesource.gerrit.plugins.github.GitHubURL;
-import com.googlesource.gerrit.plugins.github.oauth.GitHubLogin;
-import com.googlesource.gerrit.plugins.github.oauth.ScopedProvider;
-import com.googlesource.gerrit.plugins.github.git.GitJobStatus.Code;
+import java.io.IOException;
+import java.util.List;
 
 public class PullRequestImportJob implements GitJob, ProgressMonitor {
 
@@ -172,34 +173,35 @@
     ObjectId baseObjectId = ObjectId.fromString(pr.getBase().getSha());
     ObjectId prHeadObjectId = ObjectId.fromString(pr.getHead().getSha());
 
-    RevWalk walk = new RevWalk(gitRepo);
-    walk.markUninteresting(walk.lookupCommit(baseObjectId));
-    walk.markStart(walk.lookupCommit(prHeadObjectId));
-    walk.sort(RevSort.REVERSE);
-
-    int patchNr = 1;
-    for (GHPullRequestCommitDetail ghCommitDetail : pr.listCommits()) {
-      status.update(Code.SYNC, "Patch #" + patchNr, "Patch#" + patchNr
-          + ": Inserting PullRequest into Gerrit");
-      RevCommit revCommit =
-          walk.parseCommit(ObjectId.fromString(ghCommitDetail.getSha()));
-
-      GHUser prUser = pr.getUser();
-      GitUser commitAuthor = ghCommitDetail.getCommit().getAuthor();
-      GitHubUser gitHubUser = GitHubUser.from(prUser, commitAuthor);
-
-      Account.Id pullRequestOwner = getOrRegisterAccount(db, gitHubUser);
-      Id changeId =
-          createChange.addCommitToChange(db, project, gitRepo,
-              destinationBranch, pullRequestOwner, revCommit,
-              getChangeMessage(pr),
-              String.format(TOPIC_FORMAT, pr.getNumber()), false);
-      if (changeId != null) {
-        prChanges.add(changeId);
+    try (RevWalk walk = new RevWalk(gitRepo)) {
+      walk.markUninteresting(walk.lookupCommit(baseObjectId));
+      walk.markStart(walk.lookupCommit(prHeadObjectId));
+      walk.sort(RevSort.REVERSE);
+  
+      int patchNr = 1;
+      for (GHPullRequestCommitDetail ghCommitDetail : pr.listCommits()) {
+        status.update(Code.SYNC, "Patch #" + patchNr, "Patch#" + patchNr
+            + ": Inserting PullRequest into Gerrit");
+        RevCommit revCommit =
+            walk.parseCommit(ObjectId.fromString(ghCommitDetail.getSha()));
+  
+        GHUser prUser = pr.getUser();
+        GitUser commitAuthor = ghCommitDetail.getCommit().getAuthor();
+        GitHubUser gitHubUser = GitHubUser.from(prUser, commitAuthor);
+  
+        Account.Id pullRequestOwner = getOrRegisterAccount(db, gitHubUser);
+        Id changeId =
+            createChange.addCommitToChange(db, project, gitRepo,
+                destinationBranch, pullRequestOwner, revCommit,
+                getChangeMessage(pr),
+                String.format(TOPIC_FORMAT, pr.getNumber()), false);
+        if (changeId != null) {
+          prChanges.add(changeId);
+        }
       }
+  
+      return prChanges;
     }
-
-    return prChanges;
   }
 
   private com.google.gerrit.reviewdb.client.Account.Id getOrRegisterAccount(
@@ -246,6 +248,7 @@
     fetch.setRefSpecs(new RefSpec("+refs/pull/" + pr.getNumber()
         + "/head:refs/remotes/origin/pr/" + pr.getNumber()));
     fetch.setProgressMonitor(this);
+    fetch.setCredentialsProvider(ghRepository.getCredentialsProvider());
     fetch.call();
   }
 
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/PullRequestImporter.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/PullRequestImporter.java
index 7478571..3acdf9d 100644
--- a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/PullRequestImporter.java
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/PullRequestImporter.java
@@ -13,13 +13,13 @@
 // limitations under the License.
 package com.googlesource.gerrit.plugins.github.git;
 
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.inject.Inject;
 import com.google.inject.servlet.SessionScoped;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 @SessionScoped
 public class PullRequestImporter extends BatchImporter {
   private static final Logger log = LoggerFactory.getLogger(PullRequestImporter.class);
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/ReplicateProjectStep.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/ReplicateProjectStep.java
index 3881c86..5410c78 100644
--- a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/ReplicateProjectStep.java
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/ReplicateProjectStep.java
@@ -13,16 +13,19 @@
 // limitations under the License.
 package com.googlesource.gerrit.plugins.github.git;
 
-import org.eclipse.jgit.lib.ProgressMonitor;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import java.io.IOException;
 
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
+
 import com.googlesource.gerrit.plugins.github.GitHubURL;
 import com.googlesource.gerrit.plugins.github.oauth.GitHubLogin;
 import com.googlesource.gerrit.plugins.github.oauth.ScopedProvider;
 
+import org.eclipse.jgit.lib.ProgressMonitor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 public class ReplicateProjectStep extends ImportStep {
   private static final Logger LOG = LoggerFactory.getLogger(ReplicateProjectStep.class);
   private final ReplicationConfig replicationConfig;
@@ -42,7 +45,7 @@
       final ScopedProvider<GitHubLogin> ghLoginProvider,
       @GitHubURL String gitHubUrl,
       @Assisted("organisation") String organisation,
-      @Assisted("name") String repository) {
+      @Assisted("name") String repository) throws IOException {
     super(gitHubUrl, organisation, repository, gitHubRepoFactory);
     LOG.debug("Gerrit ReplicateProject " + organisation + "/" + repository);
     this.replicationConfig = replicationConfig;
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/ReplicationConfig.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/ReplicationConfig.java
index 4b6bb97..1784e0e 100644
--- a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/ReplicationConfig.java
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/ReplicationConfig.java
@@ -13,19 +13,19 @@
 // limitations under the License.
 package com.googlesource.gerrit.plugins.github.git;
 
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
+import com.google.gerrit.server.config.SitePaths;
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
 
 import org.eclipse.jgit.errors.ConfigInvalidException;
 import org.eclipse.jgit.storage.file.FileBasedConfig;
 import org.eclipse.jgit.util.FS;
 
-import com.google.gerrit.server.config.SitePaths;
-import com.google.inject.Inject;
-import com.google.inject.Singleton;
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
 
 @Singleton
 public class ReplicationConfig {
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/group/GitHubGroup.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/group/GitHubGroup.java
index 4f5947c..95158ff 100644
--- a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/group/GitHubGroup.java
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/group/GitHubGroup.java
@@ -14,11 +14,11 @@
 
 package com.googlesource.gerrit.plugins.github.group;
 
-import lombok.Getter;
-
 import com.google.gerrit.common.data.GroupDescription.Basic;
 import com.google.gerrit.reviewdb.client.AccountGroup.UUID;
 
+import lombok.Getter;
+
 public abstract class GitHubGroup implements Basic {
   public static final String UUID_PREFIX = "github:";
   public static final String NAME_PREFIX = "github/";
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/group/GitHubGroupBackend.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/group/GitHubGroupBackend.java
index 7846d77..00181b8 100644
--- a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/group/GitHubGroupBackend.java
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/group/GitHubGroupBackend.java
@@ -15,31 +15,33 @@
 package com.googlesource.gerrit.plugins.github.group;
 
 import static com.google.common.base.Preconditions.checkArgument;
-import static com.googlesource.gerrit.plugins.github.group.GitHubOrganisationGroup.NAME_PREFIX;
-import static com.googlesource.gerrit.plugins.github.group.GitHubOrganisationGroup.UUID_PREFIX;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Set;
-import java.util.concurrent.ExecutionException;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import static com.googlesource.gerrit.plugins.github.group.GitHubGroup.NAME_PREFIX;
+import static com.googlesource.gerrit.plugins.github.group.GitHubGroup.UUID_PREFIX;
 
 import com.google.common.base.Strings;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.ImmutableSet.Builder;
 import com.google.gerrit.common.data.GroupDescription.Basic;
 import com.google.gerrit.common.data.GroupReference;
+import com.google.gerrit.reviewdb.client.AccountGroup;
 import com.google.gerrit.reviewdb.client.AccountGroup.UUID;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.account.GroupBackend;
 import com.google.gerrit.server.account.GroupMembership;
 import com.google.gerrit.server.project.ProjectControl;
 import com.google.inject.Inject;
+
 import com.googlesource.gerrit.plugins.github.oauth.GitHubLogin;
 import com.googlesource.gerrit.plugins.github.oauth.UserScopedProvider;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
+
 public class GitHubGroupBackend implements GroupBackend {
   private static final Logger log = LoggerFactory
       .getLogger(GitHubGroupBackend.class);
@@ -56,6 +58,11 @@
   }
 
   @Override
+  public boolean isVisibleToAll(AccountGroup.UUID uuid) {
+    return true;
+  }
+
+  @Override
   public boolean handles(UUID uuid) {
     return uuid.get().startsWith(UUID_PREFIX);
   }
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/group/GitHubGroupMembership.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/group/GitHubGroupMembership.java
index b93c138..0c509f0 100644
--- a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/group/GitHubGroupMembership.java
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/group/GitHubGroupMembership.java
@@ -14,14 +14,14 @@
 
 package com.googlesource.gerrit.plugins.github.group;
 
-import java.util.Set;
-
 import com.google.common.collect.ImmutableSet;
 import com.google.gerrit.reviewdb.client.AccountGroup.UUID;
 import com.google.gerrit.server.account.GroupMembership;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
 
+import java.util.Set;
+
 public class GitHubGroupMembership implements GroupMembership {
   private final Set<UUID> groups;
 
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/group/GitHubGroupsCache.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/group/GitHubGroupsCache.java
index d02d4ff..f895500 100644
--- a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/group/GitHubGroupsCache.java
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/group/GitHubGroupsCache.java
@@ -16,18 +16,6 @@
 
 import static java.util.concurrent.TimeUnit.MINUTES;
 
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.util.Collections;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.concurrent.ExecutionException;
-
-import org.kohsuke.github.GHTeam;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
 import com.google.common.cache.CacheLoader;
 import com.google.common.cache.LoadingCache;
 import com.google.common.collect.HashMultimap;
@@ -42,9 +30,22 @@
 import com.google.inject.Singleton;
 import com.google.inject.TypeLiteral;
 import com.google.inject.name.Named;
+
 import com.googlesource.gerrit.plugins.github.oauth.GitHubLogin;
 import com.googlesource.gerrit.plugins.github.oauth.UserScopedProvider;
 
+import org.kohsuke.github.GHTeam;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
+
 @Singleton
 public class GitHubGroupsCache {
   private static final Logger log = LoggerFactory
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/replication/Destination.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/replication/Destination.java
index 6519c16..e6c070a 100644
--- a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/replication/Destination.java
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/replication/Destination.java
@@ -14,15 +14,7 @@
 
 package com.googlesource.gerrit.plugins.github.replication;
 
-import java.io.UnsupportedEncodingException;
-import java.net.URLEncoder;
-import java.util.List;
-
-import org.eclipse.jgit.lib.Config;
-import org.eclipse.jgit.transport.RemoteConfig;
-import org.eclipse.jgit.transport.URIish;
-
-import com.google.common.base.Objects;
+import com.google.common.base.MoreObjects;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Lists;
 import com.google.gerrit.common.data.GroupReference;
@@ -40,6 +32,14 @@
 import com.google.gwtorm.server.SchemaFactory;
 import com.google.inject.Injector;
 
+import org.eclipse.jgit.lib.Config;
+import org.eclipse.jgit.transport.RemoteConfig;
+import org.eclipse.jgit.transport.URIish;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.util.List;
+
 public class Destination {
   private final RemoteConfig remote;
   private final ProjectControl.Factory projectControlFactory;
@@ -55,7 +55,7 @@
     remote = rc;
 
     remoteNameStyle =
-        Objects.firstNonNull(
+        MoreObjects.firstNonNull(
             cfg.getString("remote", rc.getName(), "remoteNameStyle"), "slash");
 
     String[] authGroupNames =
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/replication/GitHubDestinations.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/replication/GitHubDestinations.java
index 48474c3..e383fe1 100644
--- a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/replication/GitHubDestinations.java
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/replication/GitHubDestinations.java
@@ -14,23 +14,6 @@
 
 package com.googlesource.gerrit.plugins.github.replication;
 
-import java.io.File;
-import java.io.IOException;
-import java.net.URISyntaxException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
-
-import org.eclipse.jgit.errors.ConfigInvalidException;
-import org.eclipse.jgit.storage.file.FileBasedConfig;
-import org.eclipse.jgit.transport.RefSpec;
-import org.eclipse.jgit.transport.RemoteConfig;
-import org.eclipse.jgit.transport.URIish;
-import org.eclipse.jgit.util.FS;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Lists;
 import com.google.gerrit.reviewdb.server.ReviewDb;
@@ -42,6 +25,23 @@
 import com.google.inject.Inject;
 import com.google.inject.Injector;
 
+import org.eclipse.jgit.errors.ConfigInvalidException;
+import org.eclipse.jgit.storage.file.FileBasedConfig;
+import org.eclipse.jgit.transport.RefSpec;
+import org.eclipse.jgit.transport.RemoteConfig;
+import org.eclipse.jgit.transport.URIish;
+import org.eclipse.jgit.util.FS;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
 /** Manages automatic replication to remote repositories. */
 public class GitHubDestinations {
   private static final String GITHUB_DESTINATION = "github";
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/velocity/PluginVelocityModel.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/velocity/PluginVelocityModel.java
index 81933df..8b4236b 100644
--- a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/velocity/PluginVelocityModel.java
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/velocity/PluginVelocityModel.java
@@ -13,11 +13,11 @@
 // limitations under the License.
 package com.googlesource.gerrit.plugins.github.velocity;
 
-import org.apache.velocity.VelocityContext;
-
 import com.google.inject.Inject;
 import com.google.inject.servlet.RequestScoped;
 
+import org.apache.velocity.VelocityContext;
+
 @RequestScoped
 public class PluginVelocityModel {
 
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/velocity/PluginVelocityRuntimeProvider.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/velocity/PluginVelocityRuntimeProvider.java
index 7741a88..57b4780 100644
--- a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/velocity/PluginVelocityRuntimeProvider.java
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/velocity/PluginVelocityRuntimeProvider.java
@@ -13,14 +13,6 @@
 // limitations under the License.
 package com.googlesource.gerrit.plugins.github.velocity;
 
-import java.io.File;
-import java.util.Properties;
-
-import org.apache.velocity.runtime.RuntimeConstants;
-import org.apache.velocity.runtime.RuntimeInstance;
-import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;
-import org.apache.velocity.runtime.resource.loader.JarResourceLoader;
-
 import com.google.gerrit.extensions.annotations.PluginName;
 import com.google.gerrit.server.config.SitePaths;
 import com.google.gerrit.server.mail.VelocityRuntimeProvider.Slf4jLogChute;
@@ -29,6 +21,14 @@
 import com.google.inject.ProvisionException;
 import com.google.inject.Singleton;
 
+import org.apache.velocity.runtime.RuntimeConstants;
+import org.apache.velocity.runtime.RuntimeInstance;
+import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;
+import org.apache.velocity.runtime.resource.loader.JarResourceLoader;
+
+import java.io.File;
+import java.util.Properties;
+
 @Singleton
 public class PluginVelocityRuntimeProvider implements Provider<RuntimeInstance> {
   private static final String VELOCITY_FILE_RESOURCE_LOADER_PATH =
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/velocity/VelocityStaticServlet.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/velocity/VelocityStaticServlet.java
index 11921d5..4139adf 100644
--- a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/velocity/VelocityStaticServlet.java
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/velocity/VelocityStaticServlet.java
@@ -14,6 +14,20 @@
 
 package com.googlesource.gerrit.plugins.github.velocity;
 
+import com.google.common.collect.Maps;
+import com.google.gwtexpui.server.CacheHeaders;
+import com.google.gwtjsonrpc.server.RPCServletUtils;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.Singleton;
+import com.google.inject.name.Named;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.velocity.runtime.RuntimeInstance;
+import org.apache.velocity.runtime.resource.Resource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
@@ -26,20 +40,6 @@
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-import org.apache.commons.io.IOUtils;
-import org.apache.velocity.runtime.RuntimeInstance;
-import org.apache.velocity.runtime.resource.Resource;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.collect.Maps;
-import com.google.gwtexpui.server.CacheHeaders;
-import com.google.gwtjsonrpc.server.RPCServletUtils;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import com.google.inject.Singleton;
-import com.google.inject.name.Named;
-
 /** Sends static content using Velocity resource resolver */
 @SuppressWarnings("serial")
 @Singleton
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/velocity/VelocityViewServlet.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/velocity/VelocityViewServlet.java
index 0d1cc41..cd1a202 100644
--- a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/velocity/VelocityViewServlet.java
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/velocity/VelocityViewServlet.java
@@ -13,6 +13,25 @@
 // limitations under the License.
 package com.googlesource.gerrit.plugins.github.velocity;
 
+import com.google.common.base.MoreObjects;
+import com.google.gerrit.server.IdentifiedUser;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.Singleton;
+import com.google.inject.name.Named;
+
+import com.googlesource.gerrit.plugins.github.GitHubConfig.NextPage;
+import com.googlesource.gerrit.plugins.github.oauth.GitHubLogin;
+import com.googlesource.gerrit.plugins.github.oauth.ScopedProvider;
+
+import org.apache.http.HttpStatus;
+import org.apache.velocity.Template;
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.exception.ResourceNotFoundException;
+import org.apache.velocity.runtime.RuntimeInstance;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import java.io.IOException;
 import java.nio.charset.StandardCharsets;
 import java.util.Map.Entry;
@@ -24,24 +43,6 @@
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-import org.apache.http.HttpStatus;
-import org.apache.velocity.Template;
-import org.apache.velocity.VelocityContext;
-import org.apache.velocity.exception.ResourceNotFoundException;
-import org.apache.velocity.runtime.RuntimeInstance;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Objects;
-import com.google.gerrit.server.IdentifiedUser;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import com.google.inject.Singleton;
-import com.google.inject.name.Named;
-import com.googlesource.gerrit.plugins.github.GitHubConfig.NextPage;
-import com.googlesource.gerrit.plugins.github.oauth.GitHubLogin;
-import com.googlesource.gerrit.plugins.github.oauth.ScopedProvider;
-
 @Singleton
 public class VelocityViewServlet extends HttpServlet {
   private static final Logger log = LoggerFactory
@@ -81,10 +82,7 @@
               + nextPage.uri;
     }
 
-    String pathInfo = Objects.firstNonNull(destUrl, servletPath);
-    if (!pathInfo.startsWith(STATIC_PREFIX)) {
-      resp.sendError(HttpStatus.SC_NOT_FOUND);
-    }
+    String pathInfo = STATIC_PREFIX + MoreObjects.firstNonNull(destUrl, servletPath);
 
     try {
       Template template = velocityRuntime.getTemplate(pathInfo, "UTF-8");
@@ -103,7 +101,7 @@
     }
   }
 
-  private PluginVelocityModel initVelocityModel(HttpServletRequest request) {
+  private PluginVelocityModel initVelocityModel(HttpServletRequest request) throws IOException {
     PluginVelocityModel model = modelProvider.get();
     GitHubLogin gitHubLogin = loginProvider.get(request);
     model.put("myself", gitHubLogin.getMyself());
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/wizard/AccountController.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/wizard/AccountController.java
index 4235308..83b8093 100644
--- a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/wizard/AccountController.java
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/wizard/AccountController.java
@@ -13,24 +13,6 @@
 // limitations under the License.
 package com.googlesource.gerrit.plugins.github.wizard;
 
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.commons.lang.StringUtils;
-import org.kohsuke.github.GHKey;
-import org.kohsuke.github.GHMyself;
-import org.kohsuke.github.GHVerifiedKey;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
 import com.google.common.base.Function;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
@@ -51,8 +33,27 @@
 import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
+
 import com.googlesource.gerrit.plugins.github.oauth.GitHubLogin;
 
+import org.apache.commons.lang.StringUtils;
+import org.kohsuke.github.GHKey;
+import org.kohsuke.github.GHMyself;
+import org.kohsuke.github.GHVerifiedKey;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
 public class AccountController implements VelocityController {
 
   private static final Logger log = LoggerFactory
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/wizard/ControllerErrors.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/wizard/ControllerErrors.java
index 08ea959..49a4a84 100644
--- a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/wizard/ControllerErrors.java
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/wizard/ControllerErrors.java
@@ -13,13 +13,13 @@
 // limitations under the License.
 package com.googlesource.gerrit.plugins.github.wizard;
 
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 @Singleton
 public class ControllerErrors {
   private static final Logger log = LoggerFactory
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/wizard/JobStatusController.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/wizard/JobStatusController.java
index 966f33f..0c5e52f 100644
--- a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/wizard/JobStatusController.java
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/wizard/JobStatusController.java
@@ -13,19 +13,20 @@
 // limitations under the License.
 package com.googlesource.gerrit.plugins.github.wizard;
 
+import com.google.common.collect.Lists;
+import com.google.gson.Gson;
+import com.google.gson.stream.JsonWriter;
+
+import com.googlesource.gerrit.plugins.github.git.BatchImporter;
+import com.googlesource.gerrit.plugins.github.git.GitJob;
+import com.googlesource.gerrit.plugins.github.git.GitJobStatus;
+
 import java.io.IOException;
 import java.util.Collection;
 import java.util.List;
 
 import javax.servlet.http.HttpServletResponse;
 
-import com.google.common.collect.Lists;
-import com.google.gson.Gson;
-import com.google.gson.stream.JsonWriter;
-import com.googlesource.gerrit.plugins.github.git.BatchImporter;
-import com.googlesource.gerrit.plugins.github.git.GitJob;
-import com.googlesource.gerrit.plugins.github.git.GitJobStatus;
-
 
 
 public class JobStatusController {
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/wizard/PullRequestImportController.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/wizard/PullRequestImportController.java
index 43d9924..747f388 100644
--- a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/wizard/PullRequestImportController.java
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/wizard/PullRequestImportController.java
@@ -13,6 +13,15 @@
 // limitations under the License.
 package com.googlesource.gerrit.plugins.github.wizard;
 
+import com.google.gerrit.server.IdentifiedUser;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.Singleton;
+
+import com.googlesource.gerrit.plugins.github.git.PullRequestImportType;
+import com.googlesource.gerrit.plugins.github.git.PullRequestImporter;
+import com.googlesource.gerrit.plugins.github.oauth.GitHubLogin;
+
 import java.io.IOException;
 import java.util.Map.Entry;
 
@@ -20,14 +29,6 @@
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-import com.google.gerrit.server.IdentifiedUser;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import com.google.inject.Singleton;
-import com.googlesource.gerrit.plugins.github.oauth.GitHubLogin;
-import com.googlesource.gerrit.plugins.github.git.PullRequestImportType;
-import com.googlesource.gerrit.plugins.github.git.PullRequestImporter;
-
 @Singleton
 public class PullRequestImportController implements VelocityController {
 
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/wizard/PullRequestImportStatusController.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/wizard/PullRequestImportStatusController.java
index dad9597..0a9d2c7 100644
--- a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/wizard/PullRequestImportStatusController.java
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/wizard/PullRequestImportStatusController.java
@@ -13,18 +13,19 @@
 // limitations under the License.
 package com.googlesource.gerrit.plugins.github.wizard;
 
+import com.google.gerrit.server.IdentifiedUser;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+
+import com.googlesource.gerrit.plugins.github.git.PullRequestImporter;
+import com.googlesource.gerrit.plugins.github.oauth.GitHubLogin;
+
 import java.io.IOException;
 
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-import com.google.gerrit.server.IdentifiedUser;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import com.googlesource.gerrit.plugins.github.oauth.GitHubLogin;
-import com.googlesource.gerrit.plugins.github.git.PullRequestImporter;
-
 public class PullRequestImportStatusController extends JobStatusController
     implements VelocityController {
 
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/wizard/PullRequestListController.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/wizard/PullRequestListController.java
index 4fad6ab..8449edb 100644
--- a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/wizard/PullRequestListController.java
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/wizard/PullRequestListController.java
@@ -13,31 +13,6 @@
 // limitations under the License.
 package com.googlesource.gerrit.plugins.github.wizard;
 
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.text.SimpleDateFormat;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.eclipse.jgit.errors.IncorrectObjectTypeException;
-import org.eclipse.jgit.errors.MissingObjectException;
-import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.revwalk.RevWalk;
-import org.kohsuke.github.GHIssueState;
-import org.kohsuke.github.GHPerson;
-import org.kohsuke.github.GHPullRequest;
-import org.kohsuke.github.GHPullRequestCommitDetail;
-import org.kohsuke.github.GHRepository;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
 import com.google.common.base.Optional;
 import com.google.common.base.Strings;
 import com.google.common.collect.Lists;
@@ -57,9 +32,35 @@
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 import com.google.inject.Singleton;
+
 import com.googlesource.gerrit.plugins.github.GitHubConfig;
 import com.googlesource.gerrit.plugins.github.oauth.GitHubLogin;
 
+import org.eclipse.jgit.errors.IncorrectObjectTypeException;
+import org.eclipse.jgit.errors.MissingObjectException;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevWalk;
+import org.kohsuke.github.GHIssueState;
+import org.kohsuke.github.GHPerson;
+import org.kohsuke.github.GHPullRequest;
+import org.kohsuke.github.GHPullRequestCommitDetail;
+import org.kohsuke.github.GHRepository;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.text.SimpleDateFormat;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
 @Singleton
 public class PullRequestListController implements VelocityController {
   private static final Logger LOG = LoggerFactory
@@ -204,30 +205,31 @@
       Repository gitRepo, GHPullRequest ghPullRequest)
       throws IncorrectObjectTypeException, IOException {
     boolean pullRequestToImport = false;
-    RevWalk gitWalk = new RevWalk(gitRepo);
-    for (GHPullRequestCommitDetail pullRequestCommit : ghPullRequest
-        .listCommits()) {
-      ObjectId pullRequestHeadObjectId =
-          ObjectId.fromString(pullRequestCommit.getSha());
-
-      try {
-        gitWalk.parseCommit(pullRequestHeadObjectId);
-
-        ResultSet<PatchSet> patchSets;
+    try (RevWalk gitWalk = new RevWalk(gitRepo)) {
+      for (GHPullRequestCommitDetail pullRequestCommit : ghPullRequest
+          .listCommits()) {
+        ObjectId pullRequestHeadObjectId =
+            ObjectId.fromString(pullRequestCommit.getSha());
+  
         try {
-          patchSets =
-              db.patchSets().byRevision(new RevId(pullRequestCommit.getSha()));
-        } catch (OrmException e) {
-          LOG.error("Error whilst fetching patch-sets from DB associated to commit "
-              + pullRequestCommit.getSha());
-          return false;
+          gitWalk.parseCommit(pullRequestHeadObjectId);
+  
+          ResultSet<PatchSet> patchSets;
+          try {
+            patchSets =
+                db.patchSets().byRevision(new RevId(pullRequestCommit.getSha()));
+          } catch (OrmException e) {
+            LOG.error("Error whilst fetching patch-sets from DB associated to commit "
+                + pullRequestCommit.getSha());
+            return false;
+          }
+          pullRequestToImport = !patchSets.iterator().hasNext();
+          patchSets.close();
+        } catch (MissingObjectException e) {
+          pullRequestToImport = true;
         }
-        pullRequestToImport = !patchSets.iterator().hasNext();
-        patchSets.close();
-      } catch (MissingObjectException e) {
-        pullRequestToImport = true;
       }
+      return pullRequestToImport;
     }
-    return pullRequestToImport;
   }
 }
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/wizard/RepositoriesCloneCancelController.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/wizard/RepositoriesCloneCancelController.java
index 01d919c..7667eeb 100644
--- a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/wizard/RepositoriesCloneCancelController.java
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/wizard/RepositoriesCloneCancelController.java
@@ -13,19 +13,20 @@
 // limitations under the License.
 package com.googlesource.gerrit.plugins.github.wizard;
 
+import com.google.gerrit.server.IdentifiedUser;
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+
+import com.googlesource.gerrit.plugins.github.git.GitImporter;
+import com.googlesource.gerrit.plugins.github.oauth.GitHubLogin;
+import com.googlesource.gerrit.plugins.github.oauth.ScopedProvider;
+
 import java.io.IOException;
 
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-import com.google.gerrit.server.IdentifiedUser;
-import com.google.inject.Inject;
-import com.google.inject.Singleton;
-import com.googlesource.gerrit.plugins.github.oauth.GitHubLogin;
-import com.googlesource.gerrit.plugins.github.oauth.ScopedProvider;
-import com.googlesource.gerrit.plugins.github.git.GitImporter;
-
 @Singleton
 public class RepositoriesCloneCancelController implements VelocityController {
 
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/wizard/RepositoriesCloneController.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/wizard/RepositoriesCloneController.java
index e656862..72e2a91 100644
--- a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/wizard/RepositoriesCloneController.java
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/wizard/RepositoriesCloneController.java
@@ -13,6 +13,13 @@
 // limitations under the License.
 package com.googlesource.gerrit.plugins.github.wizard;
 
+import com.google.gerrit.server.IdentifiedUser;
+import com.google.inject.Inject;
+
+import com.googlesource.gerrit.plugins.github.git.GitImporter;
+import com.googlesource.gerrit.plugins.github.oauth.GitHubLogin;
+import com.googlesource.gerrit.plugins.github.oauth.ScopedProvider;
+
 import java.io.IOException;
 import java.util.Map.Entry;
 import java.util.Set;
@@ -21,12 +28,6 @@
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-import com.google.gerrit.server.IdentifiedUser;
-import com.google.inject.Inject;
-import com.googlesource.gerrit.plugins.github.oauth.GitHubLogin;
-import com.googlesource.gerrit.plugins.github.oauth.ScopedProvider;
-import com.googlesource.gerrit.plugins.github.git.GitImporter;
-
 public class RepositoriesCloneController implements VelocityController {
   private static final String REPO_PARAM_PREFIX = "repo_";
   private final ScopedProvider<GitImporter> cloneProvider;
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/wizard/RepositoriesCloneStatusController.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/wizard/RepositoriesCloneStatusController.java
index a2ead75..e8c2f05 100644
--- a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/wizard/RepositoriesCloneStatusController.java
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/wizard/RepositoriesCloneStatusController.java
@@ -13,19 +13,20 @@
 // limitations under the License.
 package com.googlesource.gerrit.plugins.github.wizard;
 
+import com.google.gerrit.server.IdentifiedUser;
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+
+import com.googlesource.gerrit.plugins.github.git.GitImporter;
+import com.googlesource.gerrit.plugins.github.oauth.GitHubLogin;
+import com.googlesource.gerrit.plugins.github.oauth.ScopedProvider;
+
 import java.io.IOException;
 
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-import com.google.gerrit.server.IdentifiedUser;
-import com.google.inject.Inject;
-import com.google.inject.Singleton;
-import com.googlesource.gerrit.plugins.github.oauth.GitHubLogin;
-import com.googlesource.gerrit.plugins.github.oauth.ScopedProvider;
-import com.googlesource.gerrit.plugins.github.git.GitImporter;
-
 @Singleton
 public class RepositoriesCloneStatusController extends JobStatusController implements VelocityController {
   private ScopedProvider<GitImporter> clonerProvider;
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/wizard/RepositoriesListController.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/wizard/RepositoriesListController.java
index 941a74e..45198ab 100644
--- a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/wizard/RepositoriesListController.java
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/wizard/RepositoriesListController.java
@@ -13,17 +13,6 @@
 // limitations under the License.
 package com.googlesource.gerrit.plugins.github.wizard;
 
-import java.io.IOException;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.kohsuke.github.GHOrganization;
-import org.kohsuke.github.GHRepository;
-import org.kohsuke.github.PagedIterable;
-import org.kohsuke.github.PagedIterator;
-
 import com.google.common.base.Strings;
 import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.IdentifiedUser;
@@ -33,9 +22,21 @@
 import com.google.gson.JsonPrimitive;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
+
 import com.googlesource.gerrit.plugins.github.GitHubConfig;
 import com.googlesource.gerrit.plugins.github.oauth.GitHubLogin;
 
+import org.kohsuke.github.GHOrganization;
+import org.kohsuke.github.GHRepository;
+import org.kohsuke.github.PagedIterable;
+import org.kohsuke.github.PagedIterator;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
 @Singleton
 public class RepositoriesListController implements VelocityController {
   private final ProjectCache projects;
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/wizard/VelocityController.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/wizard/VelocityController.java
index 1644cce..12da108 100644
--- a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/wizard/VelocityController.java
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/wizard/VelocityController.java
@@ -13,15 +13,16 @@
 // limitations under the License.
 package com.googlesource.gerrit.plugins.github.wizard;
 
+import com.google.gerrit.server.IdentifiedUser;
+
+import com.googlesource.gerrit.plugins.github.oauth.GitHubLogin;
+
 import java.io.IOException;
 
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-import com.google.gerrit.server.IdentifiedUser;
-import com.googlesource.gerrit.plugins.github.oauth.GitHubLogin;
-
 
 
 public interface VelocityController {
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/wizard/VelocityControllerServlet.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/wizard/VelocityControllerServlet.java
index ff121ae..1d7b65e 100644
--- a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/wizard/VelocityControllerServlet.java
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/wizard/VelocityControllerServlet.java
@@ -13,6 +13,21 @@
 // limitations under the License.
 package com.googlesource.gerrit.plugins.github.wizard;
 
+import com.google.gerrit.server.IdentifiedUser;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Provider;
+import com.google.inject.Singleton;
+
+import com.googlesource.gerrit.plugins.github.GitHubConfig;
+import com.googlesource.gerrit.plugins.github.GitHubConfig.NextPage;
+import com.googlesource.gerrit.plugins.github.oauth.GitHubLogin;
+import com.googlesource.gerrit.plugins.github.oauth.ScopedProvider;
+
+import org.apache.http.HttpStatus;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import java.io.IOException;
 
 import javax.servlet.RequestDispatcher;
@@ -21,20 +36,6 @@
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-import org.apache.http.HttpStatus;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.gerrit.server.IdentifiedUser;
-import com.google.inject.Inject;
-import com.google.inject.Injector;
-import com.google.inject.Provider;
-import com.google.inject.Singleton;
-import com.googlesource.gerrit.plugins.github.GitHubConfig;
-import com.googlesource.gerrit.plugins.github.GitHubConfig.NextPage;
-import com.googlesource.gerrit.plugins.github.oauth.GitHubLogin;
-import com.googlesource.gerrit.plugins.github.oauth.ScopedProvider;
-
 @Singleton
 public class VelocityControllerServlet extends HttpServlet {
   private static final long serialVersionUID = 5565594120346641704L;
diff --git a/github-plugin/src/main/resources/Documentation/about.md b/github-plugin/src/main/resources/Documentation/about.md
new file mode 100644
index 0000000..5ba04a6
--- /dev/null
+++ b/github-plugin/src/main/resources/Documentation/about.md
@@ -0,0 +1,26 @@
+
+This plugins allows to integrate Gerrit with external set of users configured
+on GitHub.
+It relies on the installation of the github-oauth Java library under the `$GERRIT_SITE/lib`
+in order filter all the HTTP requests through the GitHub OAuth 2.0 secure authentication.
+
+GitHub application registration
+-------------------------------
+
+GitHub uses OAuth2 as protocol to allow external apps request authorization to private
+details in a user's GitHub account without getting their password. This is
+preferred over Basic Authentication because tokens can be limited to specific
+types of data, and can be revoked by users at any time.
+
+Site owners have to register their application before getting started.  For
+more information see [GitHub application registration page](https://github.com/settings/applications/new).
+A registered OAuth application is assigned a unique `Client ID` and `Client
+Secret`. The `Client Secret` should never be shared.
+
+The Gerrit OAuth callback `<gerrit canonical URL>/oauth`
+needs to be specified in the GitHub application registration to establish mutual
+trust between the two domains and exchange the authorization codes. The use of HTTPS
+for Gerrit is strongly recommended for keeping the secrets exchange confidential.
+
+`auth.httpHeader` is set to `GITHUB_USER` with this authentication method and `auth.type`
+must be set to HTTP.
\ No newline at end of file
diff --git a/github-plugin/src/main/resources/Documentation/config.md b/github-plugin/src/main/resources/Documentation/config.md
index 2d18944..9d7c87b 100644
--- a/github-plugin/src/main/resources/Documentation/config.md
+++ b/github-plugin/src/main/resources/Documentation/config.md
@@ -1,13 +1,6 @@
-Plugin @PLUGIN@
-===============
 
-This plugins allows to integrate Gerrit with external set of users configured
-on GitHub.
-It relies on the installation of the github-oauth Java library under the $GERRIT_SITE/lib
-in order filter all the HTTP requests through the GitHub OAuth 2.0 secure authentication.
-
-GitHub init step
-----------------
+GitHub configuration during Gerrit init
+---------------------------------------
 
 This plugin provides a customized Gerrit init step for the self-configuration of
 the main GitHub and Gerrit authentication settings for allowing the github-oauth
@@ -18,19 +11,58 @@
 See below a sample session of relevant init steps for a default
 configuration pointing to the Web GitHub instance:
 
-	*** User Authentication
-	***
+```
+   *** GitHub Integration
+   *** 
 
-	Authentication method          []: HTTP
-	Get username from custom HTTP header [Y/n]? Y
-	Username HTTP header           []: GITHUB_USER
-	SSO logout URL                 : /oauth/reset
+   GitHub URL                     [https://github.com]: 
+   GitHub API URL                 [https://api.github.com]: 
 
+   NOTE: You might need to configure a proxy using http.proxy if you run Gerrit behind a firewall.
 
-	*** GitHub Integration
-	***
+   *** GitHub OAuth registration and credentials
+   *** 
 
-	GitHub URL                     [https://github.com]:
-	Use GitHub for Gerrit login ?  [Y/n]? Y
-	ClientId                       []: 384cbe2e8d98192f9799
-	ClientSecret                   []: f82c3f9b3802666f2adcc4c8cacfb164295b0a99
+   Register Gerrit as GitHub application on:
+   https://github.com/settings/applications/new
+
+   Settings (assumed Gerrit URL: http://localhost:8080/)
+   * Application name: Gerrit Code Review
+   * Homepage URL: http://localhost:8080/
+   * Authorization callback URL: http://localhost:8080/oauth
+
+   After registration is complete, enter the generated OAuth credentials:
+   GitHub Client ID               [1ebea047915210179cf5]: 
+   ClientSecret                   []: f82c3f9b3802666f2adcc4c8cacfb164295b0a99
+   confirm password : 
+   HTTP Authentication Header     [GITHUB_USER]: 
+```
+
+Configuration
+-------------
+
+GitHub plugin read his configuration from gerrit.config under the `[github]` section.
+
+github.url
+:   GitHub homepage URL. Default is `https://github.com`. Can be customized to a different 
+    value for GitHub:Enterprise integration
+
+**NOTE** You might need to configure a proxy using the configuration `http.proxy` if you run
+Gerrit behind a firewall.
+
+github.apiUrl
+:   GitHub API URL. Default is `https://api.github.com`. Can be customized to a different 
+    value for GitHub:Enterprise integration
+
+github.clientId
+:   The `Client ID`, that was received from GitHub when the application was registered. Required.
+
+github.clientSecret
+:   The `Client Secret`, that was received from GitHub when the application was registered. Required.
+
+github.scopes
+:   The GitHub scopes for allowing access to the user's public or private profile, organisations and 
+    repositories. See [GitHub Scopes definition](https://developer.github.com/v3/oauth/#scopes) 
+    for a detailed description of available scopes and their associated permissions. 
+    Default is empty read-only access to public 
+    information (includes public user profile info, public repository info, and gists).
diff --git a/pom.xml b/pom.xml
index 1467223..575be55 100644
--- a/pom.xml
+++ b/pom.xml
@@ -18,7 +18,7 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.googlesource.gerrit.plugins.github</groupId>
   <artifactId>github-parent</artifactId>
-  <version>2.10.3</version>
+  <version>2.11</version>
   <name>Gerrit Code Review - GitHub integration</name>
   <url>http://www.gerritforge.com</url>
   <packaging>pom</packaging>
@@ -247,6 +247,15 @@
       </plugin>
     </plugins>
   </build>
+  <reporting>
+    <plugins>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>findbugs-maven-plugin</artifactId>
+        <version>3.0.0</version>
+      </plugin>
+    </plugins>
+  </reporting>
   <repositories>
     <repository>
       <releases>