Refactor OAuth handshake: remove usage of GerritOAuth cookie

The GerritOAuth cookie is now obsolete as we do rely on a shared
GHLogin object in the HTTP Session. Whenever the session expires or
is lost, the situation is detected and automatically recovered by
triggering a new OAuth handshake with GitHub.

The session GHLogin object is used as well to remember the user
scopes and username for HTTP Header enrichment.

Change-Id: Ibede5c16995f6659c8401c6d5083d44f1185e0ba
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 69f94da..6fb6fbe 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
@@ -14,6 +14,8 @@
 
 package com.googlesource.gerrit.plugins.github.oauth;
 
+import static java.util.concurrent.TimeUnit.DAYS;
+
 import java.io.IOException;
 import java.util.Arrays;
 import java.util.HashSet;
@@ -34,26 +36,24 @@
 import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Objects;
-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;
-import static java.util.concurrent.TimeUnit.*;
 
 public class GitHubLogin {
   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 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);
+  private static final long SCOPE_COOKIE_NEVER_EXPIRES = DAYS
+      .toSeconds(50 * YEARS);
 
   @Singleton
   public static class Provider extends HttpSessionProvider<GitHubLogin> {
     @Override
     public GitHubLogin get(HttpServletRequest request) {
-      GitHubLogin login = super.get(request);
-      login.initOAuthCookie(request);
-      return login;
+      return super.get(request);
     }
   }
 
@@ -64,9 +64,7 @@
 
   private GHMyself myself;
   private SortedSet<Scope> loginScopes;
-  private final OAuthCookieProvider cookieProvider;
   private final GitHubOAuthConfig config;
-  private OAuthCookie oAuthCookie;
 
   public GHMyself getMyself() {
     if (isLoggedIn()) {
@@ -79,7 +77,6 @@
   @Inject
   public GitHubLogin(final OAuthProtocol oauth, final GitHubOAuthConfig config) {
     this.oauth = oauth;
-    this.cookieProvider = new OAuthCookieProvider(TokenCipher.get(), config);
     this.config = config;
   }
 
@@ -97,25 +94,6 @@
     return loggedIn;
   }
 
-  private void initOAuthCookie(HttpServletRequest request) {
-    for (Cookie cookie : getCookies(request)) {
-      if (cookie.getName().equalsIgnoreCase(OAuthCookie.OAUTH_COOKIE_NAME)
-          && !Strings.isNullOrEmpty(cookie.getValue())) {
-        try {
-          oAuthCookie = cookieProvider.getFromCookie(cookie);
-          loginScopes = oAuthCookie.scopes;
-        } catch (OAuthTokenException e) {
-          LOG.warn("Invalid cookie detected", e);
-        }
-      }
-    }
-  }
-
-  private Cookie[] getCookies(HttpServletRequest httpRequest) {
-    Cookie[] cookies = httpRequest.getCookies();
-    return cookies == null ? new Cookie[0] : cookies;
-  }
-
   public boolean login(ServletRequest request, ServletResponse response,
       Scope... scopes) throws IOException {
     return login((HttpServletRequest) request, (HttpServletResponse) response,
@@ -135,16 +113,6 @@
       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, loginScopes);
-        response.addCookie(userCookie);
-
         response.sendRedirect(OAuthProtocol.getTargetUrl(request));
         return true;
       } else {
@@ -181,13 +149,14 @@
         + loginScopes + "]";
   }
 
-  private String getScopesKey(HttpServletRequest request, HttpServletResponse response) {
+  private String getScopesKey(HttpServletRequest request,
+      HttpServletResponse response) {
     String scopeRequested = request.getParameter("scope");
-    if(scopeRequested == null) {
+    if (scopeRequested == null) {
       scopeRequested = getScopesKeyFromCookie(request);
     }
 
-    if(scopeRequested != null) {
+    if (scopeRequested != null) {
       Cookie scopeCookie = new Cookie("scope", scopeRequested);
       scopeCookie.setPath("/");
       scopeCookie.setMaxAge((int) SCOPE_COOKIE_NEVER_EXPIRES);
@@ -199,12 +168,12 @@
 
   private String getScopesKeyFromCookie(HttpServletRequest request) {
     Cookie[] cookies = request.getCookies();
-    if(cookies == null) {
+    if (cookies == null) {
       return null;
     }
 
-    for(Cookie cookie : cookies) {
-      if(cookie.getName().equalsIgnoreCase("scope")) {
+    for (Cookie cookie : cookies) {
+      if (cookie.getName().equalsIgnoreCase("scope")) {
         return cookie.getValue();
       }
     }
@@ -212,16 +181,14 @@
   }
 
   private SortedSet<Scope> getScopes(String baseScopeKey, Scope... scopes) {
-    HashSet<Scope> fullScopes =
-        oAuthCookie == null ? new HashSet<Scope>(
-            scopesForKey(baseScopeKey)) : new HashSet<Scope>(
-            oAuthCookie.scopes);
+    HashSet<Scope> fullScopes = new HashSet<Scope>(scopesForKey(baseScopeKey));
     fullScopes.addAll(Arrays.asList(scopes));
 
     return new TreeSet<Scope>(fullScopes);
   }
 
   private List<Scope> scopesForKey(String baseScopeKey) {
-    return Objects.firstNonNull(config.scopes.get(baseScopeKey), DEFAULT_SCOPES);
+    return Objects
+        .firstNonNull(config.scopes.get(baseScopeKey), DEFAULT_SCOPES);
   }
 }
diff --git a/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/OAuthCookie.java b/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/OAuthCookie.java
deleted file mode 100644
index 9df3190..0000000
--- a/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/OAuthCookie.java
+++ /dev/null
@@ -1,84 +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 java.util.SortedSet;
-import java.util.TreeSet;
-
-import javax.servlet.http.Cookie;
-
-import com.googlesource.gerrit.plugins.github.oauth.OAuthProtocol.Scope;
-
-public class OAuthCookie extends Cookie {
-  private static final long serialVersionUID = 2771690299147135167L;
-  public static final String OAUTH_COOKIE_NAME = "GerritOAuth";
-  public static final OAuthCookie ANONYMOUS = new OAuthCookie();
-
-  public final String user;
-  public final String email;
-  public final String fullName;
-  public final SortedSet<Scope> scopes;
-
-  public OAuthCookie(TokenCipher cipher, final String user, final String email,
-      final String fullName, final SortedSet<Scope> scopes, final long maxAgeSeconds) throws OAuthTokenException {
-    super(OAUTH_COOKIE_NAME, cipher.encode(getClearTextCookie(user, email, fullName, scopes)));
-    this.user = user;
-    this.email = email;
-    this.fullName = fullName;
-    this.scopes = scopes;
-    setMaxAge((int) maxAgeSeconds);
-    setHttpOnly(true);
-    setPath("/");
-  }
-
-  private static String getClearTextCookie(final String user,
-      final String email, final String fullName, final SortedSet<Scope> scopes) {
-    StringBuilder clearTextCookie = new StringBuilder();
-    clearTextCookie.append(user);
-    clearTextCookie.append("\n");
-    clearTextCookie.append(email);
-    clearTextCookie.append("\n");
-    clearTextCookie.append(fullName);
-
-    for (Scope scope : scopes) {
-      clearTextCookie.append("\n");
-      clearTextCookie.append(scope);
-    }
-    return clearTextCookie.toString();
-  }
-
-  private OAuthCookie() {
-    super(OAUTH_COOKIE_NAME, "");
-    this.user = "";
-    this.scopes = null;
-    this.fullName = "";
-    this.email = "";
-  }
-
-  public OAuthCookie(TokenCipher cipher, Cookie cookie)
-      throws OAuthTokenException {
-    super(OAUTH_COOKIE_NAME, cookie.getValue());
-    String clearTextValue = cipher.decode(cookie.getValue());
-    String[] clearText = clearTextValue.split("\n");
-    user = clearText.length > 0 ? clearText[0]:null;
-    email = clearText.length > 1 ? clearText[1]:null;
-    fullName = clearText.length > 2 ? clearText[2]:null;
-
-    this.scopes = new TreeSet<Scope>();
-    for (int i = 3; i < clearText.length; i++) {
-      Scope scope = Enum.valueOf(Scope.class, clearText[i]);
-      this.scopes.add(scope);
-    }
-  }
-}
diff --git a/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/OAuthCookieProvider.java b/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/OAuthCookieProvider.java
deleted file mode 100644
index 293abef..0000000
--- a/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/OAuthCookieProvider.java
+++ /dev/null
@@ -1,53 +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 static java.util.concurrent.TimeUnit.SECONDS;
-
-import java.util.SortedSet;
-
-import javax.servlet.http.Cookie;
-
-import com.google.gerrit.server.config.ConfigUtil;
-import com.googlesource.gerrit.plugins.github.oauth.OAuthProtocol.Scope;
-
-public class OAuthCookieProvider {
-  private static final String CACHE_NAME = "web_sessions";
-
-  private TokenCipher cipher;
-  private GitHubOAuthConfig config;
-
-
-  public OAuthCookieProvider(TokenCipher cipher, GitHubOAuthConfig config) {
-    this.cipher = cipher;
-    this.config = config;
-  }
-
-  public OAuthCookie getFromUser(String username, String email, String fullName, SortedSet<Scope> scopes) {
-    try {
-      return new OAuthCookie(cipher, username, email, fullName, scopes, getGerritSessionMaxAgeMillis());
-    } catch (OAuthTokenException e) {
-      return null;
-    }
-  }
-
-  public OAuthCookie getFromCookie(Cookie cookie) throws OAuthTokenException {
-      return new OAuthCookie(cipher, cookie);
-  }
-
-  private long getGerritSessionMaxAgeMillis() {
-    return ConfigUtil.getTimeUnit(config.gerritConfig, "cache", CACHE_NAME,
-        "maxAge", TokenCipher.MAX_COOKIE_TIMEOUT_SECS, SECONDS);
-  }
-}
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 26793e2..326ad23 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
@@ -24,7 +24,6 @@
 import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.TreeSet;
 import java.util.concurrent.ExecutionException;
 
 import javax.servlet.Filter;
@@ -55,7 +54,6 @@
 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;
 
 @Singleton
 public class OAuthGitFilter implements Filter {
@@ -71,8 +69,8 @@
   private final AccountCache accountCache;
   private final GitHubHttpProvider httpClientProvider;
   private final GitHubOAuthConfig config;
-  private final OAuthCookieProvider cookieProvider;
   private final XGerritAuth xGerritAuth;
+  private ScopedProvider<GitHubLogin> ghLoginProvider;
 
   public static class BasicAuthHttpRequest extends HttpServletRequestWrapper {
     private HashMap<String, String> headers = new HashMap<String, String>();
@@ -122,12 +120,12 @@
     this.accountCache = accountCache;
     this.httpClientProvider = httpClientProvider;
     this.config = config;
-    this.cookieProvider = new OAuthCookieProvider(TokenCipher.get(), config);
     this.xGerritAuth = xGerritAuth;
   }
 
   @Override
   public void init(FilterConfig filterConfig) throws ServletException {
+    this.ghLoginProvider = new GitHubLogin.Provider();
   }
 
   @Override
@@ -137,32 +135,29 @@
     HttpServletRequest httpRequest = (HttpServletRequest) request;
     HttpServletResponse httpResponse =
         new OAuthGitWrappedResponse((HttpServletResponse) response);
-    log.debug("OAuthGitFilter(" + httpRequest.getRequestURL() + ") code="
-        + request.getParameter("code"));
+    GitHubLogin ghLogin = ghLoginProvider.get(httpRequest);
+    log.debug("OAuthGitFilter(" + httpRequest.getRequestURL() + ") ghLogin="
+        + ghLogin);
 
-    OAuthCookie oAuthCookie =
-        getAuthenticationCookieFromGitRequestUsingOAuthToken(httpRequest,
+    String username =
+        getAuthenticatedUserFromGitRequestUsingOAuthToken(httpRequest,
             httpResponse);
-    if (oAuthCookie == null) {
+    if (username == null) {
       return;
     }
     String gerritPassword =
-        oAuthCookie == OAuthCookie.ANONYMOUS ? null : accountCache
-            .getByUsername(oAuthCookie.user).getPassword(oAuthCookie.user);
+        accountCache.getByUsername(username).getPassword(username);
 
-    if (gerritPassword == null && oAuthCookie != OAuthCookie.ANONYMOUS) {
+    if (gerritPassword == null) {
       gerritPassword =
-          generateRandomGerritPassword(oAuthCookie, httpRequest, httpResponse,
+          generateRandomGerritPassword(username, httpRequest, httpResponse,
               chain);
       httpResponse.sendRedirect(getRequestPathWithQueryString(httpRequest));
       return;
     }
 
-    if (oAuthCookie != OAuthCookie.ANONYMOUS) {
-      httpRequest =
-          new BasicAuthHttpRequest(httpRequest, oAuthCookie.user,
-              gerritPassword);
-    }
+    httpRequest =
+        new BasicAuthHttpRequest(httpRequest, username, gerritPassword);
 
     chain.doFilter(httpRequest, httpResponse);
   }
@@ -175,21 +170,20 @@
     return requestPathWithQueryString;
   }
 
-  private String generateRandomGerritPassword(OAuthCookie oAuthCookie,
+  private String generateRandomGerritPassword(String username,
       HttpServletRequest httpRequest, HttpServletResponse httpResponse,
       FilterChain chain) throws IOException, ServletException {
-    log.warn("User " + oAuthCookie.user + " has not a Gerrit HTTP password: "
+    log.warn("User " + username + " has not a Gerrit HTTP password: "
         + "generating a random one in order to be able to use Git over HTTP");
     Cookie gerritCookie =
-        getGerritLoginCookie(oAuthCookie.user, httpRequest, httpResponse, chain);
+        getGerritLoginCookie(username, httpRequest, httpResponse, chain);
     String xGerritAuthValue = xGerritAuth.getAuthValue(gerritCookie);
 
     HttpPut putRequest =
         new HttpPut(getRequestUrlWithAlternatePath(httpRequest,
             "/accounts/self/password.http"));
     putRequest.setHeader("Cookie",
-        gerritCookie.getName() + "=" + gerritCookie.getValue() + "; "
-            + oAuthCookie.getName() + "=" + oAuthCookie.getValue());
+        gerritCookie.getName() + "=" + gerritCookie.getValue());
     putRequest.setHeader(XGerritAuth.X_GERRIT_AUTH, xGerritAuthValue);
 
     putRequest.setEntity(new StringEntity("{\"generate\":true}",
@@ -197,12 +191,10 @@
     HttpResponse putResponse = httpClientProvider.get().execute(putRequest);
     if (putResponse.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
       throw new ServletException(
-          "Cannot generate HTTP password for authenticating user "
-              + oAuthCookie.user);
+          "Cannot generate HTTP password for authenticating user " + username);
     }
 
-    return accountCache.getByUsername(oAuthCookie.user).getPassword(
-        oAuthCookie.user);
+    return accountCache.getByUsername(username).getPassword(username);
   }
 
   private URI getRequestUrlWithAlternatePath(HttpServletRequest httpRequest,
@@ -235,11 +227,11 @@
     return loginResponse.getGerritCookie();
   }
 
-  private OAuthCookie getAuthenticationCookieFromGitRequestUsingOAuthToken(
+  private String getAuthenticatedUserFromGitRequestUsingOAuthToken(
       HttpServletRequest req, HttpServletResponse rsp) throws IOException {
     final String httpBasicAuth = getHttpBasicAuthenticationHeader(req);
     if (httpBasicAuth == null) {
-      return OAuthCookie.ANONYMOUS;
+      return null;
     }
 
     if (isInvalidHttpAuthenticationHeader(httpBasicAuth)) {
@@ -256,7 +248,7 @@
     }
 
     if (!oauthKeyword.equalsIgnoreCase(GITHUB_X_OAUTH_BASIC)) {
-      return OAuthCookie.ANONYMOUS;
+      return null;
     }
 
     boolean loginSuccessful = false;
@@ -275,7 +267,7 @@
       return null;
     }
 
-    return cookieProvider.getFromUser(oauthLogin, "", "", new TreeSet<Scope>());
+    return oauthLogin;
   }
 
 
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
deleted file mode 100644
index 042a301..0000000
--- a/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/TokenCipher.java
+++ /dev/null
@@ -1,127 +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 static java.util.concurrent.TimeUnit.HOURS;
-
-import java.net.URLDecoder;
-import java.net.URLEncoder;
-import java.security.NoSuchAlgorithmException;
-import java.security.SecureRandom;
-
-import javax.crypto.Cipher;
-import javax.crypto.KeyGenerator;
-import javax.crypto.SecretKey;
-import javax.crypto.spec.IvParameterSpec;
-
-import org.slf4j.Logger;
-
-import com.google.inject.Singleton;
-
-@Singleton
-public class TokenCipher {
-  private static final String UTF8 = "UTF-8";
-  private static final String ENC_ALGO_PADDING = "AES/CBC/PKCS5Padding";
-  private static final String JCE_PROVIDER = "SunJCE";
-  private static final String ENC_ALGO = "AES";
-  private static final Logger log = org.slf4j.LoggerFactory
-      .getLogger(OAuthCookieProvider.class);
-  public static final Long MAX_COOKIE_TIMEOUT_SECS = HOURS.toSeconds(12);
-
-  private SecretKey aesKey;
-  private byte[] IV;
-  private SecureRandom sessionRnd = new SecureRandom();
-
-  private static TokenCipher singleton = new TokenCipher();
-
-  private TokenCipher() {
-    KeyGenerator kgen;
-    try {
-      kgen = KeyGenerator.getInstance(ENC_ALGO);
-      kgen.init(128);
-      SecureRandom sr = new SecureRandom();
-      sr.setSeed(System.currentTimeMillis());
-      byte[] key = new byte[16];
-      IV = new byte[16];
-      sr.nextBytes(key);
-      sr.nextBytes(IV);
-      aesKey = kgen.generateKey();
-      sessionRnd.setSeed(System.currentTimeMillis());
-    } catch (NoSuchAlgorithmException e) {
-      log.error("Cannot find encryption algorithm " + ENC_ALGO);
-      throw new IllegalArgumentException(e);
-    }
-  }
-
-  public static TokenCipher get() {
-    return singleton;
-  }
-
-  public String encode(String clearText) throws OAuthTokenException {
-    try {
-      long sessionId = sessionRnd.nextLong();
-      long ts = System.currentTimeMillis();
-      String userSession =
-          String.format("%d/%d/%s", sessionId, ts,
-              URLEncoder.encode(clearText, UTF8));
-      byte[] plainText =
-          (userSession + "/" + userSession.hashCode()).getBytes(UTF8);
-
-      Cipher cipher = Cipher.getInstance(ENC_ALGO_PADDING, JCE_PROVIDER);
-      cipher.init(Cipher.ENCRYPT_MODE, aesKey, new IvParameterSpec(IV));
-      byte[] enc = cipher.doFinal(plainText);
-      return org.eclipse.jgit.util.Base64.encodeBytes(enc).trim();
-    } catch (Exception e) {
-      log.error("Encryption failed", e);
-      throw new OAuthTokenException("Cannot generate token for "
-          + clearText, e);
-    }
-  }
-  
-  public String decode(String sessionToken) throws OAuthTokenException {
-    try {
-      byte[] enc =
-          org.eclipse.jgit.util.Base64.decode(sessionToken.trim().getBytes(),
-              0, sessionToken.length());
-      Cipher cipher = Cipher.getInstance(ENC_ALGO_PADDING, JCE_PROVIDER);
-      cipher.init(Cipher.DECRYPT_MODE, aesKey, new IvParameterSpec(IV));
-
-      String[] clearTextParts =
-          new String(cipher.doFinal(enc), UTF8).split("/");
-
-      isValid(sessionToken, clearTextParts);
-
-      return URLDecoder.decode(clearTextParts[2], UTF8);
-    } catch (Exception e) {
-      log.error("Decryption failed", e);
-      throw new OAuthTokenException("Invalid session token " + sessionToken, e);
-    }
-  }
-
-  private void isValid(String sessionToken, String[] clearTextParts)
-      throws OAuthTokenException {
-    int hashCode = Integer.parseInt(clearTextParts[3]);
-    if (hashCode != (clearTextParts[0] + "/" + clearTextParts[1] + "/" + clearTextParts[2])
-        .hashCode()) {
-      throw new OAuthTokenException("Invalid or forged token " + sessionToken);
-    }
-
-    long ts = Long.parseLong(clearTextParts[1]);
-    if (((System.currentTimeMillis() - ts) / 1000) > MAX_COOKIE_TIMEOUT_SECS) {
-      throw new OAuthTokenException("Session token " + sessionToken
-          + " has expired");
-    }
-  }
-}