Cache for OAuth access tokens

OAuth access tokens retrieved during login in the web UI are stored
privately in OAuthSession. There is no possibility for a user to
obtain that token, e.g. to authenticate with a native Git client.

This patch adds a persistent cache for OAuth tokens and modifies
OAuthSession to store tokens received during the login handshake
with the OAuth provider in this cache.

Since access tokens must be kept secret, the cache defines a new
extension point OAuthTokenEncrypter. If an encrypter is provided,
access tokens are encrypted before storing them in the cache, and
decrypted when reading from the cache. By default, no encryption
is applied.

In subsequent patches a REST API for retrieving OAuth tokens will
be added as well as a corresponding settings page.

Change-Id: I751dd5f70dd30823bd2f531e1ac1da0759f98976
Signed-off-by: Michael Ochmann <michael.ochmann@sap.com>
This commit is contained in:
Michael Ochmann
2015-12-15 15:40:12 +01:00
parent 1703aff9f0
commit 524faceb97
5 changed files with 183 additions and 8 deletions

View File

@@ -31,6 +31,7 @@ import com.google.gerrit.server.account.AccountException;
import com.google.gerrit.server.account.AccountManager;
import com.google.gerrit.server.account.AuthRequest;
import com.google.gerrit.server.account.AuthResult;
import com.google.gerrit.server.auth.oauth.OAuthTokenCache;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
@@ -58,8 +59,8 @@ class OAuthSession {
private final Provider<IdentifiedUser> identifiedUser;
private final AccountManager accountManager;
private final CanonicalWebUrl urlProvider;
private final OAuthTokenCache tokenCache;
private OAuthServiceProvider serviceProvider;
private OAuthToken token;
private OAuthUserInfo user;
private String redirectToken;
private boolean linkMode;
@@ -68,16 +69,18 @@ class OAuthSession {
OAuthSession(DynamicItem<WebSession> webSession,
Provider<IdentifiedUser> identifiedUser,
AccountManager accountManager,
CanonicalWebUrl urlProvider) {
CanonicalWebUrl urlProvider,
OAuthTokenCache tokenCache) {
this.state = generateRandomState();
this.identifiedUser = identifiedUser;
this.webSession = webSession;
this.accountManager = accountManager;
this.urlProvider = urlProvider;
this.tokenCache = tokenCache;
}
boolean isLoggedIn() {
return token != null && user != null;
return tokenCache.has(user);
}
boolean isOAuthFinal(HttpServletRequest request) {
@@ -95,9 +98,12 @@ class OAuthSession {
}
log.debug("Login-Retrieve-User " + this);
token = oauth.getAccessToken(new OAuthVerifier(request.getParameter("code")));
OAuthToken token = oauth.getAccessToken(
new OAuthVerifier(request.getParameter("code")));
user = oauth.getUserInfo(token);
if (user != null && token != null) {
tokenCache.put(user, token);
}
if (isLoggedIn()) {
log.debug("Login-SUCCESS " + this);
@@ -211,7 +217,7 @@ class OAuthSession {
}
void logout() {
token = null;
tokenCache.remove(user);
user = null;
redirectToken = null;
serviceProvider = null;
@@ -243,7 +249,8 @@ class OAuthSession {
@Override
public String toString() {
return "OAuthSession [token=" + token + ", user=" + user + "]";
return "OAuthSession [token=" + tokenCache.get(user) + ", user=" + user
+ "]";
}
public void setServiceProvider(OAuthServiceProvider provider) {