Allow JSON token extractor to be used with CAS

Add config boolean to use JSON token extraction rather than the regex
based extractor for plain text responses.

Support for JSON token responses was added in CAS v6.1.0:

 https://github.com/apereo/cas/pull/1645

Support for plain text seems to have been removed in the same release
by this commit:

 https://github.com/apereo/cas/commit/c9b555386f7e165d98d6616b4294

Default behaviour unchanged to continue to support CAS v5 users.

Bug: Issue 16232
Change-Id: I15f195001e5ee823f3832388b23c6b2f2dbb3cd4
diff --git a/src/main/java/com/googlesource/gerrit/plugins/oauth/CasApi.java b/src/main/java/com/googlesource/gerrit/plugins/oauth/CasApi.java
index 450549f..6c06b24 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/oauth/CasApi.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/oauth/CasApi.java
@@ -16,6 +16,7 @@
 
 import com.github.scribejava.core.builder.api.DefaultApi20;
 import com.github.scribejava.core.extractors.OAuth2AccessTokenExtractor;
+import com.github.scribejava.core.extractors.OAuth2AccessTokenJsonExtractor;
 import com.github.scribejava.core.extractors.TokenExtractor;
 import com.github.scribejava.core.model.OAuth2AccessToken;
 import com.github.scribejava.core.oauth2.bearersignature.BearerSignature;
@@ -25,8 +26,13 @@
   private static final String AUTHORIZE_URL = "%s/oauth2.0/authorize";
 
   private final String rootUrl;
+  private final TokenExtractor<OAuth2AccessToken> tokenExtractor;
 
-  public CasApi(String rootUrl) {
+  public CasApi(String rootUrl, boolean useJsonExtractor) {
+    this.tokenExtractor =
+        useJsonExtractor
+            ? OAuth2AccessTokenJsonExtractor.instance()
+            : OAuth2AccessTokenExtractor.instance();
     this.rootUrl = rootUrl;
   }
 
@@ -47,6 +53,6 @@
 
   @Override
   public TokenExtractor<OAuth2AccessToken> getAccessTokenExtractor() {
-    return OAuth2AccessTokenExtractor.instance();
+    return tokenExtractor;
   }
 }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/oauth/CasOAuthService.java b/src/main/java/com/googlesource/gerrit/plugins/oauth/CasOAuthService.java
index b282a84..447b145 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/oauth/CasOAuthService.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/oauth/CasOAuthService.java
@@ -52,6 +52,7 @@
   static final String CONFIG_SUFFIX = "-cas-oauth";
   private static final String CAS_PROVIDER_PREFIX = "cas-oauth:";
   private static final String PROTECTED_RESOURCE_URL = "%s/oauth2.0/profile";
+  private static final String USE_JSON_EXTRACTOR = "use-json-extractor";
 
   private final String rootUrl;
   private final boolean fixLegacyUserId;
@@ -69,11 +70,12 @@
     }
     String canonicalWebUrl = CharMatcher.is('/').trimTrailingFrom(urlProvider.get()) + "/";
     fixLegacyUserId = cfg.getBoolean(InitOAuth.FIX_LEGACY_USER_ID, false);
+    boolean useJsonExtractor = cfg.getBoolean(USE_JSON_EXTRACTOR, false);
     service =
         new ServiceBuilder(cfg.getString(InitOAuth.CLIENT_ID))
             .apiSecret(cfg.getString(InitOAuth.CLIENT_SECRET))
             .callback(canonicalWebUrl + "oauth")
-            .build(new CasApi(rootUrl));
+            .build(new CasApi(rootUrl, useJsonExtractor));
   }
 
   @Override
diff --git a/src/main/resources/Documentation/config.md b/src/main/resources/Documentation/config.md
index 91d7288..0ccb809 100644
--- a/src/main/resources/Documentation/config.md
+++ b/src/main/resources/Documentation/config.md
@@ -27,6 +27,7 @@
     root-url = "<cas url>"
     client-id = "<client-id>"
     client-secret = "<client-secret>"
+    use-json-extractor = false
 
   [plugin "@PLUGIN@-gitlab-oauth"]
     root-url = "<gitlab url>"
@@ -122,7 +123,8 @@
 
 is required, since CAS is a self-hosted application.
 
-Note that the CAS OAuth plugin only supports CAS V5 and higher.
+Note that the CAS OAuth plugin only supports CAS V5 and higher. Both plain text
+and JSON responses are supported (see configuration).
 
 The plugin expects CAS to make several attributes available to it:
 
diff --git a/src/test/java/com/googlesource/gerrit/plugins/oauth/CasApiTest.java b/src/test/java/com/googlesource/gerrit/plugins/oauth/CasApiTest.java
index 17d0ca3..f85c316 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/oauth/CasApiTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/oauth/CasApiTest.java
@@ -17,19 +17,20 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import com.github.scribejava.core.extractors.OAuth2AccessTokenExtractor;
-import org.junit.Before;
+import com.github.scribejava.core.extractors.OAuth2AccessTokenJsonExtractor;
 import org.junit.Test;
 
 public class CasApiTest {
-  private CasApi api;
-
-  @Before
-  public void setUp() {
-    api = new CasApi("");
-  }
 
   @Test
   public void testAccessTokenExtractor() {
+    CasApi api = new CasApi("", false);
     assertThat(api.getAccessTokenExtractor()).isInstanceOf(OAuth2AccessTokenExtractor.class);
   }
+
+  @Test
+  public void testJsonAccessTokenExtractor() {
+    CasApi api = new CasApi("", true);
+    assertThat(api.getAccessTokenExtractor()).isInstanceOf(OAuth2AccessTokenJsonExtractor.class);
+  }
 }