Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save fedotxxl/7b7b74cb345536f02a6dea1e468c455f to your computer and use it in GitHub Desktop.

Select an option

Save fedotxxl/7b7b74cb345536f02a6dea1e468c455f to your computer and use it in GitHub Desktop.

Revisions

  1. fedotxxl created this gist Feb 10, 2023.
    108 changes: 108 additions & 0 deletions CustomPersistentTokenBasedRememberMeServices.java
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,108 @@
    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
    );
    }


    }