Refactor the extraction of access tokens

Change-Id: Ib7bfaac995d53cd8fe5e730f5e17abcc2c6cc20f
Signed-off-by: Michael Ochmann <michael.ochmann@sap.com>
diff --git a/src/main/java/com/googlesource/gerrit/plugins/cfoauth/UAAClient.java b/src/main/java/com/googlesource/gerrit/plugins/cfoauth/UAAClient.java
index 611f317..e2ccc02 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/cfoauth/UAAClient.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/cfoauth/UAAClient.java
@@ -124,7 +124,12 @@
       throw new UAAClientException(MessageFormat.format(
           "POST /oauth/token failed with status {0}", response.getCode()));
     }
-    return parseAccessTokenResponse(response.getBody());
+    String tokenResponse = response.getBody();
+    if (Strings.isNullOrEmpty(tokenResponse)) {
+      throw new UAAClientException(
+          "POST /oauth/token failed: invalid access token response");
+    }
+    return parseAccessTokenResponse(tokenResponse);
   }
 
   /**
@@ -181,44 +186,41 @@
   @VisibleForTesting
   AccessToken parseAccessTokenResponse(String tokenResponse)
       throws UAAClientException {
-    if (Strings.isNullOrEmpty(tokenResponse)) {
-      throw new UAAClientException(
-          "Can't extract a token from an empty string");
-    }
-    JsonObject json = getAsJsonObject(tokenResponse);
-    String accessToken = getAttribute(json, ACCESS_TOKEN_ATTRIBUTE);
-    if (accessToken == null) {
-      throw new UAAClientException(
-          "Can't extract a token: missing or invalid 'access_token' attribute");
-    }
-    return toAccessToken(accessToken);
+    return toAccessToken(getAccessTokenAttribute(tokenResponse));
   }
 
   @VisibleForTesting
-  JsonObject toJsonWebToken(String accessToken)
-      throws UAAClientException {
+  JsonObject toJsonWebToken(String accessToken) throws UAAClientException {
+    String[] segments = getSegments(accessToken);
+    if (verifySignatures) {
+      verifySignature(segments);
+    }
+    return getAsJsonObject(decodeBase64(segments[1]));
+  }
+
+  private String[] getSegments(String accessToken) throws UAAClientException {
     String[] segments = accessToken.split("\\.");
     if (segments.length != 3) {
       throw new UAAClientException(
           "Invalid token: must be of the form 'header.token.signature'");
     }
-    String claims = decodeBase64(segments[1]);
-    if (verifySignatures) {
-      String header = decodeBase64(segments[0]);
-      String alg = getAttribute(getAsJsonObject(header), ALG_ATTRIBUTE);
-      if (Strings.isNullOrEmpty(alg)) {
-        throw new UAAClientException("Invalid token: missing \"alg\" attribute");
-      }
-      String signature = segments[2];
-      String signedContent = segments[0] + "." + segments[1];
-      verifySignature(signedContent, signature, alg);
+    return segments;
+  }
+
+  private void verifySignature(String[] segments) throws UAAClientException {
+    String header = decodeBase64(segments[0]);
+    String alg = getAttribute(getAsJsonObject(header), ALG_ATTRIBUTE);
+    if (Strings.isNullOrEmpty(alg)) {
+      throw new UAAClientException("Invalid token: missing \"alg\" attribute");
     }
-    return getAsJsonObject(claims);
+    String signature = segments[2];
+    String signedContent = segments[0] + "." + segments[1];
+    verifySignature(signedContent, signature, alg);
   }
 
   @VisibleForTesting
-  void verifySignature(String signedContent, String signature,
-      String alg) throws UAAClientException {
+  void verifySignature(String signedContent, String signature, String alg)
+      throws UAAClientException {
     SignatureVerifier verifier = getSignatureVerifier(alg, false);
     if (!verifier.verify(signedContent, signature)) {
       // If the signature is invalid, maybe the secret has changed
@@ -277,6 +279,17 @@
     return prim != null && prim.isString() ? prim.getAsString() : null;
   }
 
+  private String getAccessTokenAttribute(String tokenResponse)
+      throws UAAClientException {
+    JsonObject json = getAsJsonObject(tokenResponse);
+    String accessToken = getAttribute(json, ACCESS_TOKEN_ATTRIBUTE);
+    if (accessToken == null) {
+      throw new UAAClientException(
+          "Can't extract a token: missing or invalid 'access_token' attribute");
+    }
+    return accessToken;
+  }
+
   @VisibleForTesting
   long getLongAttribute(JsonObject json, String name, long defaultValue) {
     JsonPrimitive prim = getAsJsonPrimitive(json, name);