Add support for GitHub OAuth
diff --git a/BUCK b/BUCK
index a3df264..3216e67 100644
--- a/BUCK
+++ b/BUCK
@@ -2,12 +2,12 @@
 define_license('scribe')
 
 gerrit_plugin(
-  name = 'gerrit-google-oauth-provider',
+  name = 'gerrit-oauth-provider',
   srcs = glob(['src/main/java/**/*.java']),
   resources = glob(['src/main/resources/**/*']),
   manifest_entries = [
-    'Gerrit-PluginName: gerrit-google-oauth-provider',
-    'Gerrit-HttpModule: com.googlesource.gerrit.plugins.google.oauth.provider.HttpModule',
+    'Gerrit-PluginName: gerrit-oauth-provider',
+    'Gerrit-HttpModule: com.googlesource.gerrit.plugins.oauth.HttpModule',
   ],
   provided_deps = ['//lib:gson'],
   deps = [':scribe-oauth'],
@@ -15,7 +15,7 @@
 
 java_library(
   name = 'classpath',
-  deps = [':gerrit-google-oauth-provider__plugin'],
+  deps = [':gerrit-oauth-provider__plugin'],
 )
 
 maven_jar(
diff --git a/README.md b/README.md
index cf060b4..53d11e8 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,11 @@
-Google OAuth2 authentication provider for Gerrit Code Review
-============================================================
+OAuth2 authentication provider for Gerrit Code Review
+=====================================================
 
-This plugin depends on OAUTH extension point, exposed by this change: [1].
+This plugin depends on OAuth extension point, exposed by this change: [1].
+
+Currently the following OAuth providers are supported:
+
+* GitHub OAuth2
+* Google OAuth2
 
 [1] https://gerrit-review.googlesource.com/65101 
diff --git a/src/main/java/com/googlesource/gerrit/plugins/google/oauth/provider/HttpModule.java b/src/main/java/com/googlesource/gerrit/plugins/google/oauth/provider/HttpModule.java
deleted file mode 100644
index b3f2f0f..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/google/oauth/provider/HttpModule.java
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (C) 2015 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.google.oauth.provider;
-
-import com.google.gerrit.extensions.annotations.Exports;
-import com.google.gerrit.extensions.auth.oauth.OAuthServiceProvider;
-import com.google.gerrit.httpd.plugins.HttpPluginModule;
-
-public class HttpModule extends HttpPluginModule {
-  @Override
-  protected void configureServlets() {
-    bind(OAuthServiceProvider.class)
-        .annotatedWith(Exports.named("google_oauth"))
-        .to(GoogleOAuthService.class);
-  }
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/oauth/GitHub2Api.java b/src/main/java/com/googlesource/gerrit/plugins/oauth/GitHub2Api.java
new file mode 100644
index 0000000..a452397
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/oauth/GitHub2Api.java
@@ -0,0 +1,21 @@
+package com.googlesource.gerrit.plugins.oauth;
+
+import org.scribe.builder.api.DefaultApi20;
+import org.scribe.model.OAuthConfig;
+import org.scribe.utils.OAuthEncoder;
+
+public class GitHub2Api extends DefaultApi20 {
+  private static final String AUTHORIZE_URL =
+      "https://github.com/login/oauth/authorize?client_id=%s&redirect_uri=%s";
+
+  @Override
+  public String getAccessTokenEndpoint() {
+    return "https://github.com/login/oauth/access_token";
+  }
+
+  @Override
+  public String getAuthorizationUrl(OAuthConfig config) {
+    return String.format(AUTHORIZE_URL, config.getApiKey(),
+        OAuthEncoder.encode(config.getCallback()));
+  }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/google/oauth/provider/GoogleOAuthService.java b/src/main/java/com/googlesource/gerrit/plugins/oauth/GitHubOAuthService.java
similarity index 72%
copy from src/main/java/com/googlesource/gerrit/plugins/google/oauth/provider/GoogleOAuthService.java
copy to src/main/java/com/googlesource/gerrit/plugins/oauth/GitHubOAuthService.java
index 576baf9..a7959ee 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/google/oauth/provider/GoogleOAuthService.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/oauth/GitHubOAuthService.java
@@ -12,11 +12,12 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.googlesource.gerrit.plugins.google.oauth.provider;
+package com.googlesource.gerrit.plugins.oauth;
 
 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;
 import com.google.gerrit.extensions.auth.oauth.OAuthVerifier;
 import com.google.gerrit.server.OutputFormat;
 import com.google.gerrit.server.config.PluginConfig;
@@ -36,20 +37,24 @@
 
 import java.io.IOException;
 
+import javax.servlet.http.HttpServletResponse;
+
 @Singleton
-class GoogleOAuthService implements OAuthServiceProvider {
+class GitHubOAuthService implements OAuthServiceProvider {
+  static final String CONFIG_SUFFIX = "-github-oauth";
   private static final String PROTECTED_RESOURCE_URL =
-      "https://www.googleapis.com/oauth2/v2/userinfo?alt=json";
-  private static final String SCOPE =
-      "https://mail.google.com/ https://www.googleapis.com/auth/userinfo.email";
+      "https://api.github.com/user";
+
+  private static final String SCOPE = "user:email";
   private final OAuthService service;
 
   @Inject
-  GoogleOAuthService(PluginConfigFactory cfgFactory,
+  GitHubOAuthService(PluginConfigFactory cfgFactory,
       @PluginName String pluginName) {
-    PluginConfig cfg = cfgFactory.getFromGerritConfig(pluginName);
+    PluginConfig cfg = cfgFactory.getFromGerritConfig(
+        pluginName + CONFIG_SUFFIX);
     service = new ServiceBuilder()
-        .provider(Google2Api.class)
+        .provider(GitHub2Api.class)
         .apiKey(cfg.getString("client-id"))
         .apiSecret(cfg.getString("client-secret"))
         .callback(cfg.getString("callback"))
@@ -63,27 +68,30 @@
   }
 
   @Override
-  public String getUsername(OAuthToken token) throws IOException {
+  public OAuthUserInfo getUserInfo(OAuthToken token) throws IOException {
     OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL);
     Token t =
         new Token(token.getToken(), token.getSecret(), token.getRaw());
     service.signRequest(t, request);
     Response response = request.send();
+    if (response.getCode() != HttpServletResponse.SC_OK) {
+      throw new IOException(String.format("Status %s (%s) for request %s",
+          response.getCode(), response.getBody(), request.getUrl()));
+    }
     JsonElement userJson =
         OutputFormat.JSON.newGson().fromJson(response.getBody(),
             JsonElement.class);
     if (userJson.isJsonObject()) {
       JsonObject jsonObject = userJson.getAsJsonObject();
-      JsonElement jsonElement = jsonObject.getAsJsonObject().get("name");
-      if (jsonElement != null) {
-        return jsonElement.getAsString();
-      } else {
-        throw new IOException(String.format(
-            "Invalid JSON '%s': cannot find login field", userJson));
-      }
+      JsonElement email = jsonObject.get("email");
+      JsonElement name = jsonObject.get("name");
+      JsonElement id = jsonObject.get("id");
+      return new OAuthUserInfo(id.getAsString(),
+          email.isJsonNull() ? null : email.getAsString(),
+          name.isJsonNull() ? null : name.getAsString());
     } else {
-      throw new IOException(String.format(
-          "Invalid JSON '%s': not a JSON Object", userJson));
+        throw new IOException(String.format(
+            "Invalid JSON '%s': not a JSON Object", userJson));
     }
   }
 
@@ -117,6 +125,6 @@
 
   @Override
   public String getName() {
-    return "Google OAuth2";
+    return "GitHub OAuth2";
   }
 }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/google/oauth/provider/Google2Api.java b/src/main/java/com/googlesource/gerrit/plugins/oauth/Google2Api.java
similarity index 98%
rename from src/main/java/com/googlesource/gerrit/plugins/google/oauth/provider/Google2Api.java
rename to src/main/java/com/googlesource/gerrit/plugins/oauth/Google2Api.java
index d88cf83..7b4f4bf 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/google/oauth/provider/Google2Api.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/oauth/Google2Api.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.googlesource.gerrit.plugins.google.oauth.provider;
+package com.googlesource.gerrit.plugins.oauth;
 
 import static org.scribe.utils.OAuthEncoder.encode;
 
diff --git a/src/main/java/com/googlesource/gerrit/plugins/google/oauth/provider/GoogleOAuthService.java b/src/main/java/com/googlesource/gerrit/plugins/oauth/GoogleOAuthService.java
similarity index 75%
rename from src/main/java/com/googlesource/gerrit/plugins/google/oauth/provider/GoogleOAuthService.java
rename to src/main/java/com/googlesource/gerrit/plugins/oauth/GoogleOAuthService.java
index 576baf9..db24967 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/google/oauth/provider/GoogleOAuthService.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/oauth/GoogleOAuthService.java
@@ -12,11 +12,12 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.googlesource.gerrit.plugins.google.oauth.provider;
+package com.googlesource.gerrit.plugins.oauth;
 
 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;
 import com.google.gerrit.extensions.auth.oauth.OAuthVerifier;
 import com.google.gerrit.server.OutputFormat;
 import com.google.gerrit.server.config.PluginConfig;
@@ -36,18 +37,21 @@
 
 import java.io.IOException;
 
+import javax.servlet.http.HttpServletResponse;
+
 @Singleton
 class GoogleOAuthService implements OAuthServiceProvider {
+  static final String CONFIG_SUFFIX = "-google-oauth";
   private static final String PROTECTED_RESOURCE_URL =
-      "https://www.googleapis.com/oauth2/v2/userinfo?alt=json";
-  private static final String SCOPE =
-      "https://mail.google.com/ https://www.googleapis.com/auth/userinfo.email";
+  "https://www.googleapis.com/plus/v1/people/me/openIdConnect";
+  private static final String SCOPE = "email profile";
   private final OAuthService service;
 
   @Inject
   GoogleOAuthService(PluginConfigFactory cfgFactory,
       @PluginName String pluginName) {
-    PluginConfig cfg = cfgFactory.getFromGerritConfig(pluginName);
+    PluginConfig cfg = cfgFactory.getFromGerritConfig(
+        pluginName + CONFIG_SUFFIX);
     service = new ServiceBuilder()
         .provider(Google2Api.class)
         .apiKey(cfg.getString("client-id"))
@@ -63,27 +67,30 @@
   }
 
   @Override
-  public String getUsername(OAuthToken token) throws IOException {
+  public OAuthUserInfo getUserInfo(OAuthToken token) throws IOException {
     OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL);
     Token t =
         new Token(token.getToken(), token.getSecret(), token.getRaw());
     service.signRequest(t, request);
     Response response = request.send();
+    if (response.getCode() != HttpServletResponse.SC_OK) {
+      throw new IOException(String.format("Status %s (%s) for request %s",
+          response.getCode(), response.getBody(), request.getUrl()));
+    }
     JsonElement userJson =
         OutputFormat.JSON.newGson().fromJson(response.getBody(),
             JsonElement.class);
     if (userJson.isJsonObject()) {
       JsonObject jsonObject = userJson.getAsJsonObject();
-      JsonElement jsonElement = jsonObject.getAsJsonObject().get("name");
-      if (jsonElement != null) {
-        return jsonElement.getAsString();
-      } else {
-        throw new IOException(String.format(
-            "Invalid JSON '%s': cannot find login field", userJson));
-      }
+      JsonElement email = jsonObject.get("email");
+      JsonElement name = jsonObject.get("name");
+      JsonElement id = jsonObject.get("sub");
+      return new OAuthUserInfo(id.getAsString(),
+          email.isJsonNull() ? null : email.getAsString(),
+          name.isJsonNull() ? null : name.getAsString());
     } else {
-      throw new IOException(String.format(
-          "Invalid JSON '%s': not a JSON Object", userJson));
+        throw new IOException(String.format(
+            "Invalid JSON '%s': not a JSON Object", userJson));
     }
   }
 
diff --git a/src/main/java/com/googlesource/gerrit/plugins/oauth/HttpModule.java b/src/main/java/com/googlesource/gerrit/plugins/oauth/HttpModule.java
new file mode 100644
index 0000000..17bf3a3
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/oauth/HttpModule.java
@@ -0,0 +1,55 @@
+// Copyright (C) 2015 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.oauth;
+
+import com.google.gerrit.extensions.annotations.Exports;
+import com.google.gerrit.extensions.annotations.PluginName;
+import com.google.gerrit.extensions.auth.oauth.OAuthServiceProvider;
+import com.google.gerrit.httpd.plugins.HttpPluginModule;
+import com.google.gerrit.server.config.PluginConfig;
+import com.google.gerrit.server.config.PluginConfigFactory;
+import com.google.inject.Inject;
+
+public class HttpModule extends HttpPluginModule {
+
+  private final PluginConfigFactory cfgFactory;
+  private final String pluginName;
+
+  @Inject
+  HttpModule(PluginConfigFactory cfgFactory,
+      @PluginName String pluginName) {
+    this.cfgFactory = cfgFactory;
+    this.pluginName = pluginName;
+  }
+
+  @Override
+  protected void configureServlets() {
+    PluginConfig cfg = cfgFactory.getFromGerritConfig(
+        pluginName + GoogleOAuthService.CONFIG_SUFFIX);
+    if (cfg.getString("client-id") != null) {
+      bind(OAuthServiceProvider.class)
+          .annotatedWith(Exports.named(GoogleOAuthService.CONFIG_SUFFIX))
+          .to(GoogleOAuthService.class);
+    }
+
+    cfg = cfgFactory.getFromGerritConfig(
+        pluginName + GitHubOAuthService.CONFIG_SUFFIX);
+    if (cfg.getString("client-id") != null) {
+      bind(OAuthServiceProvider.class)
+          .annotatedWith(Exports.named(GitHubOAuthService.CONFIG_SUFFIX))
+          .to(GitHubOAuthService.class);
+    }
+  }
+}