Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save fedotxxl/7b7b74cb345536f02a6dea1e468c455f to your computer and use it in GitHub Desktop.
Save fedotxxl/7b7b74cb345536f02a6dea1e468c455f to your computer and use it in GitHub Desktop.
package ru.gramant.adplanner.auth;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.rememberme.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
public class CustomPersistentTokenBasedRememberMeServices extends PersistentTokenBasedRememberMeServices {
private CustomPersistentTokenRepository tokenRepository;
private int maxDurationInMs;
public CustomPersistentTokenBasedRememberMeServices(
String key,
UserDetailsService userDetailsService,
CustomPersistentTokenRepository tokenRepository,
int maxDurationInMs
) {
super(key, userDetailsService, tokenRepository);
this.tokenRepository = tokenRepository;
this.maxDurationInMs = maxDurationInMs;
}
protected UserDetails processAutoLoginCookie(String[] cookieTokens,
HttpServletRequest request, HttpServletResponse response) {
if (cookieTokens.length != 2) {
throw new InvalidCookieException("Cookie token did not contain " + 2
+ " tokens, but contained '" + Arrays.asList(cookieTokens) + "'");
}
final String presentedSeries = cookieTokens[0];
final String presentedToken = cookieTokens[1];
List<PersistentRememberMeToken> tokens = tokenRepository.findAllBySeries(presentedSeries);
if (tokens.isEmpty()) {
// No series match, so we can't authenticate using this cookie
throw new RememberMeAuthenticationException("No persistent token found for series id: " + presentedSeries);
}
PersistentRememberMeToken tokenLast = tokens.get(0);
PersistentRememberMeToken tokenCurrent = tokens.stream().filter(t -> presentedToken.equals(t.getTokenValue())).findFirst().orElse(null);
// We have a match for this user/series combination
if (tokenCurrent == null || ((tokenLast.getDate().getTime() - tokenCurrent.getDate().getTime()) > maxDurationInMs)) {
// Token doesn't match series value. Delete all logins for this user and throw
// an exception to warn them.
tokenRepository.removeUserTokens(tokenLast.getUsername());
throw new CookieTheftException(
messages.getMessage(
"PersistentTokenBasedRememberMeServices.cookieStolen",
"Invalid remember-me token (Series/token) mismatch. Implies previous cookie theft attack."
)
);
}
if (tokenLast.getDate().getTime() + getTokenValiditySeconds() * 1000L < System.currentTimeMillis()) {
throw new RememberMeAuthenticationException("Remember-me login has expired");
}
// Token also matches, so login is valid. Update the token value, keeping the
// *same* series number.
if (logger.isDebugEnabled()) {
logger.debug("Refreshing persistent login token for user '" + tokenLast.getUsername() + "', series '" + tokenLast.getSeries() + "'");
}
PersistentRememberMeToken newToken = new PersistentRememberMeToken(
tokenLast.getUsername(),
tokenLast.getSeries(),
generateTokenData(),
new Date()
);
try {
tokenRepository.createNewToken(newToken);
addCookie(newToken, request, response);
} catch (Exception e) {
logger.error("Failed to update token: ", e);
throw new RememberMeAuthenticationException(
"Autologin failed due to data access problem");
}
return getUserDetailsService().loadUserByUsername(tokenLast.getUsername());
}
private void addCookie(
PersistentRememberMeToken token,
HttpServletRequest request,
HttpServletResponse response
) {
setCookie(
new String[]{token.getSeries(), token.getTokenValue()},
getTokenValiditySeconds(),
request,
response
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment