Multi-OAuth scopes configuration.

Enable the ability to have more than one scope
configured under gerrit.config and switch between
login scopes using a scope parameter in the Gerrit login.

Example use is:

GitHub's config in gerrit.config:
[github]
        scopes = USER_EMAIL,PUBLIC_REPO
        scopesPrivate = USER_EMAIL,REPO

GitHub OAuth USER_EMAIL+PUBLIC_REPO
by default at Gerrit login.

GitHub OAuth USER_EMAIL+REPO is used when loggin
in to Gerrit with /login?scope=scopesPrivate

NOTE: When logged using a specific scope, the OAuth
token is then reused throughout the Gerrit session
without having to specify the scope parameter anymore.

Change-Id: I0a6573bca6c677dd15b7878e7062bcac6b20529d
diff --git a/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/CompositeConfig.java b/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/CompositeConfig.java
new file mode 100644
index 0000000..4b9c35f
--- /dev/null
+++ b/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/CompositeConfig.java
@@ -0,0 +1,187 @@
+// Copyright (C) 2014 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 java.lang.reflect.Field;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.jgit.errors.ConfigInvalidException;
+import org.eclipse.jgit.events.ConfigChangedListener;
+import org.eclipse.jgit.events.ListenerHandle;
+import org.eclipse.jgit.lib.Config;
+import org.eclipse.jgit.lib.Config.SectionParser;
+
+import com.google.gerrit.server.config.GerritServerConfig;
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+
+@Singleton
+public class CompositeConfig extends Config {
+  private final Config secureConfig;
+  private final Config gerritConfig;
+
+  @Inject
+  public CompositeConfig(@GerritServerConfig Config config) {
+    this.secureConfig = config;
+    try {
+      Field baseConfigField = Config.class.getDeclaredField("baseConfig");
+      baseConfigField.setAccessible(true);
+      this.gerritConfig = (Config) baseConfigField.get(config);
+    } catch (SecurityException|NoSuchFieldException | IllegalArgumentException | IllegalAccessException e) {
+      throw new IllegalArgumentException("JGit baseConfig cannot be accessed from GerritServerConfig", e);
+    }
+  }
+
+  public ListenerHandle addChangeListener(ConfigChangedListener listener) {
+    return secureConfig.addChangeListener(listener);
+  }
+
+  public boolean equals(Object obj) {
+    return secureConfig.equals(obj);
+  }
+
+  public int getInt(String section, String name, int defaultValue) {
+    return secureConfig.getInt(section, name, defaultValue);
+  }
+
+  public int getInt(String section, String subsection, String name,
+      int defaultValue) {
+    return secureConfig.getInt(section, subsection, name, defaultValue);
+  }
+
+  public long getLong(String section, String name, long defaultValue) {
+    return secureConfig.getLong(section, name, defaultValue);
+  }
+
+  public long getLong(String section, String subsection, String name,
+      long defaultValue) {
+    return secureConfig.getLong(section, subsection, name, defaultValue);
+  }
+
+  public boolean getBoolean(String section, String name, boolean defaultValue) {
+    return secureConfig.getBoolean(section, name, defaultValue);
+  }
+
+  public boolean getBoolean(String section, String subsection, String name,
+      boolean defaultValue) {
+    return secureConfig.getBoolean(section, subsection, name, defaultValue);
+  }
+
+  public <T extends Enum<?>> T getEnum(String section, String subsection,
+      String name, T defaultValue) {
+    return secureConfig.getEnum(section, subsection, name, defaultValue);
+  }
+
+  public <T extends Enum<?>> T getEnum(T[] all, String section,
+      String subsection, String name, T defaultValue) {
+    return secureConfig.getEnum(all, section, subsection, name, defaultValue);
+  }
+
+  public Set<String> getNames(String section) {
+    return getNames(section, null);
+  }
+
+  public Set<String> getNames(String section, String subsection) {
+    Set<String> secureConfigNames = secureConfig.getNames(section, subsection);
+    Set<String> gerritConfigNames = gerritConfig.getNames(section, subsection);
+    gerritConfigNames.addAll(secureConfigNames);
+    return gerritConfigNames;
+  }
+
+  public <T> T get(SectionParser<T> parser) {
+    return secureConfig.get(parser);
+  }
+
+  public void fromText(String text) throws ConfigInvalidException {
+    secureConfig.fromText(text);
+  }
+
+  public Set<String> getNames(String section, boolean recursive) {
+    return secureConfig.getNames(section, recursive);
+  }
+
+  public Set<String> getNames(String section, String subsection,
+      boolean recursive) {
+    return secureConfig.getNames(section, subsection, recursive);
+  }
+
+  public String getString(String section, String subsection, String name) {
+    return secureConfig.getString(section, subsection, name);
+  }
+
+  public String[] getStringList(String section, String subsection, String name) {
+    return secureConfig.getStringList(section, subsection, name);
+  }
+
+  public Set<String> getSubsections(String section) {
+    return secureConfig.getSubsections(section);
+  }
+
+  public Set<String> getSections() {
+    return secureConfig.getSections();
+  }
+
+  public int hashCode() {
+    return secureConfig.hashCode();
+  }
+
+  public void uncache(SectionParser<?> parser) {
+    secureConfig.uncache(parser);
+  }
+
+  public void setInt(String section, String subsection, String name, int value) {
+    secureConfig.setInt(section, subsection, name, value);
+  }
+
+  public void setLong(String section, String subsection, String name, long value) {
+    secureConfig.setLong(section, subsection, name, value);
+  }
+
+  public void setBoolean(String section, String subsection, String name,
+      boolean value) {
+    secureConfig.setBoolean(section, subsection, name, value);
+  }
+
+  public <T extends Enum<?>> void setEnum(String section, String subsection,
+      String name, T value) {
+    secureConfig.setEnum(section, subsection, name, value);
+  }
+
+  public void setString(String section, String subsection, String name,
+      String value) {
+    secureConfig.setString(section, subsection, name, value);
+  }
+
+  public void unset(String section, String subsection, String name) {
+    secureConfig.unset(section, subsection, name);
+  }
+
+  public void setStringList(String section, String subsection, String name,
+      List<String> values) {
+    secureConfig.setStringList(section, subsection, name, values);
+  }
+
+  public String toString() {
+    return secureConfig.toString();
+  }
+
+  public void unsetSection(String section, String subsection) {
+    secureConfig.unsetSection(section, subsection);
+  }
+
+  public String toText() {
+    return secureConfig.toText();
+  }
+}
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 8ebc73b..459b9da 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
@@ -27,13 +27,14 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.base.Strings;
 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 {
-  private static final Logger log = LoggerFactory.getLogger(GitHubLogin.class);
+  private static final Logger LOG = LoggerFactory.getLogger(GitHubLogin.class);
 
   @Singleton
   public static class Provider extends HttpSessionProvider<GitHubLogin> {
@@ -49,6 +50,7 @@
   private transient OAuthProtocol oauth;
 
   private GHMyself myself;
+  private final OAuthCookieProvider cookieProvider;
 
   public GHMyself getMyself() {
     if (isLoggedIn()) {
@@ -61,6 +63,7 @@
   @Inject
   public GitHubLogin(OAuthProtocol oauth) {
     this.oauth = oauth;
+    this.cookieProvider = new OAuthCookieProvider(TokenCipher.get());
   }
 
   public boolean isLoggedIn() {
@@ -69,7 +72,7 @@
       try {
         myself = hub.getMyself();
       } catch (Throwable e) {
-        log.error("Connection to GitHub broken: logging out", e);
+        LOG.error("Connection to GitHub broken: logging out", e);
         logout();
         loggedIn = false;
       }
@@ -89,9 +92,23 @@
       return true;
     }
 
+    LOG.debug("Login " + this);
+
     if (OAuthProtocol.isOAuthFinal(request)) {
+      LOG.debug("Login-FINAL " + this);
       login(oauth.loginPhase2(request, response));
       if (isLoggedIn()) {
+        LOG.debug("Login-SUCCESS " + this);
+        String user = myself.getLogin();
+        String email = myself.getEmail();
+        String fullName =
+            Strings.emptyToNull(myself.getName()) == null ? user : myself
+                .getName();
+
+        OAuthCookie userCookie =
+            cookieProvider.getFromUser(user, email, fullName);
+        response.addCookie(userCookie);
+
         response.sendRedirect(OAuthProtocol.getTargetUrl(request));
         return true;
       } else {
@@ -99,6 +116,7 @@
         return false;
       }
     } else {
+      LOG.debug("Login-PHASE1 " + this);
       oauth.loginPhase1(request, response, scopes);
       return false;
     }
@@ -118,4 +136,10 @@
     this.hub = GitHub.connectUsingOAuth(authToken.access_token);
     return this.hub;
   }
+
+  @Override
+  public String toString() {
+    return "GitHubLogin [token=" + token + ", myself=" + myself + "]";
+  }
+
 }
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 a5a12ef..085125a 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
@@ -17,11 +17,14 @@
 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.Strings;
+import com.google.common.collect.Maps;
 import com.google.gerrit.reviewdb.client.AuthType;
 import com.google.gerrit.server.config.GerritServerConfig;
 import com.google.inject.Inject;
@@ -50,12 +53,12 @@
   public final String oAuthFinalRedirectUrl;
   public final String gitHubOAuthAccessTokenUrl;
   public final boolean enabled;
-  public final List<OAuthProtocol.Scope> scopes;
+  public final Map<String, List<OAuthProtocol.Scope>> scopes;
   public final int fileUpdateMaxRetryCount;
   public final int fileUpdateMaxRetryIntervalMsec;
 
   @Inject
-  public GitHubOAuthConfig(@GerritServerConfig Config config)
+  public GitHubOAuthConfig(CompositeConfig config)
       throws MalformedURLException {
     httpHeader = config.getString("auth", null, "httpHeader");
     httpDisplaynameHeader = config.getString("auth", null, "httpDisplaynameHeader");
@@ -74,17 +77,29 @@
     enabled =
         config.getString("auth", null, "type").equalsIgnoreCase(
             AuthType.HTTP.toString());
-    scopes = parseScopes(config.getString(CONF_SECTION, null, "scopes"));
+    scopes = getScopes(config);
 
     fileUpdateMaxRetryCount = config.getInt(CONF_SECTION, "fileUpdateMaxRetryCount", 3);
     fileUpdateMaxRetryIntervalMsec = config.getInt(CONF_SECTION, "fileUpdateMaxRetryIntervalMsec", 3000);
   }
 
+  private Map<String, List<Scope>> getScopes(CompositeConfig config) {
+    Map<String, List<Scope>> scopes = Maps.newHashMap();
+    Set<String> configKeys = config.getNames(CONF_SECTION);
+    for (String key : configKeys) {
+      if (key.startsWith("scopes")) {
+        String scopesString = config.getString(CONF_SECTION, null, key);
+        scopes.put(key, parseScopesString(scopesString));
+      }
+    }
+    return scopes;
+  }
+
   private String dropTrailingSlash(String url) {
     return (url.endsWith("/") ? url.substring(0, url.length()-1):url);
   }
 
-  private List<Scope> parseScopes(String scopesString) {
+  private List<Scope> parseScopesString(String scopesString) {
     ArrayList<Scope> scopes = new ArrayList<OAuthProtocol.Scope>();
     if(Strings.emptyToNull(scopesString) != null) {
       String[] scopesStrings = scopesString.split(",");
@@ -105,4 +120,12 @@
           + (path.startsWith("/") ? path.substring(1) : path);
     }
   }
+
+  public Scope[] getDefaultScopes() {
+    if (scopes == null || scopes.get("scopes") == null) {
+      return new Scope[0];
+    } else {
+      return scopes.get("scopes").toArray(new Scope[0]);
+    }
+  }
 }
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 69ac33c..ba057ff 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
@@ -14,7 +14,6 @@
 package com.googlesource.gerrit.plugins.github.oauth;
 
 import java.io.IOException;
-import java.net.HttpURLConnection;
 import java.text.SimpleDateFormat;
 import java.util.Date;
 import java.util.Random;
@@ -31,21 +30,16 @@
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpSession;
 
-import org.apache.http.client.HttpClient;
 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.kohsuke.github.GitHub;
 import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Strings;
 import com.google.gerrit.server.config.SitePaths;
-import com.google.gson.Gson;
 import com.google.inject.Inject;
-import com.google.inject.Provider;
 import com.google.inject.Singleton;
-import com.googlesource.gerrit.plugins.github.oauth.OAuthProtocol.AccessToken;
 
 @Singleton
 public class OAuthFilter implements Filter {
@@ -65,9 +59,9 @@
       // as this filter is instantiated with a standard Gerrit WebModule
       GitHubLogin.Provider loginProvider) {
     this.config = config;
-    this.cookieProvider = new OAuthCookieProvider(new TokenCipher());
     this.sites = sites;
     this.loginProvider = loginProvider;
+    this.cookieProvider = new OAuthCookieProvider(TokenCipher.get());
   }
 
   @Override
@@ -90,50 +84,15 @@
 
     Cookie gerritCookie = getGerritCookie(httpRequest);
     try {
+      GitHubLogin ghLogin = loginProvider.get((HttpServletRequest) request);
+
       OAuthCookie authCookie =
           getOAuthCookie(httpRequest, (HttpServletResponse) response);
 
       if(OAuthProtocol.isOAuthLogout((HttpServletRequest) request)) {
-        getGitHubLogin(request).logout();
-        GitHubLogoutServletResponse bufferedResponse = new GitHubLogoutServletResponse((HttpServletResponse) response,
-            config.logoutRedirectUrl);
-        chain.doFilter(httpRequest, bufferedResponse);
-      } else if (((OAuthProtocol.isOAuthLogin(httpRequest) || OAuthProtocol.isOAuthFinal(httpRequest)) && authCookie == null)
-          || (authCookie == null && gerritCookie == null)) {
-        GitHubLogin ghLogin = getGitHubLogin(httpRequest);
-        if (OAuthProtocol.isOAuthFinal(httpRequest)) {
-
-          AccessToken authToken = ghLogin.getOAuthProtocol().loginPhase2(httpRequest, httpResponse);
-          GitHub hub = ghLogin.login(authToken);
-          GHMyself myself =
-              hub.getMyself();
-          String user = myself.getLogin();
-          String email = myself.getEmail();
-          String fullName =
-              Strings.emptyToNull(myself.getName()) == null ? user : myself
-                  .getName();
-
-          updateSecureConfigWithRetry(hub.getMyOrganizations().keySet(), user,
-              ghLogin.token.access_token);
-
-          if (user != null) {
-            OAuthCookie userCookie =
-                cookieProvider.getFromUser(user, email, fullName);
-            httpResponse.addCookie(userCookie);
-            httpResponse.sendRedirect(OAuthProtocol.getTargetUrl(request));
-            return;
-          } else {
-            httpResponse.sendError(HttpURLConnection.HTTP_UNAUTHORIZED,
-                "Login failed");
-          }
-        } else {
-          if (OAuthProtocol.isOAuthLogin(httpRequest)) {
-            ghLogin.getOAuthProtocol().loginPhase1(httpRequest, httpResponse);
-          } else {
-            chain.doFilter(request, response);
-          }
-        }
-        return;
+        logout(request, response, chain, httpRequest);
+      } else if ((OAuthProtocol.isOAuthLogin(httpRequest) || OAuthProtocol.isOAuthFinal(httpRequest)) && !ghLogin.isLoggedIn()) {        
+        login(request, httpRequest, httpResponse, ghLogin);
       } else {
         if (gerritCookie != null && !OAuthProtocol.isOAuthLogin(httpRequest)) {
           if (authCookie != null) {
@@ -171,6 +130,28 @@
     }
   }
 
+  private void login(ServletRequest request,
+      HttpServletRequest httpRequest, HttpServletResponse httpResponse,
+      GitHubLogin ghLogin) throws IOException {
+    if(ghLogin.login(httpRequest, httpResponse)) {
+      GHMyself myself =
+          ghLogin.getMyself();
+      String user = myself.getLogin();
+
+      updateSecureConfigWithRetry(ghLogin.hub.getMyOrganizations().keySet(), user,
+          ghLogin.token.access_token);
+    }
+  }
+
+  private void logout(ServletRequest request, ServletResponse response,
+      FilterChain chain, HttpServletRequest httpRequest) throws IOException,
+      ServletException {
+    getGitHubLogin(request).logout();
+    GitHubLogoutServletResponse bufferedResponse = new GitHubLogoutServletResponse((HttpServletResponse) response,
+        config.logoutRedirectUrl);
+    chain.doFilter(httpRequest, bufferedResponse);
+  }
+
   private GitHubLogin getGitHubLogin(ServletRequest request) {
     return loginProvider.get((HttpServletRequest) request);
   }
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 f90bf9d..5fd96b5 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
@@ -24,6 +24,7 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.base.Objects;
 import com.google.common.base.Strings;
 import com.google.gson.Gson;
 import com.google.inject.Inject;
@@ -74,6 +75,12 @@
       this.access_token = token;
       this.token_type = type;
     }
+
+    @Override
+    public String toString() {
+      return "AccessToken [access_token=" + access_token + ", token_type="
+          + token_type + "]";
+    }
   }
 
   @Inject
@@ -85,15 +92,22 @@
 
   public void loginPhase1(HttpServletRequest request,
       HttpServletResponse response, Scope... scopes) throws IOException {
+    String scopeRequested = request.getParameter("scope");
+    String baseScopeKey = Objects.firstNonNull(scopeRequested, "scopes");
     response.sendRedirect(String.format(
         "%s?client_id=%s%s&redirect_uri=%s&state=%s%s", config.gitHubOAuthUrl,
-        config.gitHubClientId, getScope(scopes),
+        config.gitHubClientId, getScope(baseScopeKey, scopes),
         getURLEncoded(config.oAuthFinalRedirectUrl),
         me(), getURLEncoded(request.getRequestURI().toString())));
   }
 
-  private String getScope(Scope[] scopes) {
-    HashSet<Scope> fullScopes = new HashSet<OAuthProtocol.Scope>(config.scopes);
+  private String getScope(String baseScopeKey, Scope[] scopes) {
+    List<Scope> baseScopes = config.scopes.get(baseScopeKey);
+    if(baseScopes == null) {
+      throw new IllegalArgumentException("Requested OAuth base scope id " + baseScopeKey + " is not configured in gerrit.config");
+    }
+
+    HashSet<Scope> fullScopes = new HashSet<OAuthProtocol.Scope>(baseScopes);
     fullScopes.addAll(Arrays.asList(scopes));
     
     if(fullScopes.size() <= 0) {
@@ -107,8 +121,7 @@
       }
       out.append(scope.getValue());
     }
-    return "&" +
-    		"scope=" + out.toString();
+    return "&" + "scope=" + out.toString();
   }
 
   public static boolean isOAuthFinal(HttpServletRequest request) {
@@ -207,4 +220,10 @@
     return targetUrl + (targetUrl.indexOf('?') < 0 ? '?' : '&') + "code="
         + code + "&state=" + state;
   }
+
+  @Override
+  public String toString() {
+    return "OAuthProtocol";
+  }
+
 }
diff --git a/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/TokenCipher.java b/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/TokenCipher.java
index 7a71fa5..58ac738 100644
--- a/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/TokenCipher.java
+++ b/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/TokenCipher.java
@@ -42,7 +42,9 @@
   private byte[] IV;
   private SecureRandom sessionRnd = new SecureRandom();
 
-  public TokenCipher() {
+  private static TokenCipher singleton = new TokenCipher();
+
+  private TokenCipher() {
     KeyGenerator kgen;
     try {
       kgen = KeyGenerator.getInstance(ENC_ALGO);
@@ -61,6 +63,10 @@
     }
   }
 
+  public static TokenCipher get() {
+    return singleton;
+  }
+
   public String encode(String clearText) throws OAuthTokenException {
     try {
       long sessionId = sessionRnd.nextLong();
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 0512d50..2081e11 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
@@ -24,6 +24,7 @@
 import com.google.gerrit.server.config.SitePaths;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
+import com.googlesource.gerrit.plugins.github.oauth.CompositeConfig;
 import com.googlesource.gerrit.plugins.github.oauth.GitHubOAuthConfig;
 
 @Singleton
@@ -61,7 +62,7 @@
 
 
   @Inject
-  public GitHubConfig(@GerritServerConfig Config config, final SitePaths site)
+  public GitHubConfig(CompositeConfig config, final SitePaths site)
       throws MalformedURLException {
     super(config);
     String[] wizardFlows =
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 bda7484..0c27d0f 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
@@ -23,6 +23,9 @@
 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;
@@ -32,6 +35,7 @@
 
 @Singleton
 public class GitHubOAuthFilter implements Filter {
+  private Logger LOG = LoggerFactory.getLogger(GitHubOAuthFilter.class);
 
   private final ScopedProvider<GitHubLogin> loginProvider;
   private final Scope[] authScopes;
@@ -40,7 +44,7 @@
   public GitHubOAuthFilter(final ScopedProvider<GitHubLogin> loginProvider,
       final GitHubOAuthConfig githubOAuthConfig) {
     this.loginProvider = loginProvider;
-    this.authScopes = githubOAuthConfig.scopes.toArray(new Scope[0]);
+    this.authScopes = githubOAuthConfig.getDefaultScopes();
   }
 
   @Override
@@ -51,6 +55,7 @@
   public void doFilter(ServletRequest request, ServletResponse response,
       FilterChain chain) throws IOException, ServletException {
     GitHubLogin hubLogin = loginProvider.get((HttpServletRequest) request);
+    LOG.debug("GitHub login: " + hubLogin);
     if (!hubLogin.isLoggedIn()) {
       hubLogin.login(request, response, authScopes);
       return;