/** * When logout occurs, only invalidate the current token, and not all user sessions. * <p/> * The standard Spring Security implementations are too basic: they invalidate all tokens for the * current user, so when he logs out from one browser, all his other sessions are destroyed. */ @Override @Transactional public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) { String rememberMeCookie = extractRememberMeCookie(request); if (rememberMeCookie != null && rememberMeCookie.length() != 0) { try { String[] cookieTokens = decodeCookie(rememberMeCookie); Token token = getPersistentToken(cookieTokens); tokenRepo.delete(token.getSeries()); } catch (InvalidCookieException ice) { log.info("Invalid cookie, no persistent token could be deleted"); } catch (RememberMeAuthenticationException rmae) { log.debug("No persistent token found, so no token could be deleted"); } } super.logout(request, response, authentication); }
/** * When logout occurs, only invalidate the current token, and not all user sessions. * <p/> * The standard Spring Security implementations are too basic: they invalidate all tokens for the * current user, so when he logs out from one browser, all his other sessions are destroyed. */ @Override @Transactional public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) { String rememberMeCookie = extractRememberMeCookie(request); if (rememberMeCookie != null && rememberMeCookie.length() != 0) { try { String[] cookieTokens = decodeCookie(rememberMeCookie); PersistentToken token = getPersistentToken(cookieTokens); persistentTokenRepository.delete(token); } catch (InvalidCookieException ice) { log.info("Invalid cookie, no persistent token could be deleted"); } catch (RememberMeAuthenticationException rmae) { log.debug("No persistent token found, so no token could be deleted"); } } super.logout(request, response, authentication); }
/** * When logout occurs, only invalidate the current token, and not all user sessions. * <p/> * The standard Spring Security implementations are too basic: they invalidate all tokens for the current user, so when he logs out from one browser, all his other sessions are destroyed. */ @Override @Transactional public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) { String rememberMeCookie = extractRememberMeCookie(request); if (rememberMeCookie != null && rememberMeCookie.length() != 0) { try { String[] cookieTokens = decodeCookie(rememberMeCookie); Token token = getPersistentToken(cookieTokens); persistentTokenService.delete(token); } catch (InvalidCookieException ice) { LOGGER.info("Invalid cookie, no persistent token could be deleted"); } catch (RememberMeAuthenticationException rmae) { LOGGER.debug("No persistent token found, so no token could be deleted"); } } super.logout(request, response, authentication); }
protected String[] decodeCookie(String cookieValue) throws InvalidCookieException { for (int j = 0; j < cookieValue.length() % 4; j++) { cookieValue = cookieValue + "="; } if (!Base64.isBase64(cookieValue.getBytes())) { throw new InvalidCookieException("Cookie token was not Base64 encoded; value was '" + cookieValue + "'"); } String cookieAsPlainText = new String(Base64.decodeBase64(cookieValue.getBytes())); String[] tokens = StringUtils.delimitedListToStringArray(cookieAsPlainText, DELIMITER); if ((tokens[0].equalsIgnoreCase("http") || tokens[0].equalsIgnoreCase("https")) && tokens[1].startsWith("//")) { // Assume we've accidentally split a URL (OpenID identifier) String[] newTokens = new String[tokens.length - 1]; newTokens[0] = tokens[0] + ":" + tokens[1]; System.arraycopy(tokens, 2, newTokens, 1, newTokens.length - 1); tokens = newTokens; } return tokens; }
/** * When logout occurs, only invalidate the current token, and not all user * sessions. * <p/> * The standard Spring Security implementations are too basic: they * invalidate all tokens for the current user, so when he logs out from one * browser, all his other sessions are destroyed. */ @Override @Transactional public void logout(final HttpServletRequest request, final HttpServletResponse response, final Authentication authentication) { String rememberMeCookie = extractRememberMeCookie(request); if (rememberMeCookie != null && rememberMeCookie.length() != 0) { try { String[] cookieTokens = decodeCookie(rememberMeCookie); PersistentToken token = getPersistentToken(cookieTokens); persistentTokenRepository.delete(token); } catch (InvalidCookieException ice) { log.info("Invalid cookie, no persistent token could be deleted"); } catch (RememberMeAuthenticationException rmae) { log.debug("No persistent token found, so no token could be deleted"); } } super.logout(request, response, authentication); }
/** * When logout occurs, only invalidate the current token, and not all user sessions. * <p/> * The standard Spring Security implementations are too basic: they invalidate all * tokens for the current user, so when he logs out from one browser, all his other * sessions are destroyed. */ @Override public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) { String rememberMeCookie = extractRememberMeCookie(request); if (rememberMeCookie != null && rememberMeCookie.length() != 0) { try { String[] cookieTokens = decodeCookie(rememberMeCookie); removePersistentLogin(getPersistentToken(cookieTokens)); } catch (InvalidCookieException ice) { Application.logger .info("Invalid cookie, no persistent token could be deleted"); } catch (RememberMeAuthenticationException rmae) { Application.logger .debug("No persistent token found, so no token could be deleted"); } } super.logout(request, response, authentication); }
/** * When logout occurs, only invalidate the current token, and not all user sessions. <p/> The standard Spring Security * implementations are too basic: they invalidate all tokens for the current user, so when he logs out from one browser, * all his other sessions are destroyed. */ @Override @Transactional public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) { String rememberMeCookie = extractRememberMeCookie(request); if (rememberMeCookie != null && rememberMeCookie.length() != 0) { try { String[] cookieTokens = decodeCookie(rememberMeCookie); PersistentToken token = getPersistentToken(cookieTokens); persistentTokenRepository.delete(token); } catch (InvalidCookieException ice) { log.info("Invalid cookie, no persistent token could be deleted"); } catch (RememberMeAuthenticationException rmae) { log.debug("No persistent token found, so no token could be deleted"); } } super.logout(request, response, authentication); }
/** * <p> * When logout occurs, only invalidate the current token, and not all user sessions. * </p> * The standard Spring Security implementations are too basic: they invalidate all tokens for the current user, so when he logs out from one browser, all * his other sessions are destroyed. * * @param request * the http request * @param response * the http response * @param authentication * the authentication */ @Override @Transactional public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) { final String rememberMeCookie = extractRememberMeCookie(request); if (rememberMeCookie != null && rememberMeCookie.length() != 0) { try { final String[] cookieTokens = decodeCookie(rememberMeCookie); final PersistentToken token = getPersistentToken(cookieTokens); persistentTokenRepository.delete(token); } catch (final InvalidCookieException ice) { log.info("Invalid cookie, no persistent token could be deleted"); } catch (final RememberMeAuthenticationException rmae) { log.debug("No persistent token found, so no token could be deleted"); } } super.logout(request, response, authentication); }
@Override protected UserDetails processAutoLoginCookie(String[] cookieTokens, HttpServletRequest request, HttpServletResponse response) { try { setContext(request); // take off the last token String ipAddressToken = cookieTokens[cookieTokens.length - 1]; if (!getUserIPAddress(request).equals(ipAddressToken)) { throw new InvalidCookieException("Cookie IP Address did not contain a matching IP (contained '" + ipAddressToken + "')"); } return super.processAutoLoginCookie(Arrays.copyOf(cookieTokens, cookieTokens.length - 1), request, response); } finally { setContext(null); } }
@Override protected String[] decodeCookie(String cookieValue) throws InvalidCookieException { try { Claims claims = Jwts.parser() .setSigningKey(getKey()) .parseClaimsJws(cookieValue) .getBody(); return new String[] { claims.getId(), claims.getSubject() }; } catch (JwtException e) { LOGGER.warn(e.getMessage()); throw new InvalidCookieException(e.getMessage()); } }
/** * Validate the token and return it. */ private Token getPersistentToken(String[] cookieTokens) { 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]; Token token = null; try { token = tokenRepo.findOne(presentedSeries); } catch (DataAccessException e) { log.error("Error to access database", e ); } if (token == null) { // No series match, so we can't authenticate using this cookie throw new RememberMeAuthenticationException("No persistent token found for series id: " + presentedSeries); } // We have a match for this user/series combination log.info("presentedToken={} / tokenValue={}", presentedToken, token.getValue()); if (!presentedToken.equals(token.getValue())) { // Token doesn't match series value. Delete this session and throw an exception. tokenRepo.delete(token.getSeries()); throw new CookieTheftException("Invalid remember-me token (Series/token) mismatch. Implies previous cookie theft attack."); } if (DateUtils.addDays(token.getDate(), TOKEN_VALIDITY_DAYS).before(new Date())) { tokenRepo.delete(token.getSeries()); throw new RememberMeAuthenticationException("Remember-me login has expired"); } return token; }
/** * Validate the token and return it. */ private PersistentToken getPersistentToken(String[] cookieTokens) { if (cookieTokens.length != 2) { throw new InvalidCookieException("Cookie token did not contain " + 2 + " tokens, but contained '" + Arrays.asList(cookieTokens) + "'"); } String presentedSeries = cookieTokens[0]; String presentedToken = cookieTokens[1]; PersistentToken token = persistentTokenRepository.findOne(presentedSeries); if (token == null) { // No series match, so we can't authenticate using this cookie throw new RememberMeAuthenticationException("No persistent token found for series id: " + presentedSeries); } // We have a match for this user/series combination log.info("presentedToken={} / tokenValue={}", presentedToken, token.getTokenValue()); if (!presentedToken.equals(token.getTokenValue())) { // Token doesn't match series value. Delete this session and throw an exception. persistentTokenRepository.delete(token); throw new CookieTheftException("Invalid remember-me token (Series/token) mismatch. Implies previous cookie theft attack."); } if (token.getTokenDate().plusDays(TOKEN_VALIDITY_DAYS).isBefore(LocalDate.now())) { persistentTokenRepository.delete(token); throw new RememberMeAuthenticationException("Remember-me login has expired"); } return token; }
/** * Validate the token and return it. */ private Token getPersistentToken(String[] cookieTokens) { 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]; Token token = persistentTokenService.getPersistentToken(presentedSeries); if (token == null) { // No series match, so we can't authenticate using this cookie throw new RememberMeAuthenticationException("No persistent token found for series id: " + presentedSeries); } // We have a match for this user/series combination if (!presentedToken.equals(token.getTokenValue())) { // This could be caused by the opportunity window where the token just has been refreshed, but // has not been put into the token cache yet. Invalidate the token and refetch and it the new token value from the db is now returned. token = persistentTokenService.getPersistentToken(presentedSeries, true); // Note the 'true' here, which invalidates the cache before fetching if (!presentedToken.equals(token.getTokenValue())) { // Token doesn't match series value. Delete this session and throw an exception. persistentTokenService.delete(token); throw new CookieTheftException("Invalid remember-me token (Series/token) mismatch. Implies previous cookie theft attack."); } } if (new Date().getTime() - token.getTokenDate().getTime() > tokenMaxAgeInMilliseconds) { throw new RememberMeAuthenticationException("Remember-me login has expired"); } return token; }
/** * Validate the token and return it. */ private PersistentToken getPersistentToken(String[] cookieTokens) { if (cookieTokens.length != 2) { throw new InvalidCookieException("Cookie token did not contain " + 2 + " tokens, but contained '" + Arrays.asList(cookieTokens) + "'"); } String presentedSeries = cookieTokens[0]; String presentedToken = cookieTokens[1]; PersistentToken token = persistentTokenRepository.findOne(presentedSeries); if (token == null) { // No series match, so we can't authenticate using this cookie throw new RememberMeAuthenticationException("No persistent token found for series id: " + presentedSeries); } // We have a match for this user/series combination log.info("presentedToken={} / tokenValue={}", presentedToken, token.getTokenValue()); if (!presentedToken.equals(token.getTokenValue())) { // Token doesn't match series value. Delete this session and throw an exception. persistentTokenRepository.delete(token); throw new CookieTheftException("Invalid remember-me token (Series/token) mismatch. Implies previous " + "cookie theft attack."); } if (token.getTokenDate().plusDays(TOKEN_VALIDITY_DAYS).isBefore(LocalDate.now())) { persistentTokenRepository.delete(token); throw new RememberMeAuthenticationException("Remember-me login has expired"); } return token; }
/** * Validate the token and return it. */ private PersistentToken getPersistentToken(final String[] cookieTokens) { if (cookieTokens.length != 2) { throw new InvalidCookieException("Cookie token did not contain " + 2 + " tokens, but contained '" + Arrays.asList(cookieTokens) + "'"); } String presentedSeries = cookieTokens[0]; String presentedToken = cookieTokens[1]; PersistentToken token = persistentTokenRepository.findOne(presentedSeries); if (token == null) { // No series match, so we can't authenticate using this cookie throw new RememberMeAuthenticationException("No persistent token found for series id: " + presentedSeries); } // We have a match for this user/series combination log.info("presentedToken={} / tokenValue={}", presentedToken, token.getTokenValue()); if (!presentedToken.equals(token.getTokenValue())) { // Token doesn't match series value. Delete this session and throw // an exception. persistentTokenRepository.delete(token); throw new CookieTheftException("Invalid remember-me token (Series/token) mismatch. Implies previous cookie theft attack."); } if (token.getTokenDate().plusDays(TOKEN_VALIDITY_DAYS).isBefore(LocalDate.now())) { persistentTokenRepository.delete(token); throw new RememberMeAuthenticationException("Remember-me login has expired"); } return token; }