You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
139 lines
4.7 KiB
139 lines
4.7 KiB
package org.ros.chatto.security;
|
|
|
|
import java.io.IOException;
|
|
import java.time.Duration;
|
|
import java.time.Instant;
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
|
|
import javax.servlet.FilterChain;
|
|
import javax.servlet.ServletException;
|
|
import javax.servlet.http.HttpServletRequest;
|
|
import javax.servlet.http.HttpServletResponse;
|
|
|
|
import org.ros.chatto.logged.TokenCacheUtil;
|
|
import org.ros.chatto.model.UserToken;
|
|
import org.ros.chatto.service.UserTokenService;
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.beans.factory.annotation.Value;
|
|
import org.springframework.http.HttpHeaders;
|
|
import org.springframework.http.MediaType;
|
|
import org.springframework.security.authentication.BadCredentialsException;
|
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
|
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
|
import org.springframework.security.core.context.SecurityContextHolder;
|
|
import org.springframework.security.core.token.Token;
|
|
import org.springframework.security.core.token.TokenService;
|
|
import org.springframework.stereotype.Component;
|
|
import org.springframework.web.filter.OncePerRequestFilter;
|
|
|
|
@Component
|
|
public class TokenAuthenticationFilter extends OncePerRequestFilter {
|
|
|
|
@Autowired
|
|
private final UserTokenService userTokenService;
|
|
|
|
@Autowired
|
|
private final TokenService tokenService;
|
|
|
|
private final Logger logger = LoggerFactory
|
|
.getLogger(TokenAuthenticationFilter.class);
|
|
|
|
private final int tokenTimeoutDuration;
|
|
|
|
public TokenAuthenticationFilter(UserTokenService userTokenService,
|
|
TokenService tokenService,
|
|
@Value("${chatto.token.timeout-duration}") String tokenTimeoutDuration) {
|
|
this.tokenTimeoutDuration = Integer.parseInt(tokenTimeoutDuration);
|
|
this.userTokenService = userTokenService;
|
|
this.tokenService = tokenService;
|
|
}
|
|
|
|
private boolean isTokenExpired(UserToken userToken) {
|
|
Duration duration = Duration.between(userToken.getCreationTime(),
|
|
Instant.now());
|
|
long minutes = Math.abs(duration.toMinutes());
|
|
if (minutes > tokenTimeoutDuration) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
protected void doFilterInternal(HttpServletRequest request,
|
|
HttpServletResponse response, FilterChain filterChain)
|
|
throws ServletException, IOException {
|
|
|
|
try {
|
|
final String accessToken = request.getHeader("X-AUTH-TOKEN");
|
|
if (null != accessToken) {
|
|
// get and check whether token is valid ( from DB or file
|
|
// wherever you are
|
|
// storing the token)
|
|
Token token = tokenService.verifyToken(accessToken);
|
|
|
|
if (token == null) {
|
|
throw new BadCredentialsException("Token not issued by us");
|
|
}
|
|
UserToken userToken = userTokenService
|
|
.getTokenByTokenString(accessToken);
|
|
|
|
if (userToken == null) {
|
|
throw new BadCredentialsException("Token not found");
|
|
}
|
|
|
|
String userName = userToken.getUserName();
|
|
if (userName == null) {
|
|
throw new BadCredentialsException("User not found");
|
|
}
|
|
|
|
boolean isTokenExpired = isTokenExpired(userToken);
|
|
logger.trace(String.format("Token for %s is expired? %s",
|
|
userName, isTokenExpired));
|
|
|
|
if (!isTokenExpired) {
|
|
userToken.setCreationTime(Instant.now());
|
|
userTokenService.saveToken(userToken);
|
|
SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority(
|
|
userToken.getRole());
|
|
var updatedAuthorities = new ArrayList<SimpleGrantedAuthority>();
|
|
updatedAuthorities.add(simpleGrantedAuthority);
|
|
final UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
|
|
userName, token.getKey(), updatedAuthorities);
|
|
SecurityContextHolder.getContext()
|
|
.setAuthentication(authentication);
|
|
} else {
|
|
userTokenService.deleteToken(userToken);
|
|
TokenCacheUtil
|
|
.evictSingleTokenValue(userToken.getTokenContent());
|
|
// response.setHeader(HttpHeaders.CONTENT_TYPE,
|
|
// MediaType.TEXT_PLAIN_VALUE);
|
|
// response.setStatus(440);
|
|
// // response.sendError(440, "Token authentication error:
|
|
// Token has expired");
|
|
// response.getWriter().write("Token authentication error:
|
|
// Token has expired");
|
|
// logger.warn("Token authentication error: Token has
|
|
// expired");
|
|
// return;
|
|
}
|
|
|
|
}
|
|
|
|
filterChain.doFilter(request, response);
|
|
}
|
|
|
|
catch (BadCredentialsException e) {
|
|
response.setHeader(HttpHeaders.CONTENT_TYPE,
|
|
MediaType.TEXT_PLAIN_VALUE);
|
|
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
|
|
// response.sendError(HttpServletResponse.SC_BAD_REQUEST,
|
|
// e.getMessage());
|
|
response.getWriter().write("Token authentication error");
|
|
logger.warn("Token authentication error: " + e.getMessage());
|
|
}
|
|
}
|
|
|
|
}
|