LoginTokenCache.java
/*
* Copyright (c) 2007-2017 MetaSolutions AB
*
* 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 org.entrystore.rest.auth;
import org.entrystore.config.Config;
import org.entrystore.rest.util.HttpUtil;
import org.restlet.Request;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collectors;
import static com.google.common.base.Preconditions.checkArgument;
import static org.entrystore.repository.config.Settings.*;
/**
* @author Hannes Ebner
*/
public class LoginTokenCache extends TokenCache<String, UserInfo> {
private static final Logger log = LoggerFactory.getLogger(LoginTokenCache.class);
private static final int DEFAULT_MAX_AGE_IN_SECONDS = (int) Duration.ofDays(1).toSeconds();
private final boolean configTokenUpdateExpiry;
public final int MAX_AGE_IN_SECONDS;
public LoginTokenCache(Config config) {
this.configTokenUpdateExpiry = config.getBoolean(AUTH_COOKIE_REFRESH_EXPIRATION_ON_ACCESS, true);
this.MAX_AGE_IN_SECONDS = config.getInt(AUTH_TOKEN_MAX_AGE, config.getInt(AUTH_COOKIE_MAX_AGE, DEFAULT_MAX_AGE_IN_SECONDS));
}
public boolean isTokenUpdateExpiry() {
return configTokenUpdateExpiry;
}
public int getMaxAgeInSeconds() {
return MAX_AGE_IN_SECONDS;
}
public void cleanup() {
synchronized (tokenCache) {
tokenCache.entrySet().removeIf(userInfo -> userInfo.getValue().getLoginExpiration().isBefore(LocalDateTime.now()));
}
}
public void removeTokens(String userName) {
checkArgument(userName != null, "userName must not be null");
synchronized (tokenCache) {
tokenCache.entrySet().removeIf(userInfo -> userName.equals(userInfo.getValue().getUserName()));
}
}
public void removeToken(String token) {
checkArgument(token != null, "token must not be null");
synchronized (tokenCache) {
if (tokenCache.containsKey(token)) {
tokenCache.remove(token);
} else {
log.warn("Token not found in cache");
}
}
}
public void removeTokensButOne(String token) {
if (token == null) {
log.warn("Token is null, authenticated via HTTP Basic?");
return;
}
synchronized (tokenCache) {
if (tokenCache.containsKey(token)) {
String userName = tokenCache.get(token).getUserName();
tokenCache.entrySet().removeIf(userInfo ->
(userName.equals(userInfo.getValue().getUserName()) && !token.equals(userInfo.getKey()))
);
} else {
log.warn("Token not found in cache");
}
}
}
public void renameUser(String oldUserName, String newUserName) {
if (oldUserName == null || newUserName == null) {
throw new IllegalArgumentException("Username must not be null");
}
synchronized (tokenCache) {
for (Entry<String, UserInfo> e : tokenCache.entrySet()) {
UserInfo oldUi = e.getValue();
if (oldUserName.equals(oldUi.userName)) {
UserInfo newUi = new UserInfo(newUserName, oldUi.getLoginTime(), oldUi.getLoginTokenMaxAge());
newUi.setLoginExpiration(oldUi.getLoginExpiration());
newUi.setLastAccessTime(oldUi.getLastAccessTime());
newUi.setLastUsedIpAddress(oldUi.getLastUsedIpAddress());
newUi.setLastUsedUserAgent(oldUi.getLastUsedUserAgent());
tokenCache.put(e.getKey(), newUi);
}
}
}
}
public Map<String, UserInfo> getTokens(String userName) {
checkArgument(userName != null, "Username must not be null");
synchronized (tokenCache) {
return tokenCache.entrySet().stream()
.filter(entry -> userName.equals(entry.getValue().getUserName()))
.collect(Collectors.toMap(Entry::getKey, Entry::getValue));
}
}
public UserInfo registerUserInteraction(String token, Request request) {
checkArgument(token != null, "Token must not be null");
UserInfo userInfo = getTokenValue(token);
if (userInfo == null) {
log.debug("Call to registerUserInteraction with non-existent token [{}]", token);
return null;
}
userInfo.setLastUsedUserAgent(request.getClientInfo().getAgent());
userInfo.setLastAccessTime(LocalDateTime.now());
userInfo.setLastUsedIpAddress(HttpUtil.getClientIpAddress(request));
if (configTokenUpdateExpiry) {
userInfo.setLoginExpiration(userInfo.getLastAccessTime().plusSeconds(userInfo.getLoginTokenMaxAge()));
}
return userInfo;
}
}