My fork of airsonic with experimental fixes and improvements. See branch "custom"
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.
 
 
 
airsonic-custom/airsonic-main/src/main/java/org/airsonic/player/security/JWTRequestParameterProcessi...

120 lines
4.7 KiB

package org.airsonic.player.security;
import org.airsonic.player.service.JWTSecurityService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
import org.springframework.util.StringUtils;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Optional;
public class JWTRequestParameterProcessingFilter implements Filter {
private static final Logger LOG = LoggerFactory.getLogger(JWTRequestParameterProcessingFilter.class);
private final AuthenticationManager authenticationManager;
private final AuthenticationFailureHandler failureHandler;
protected JWTRequestParameterProcessingFilter(AuthenticationManager authenticationManager, String failureUrl) {
this.authenticationManager = authenticationManager;
failureHandler = new SimpleUrlAuthenticationFailureHandler(failureUrl);
}
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
Optional<JWTAuthenticationToken> token = findToken(request);
if (token.isPresent()) {
return authenticationManager.authenticate(token.get());
}
throw new AuthenticationServiceException("Invalid auth method");
}
private static Optional<JWTAuthenticationToken> findToken(HttpServletRequest request) {
String token = request.getParameter(JWTSecurityService.JWT_PARAM_NAME);
if (!StringUtils.isEmpty(token)) {
return Optional.of(new JWTAuthenticationToken(AuthorityUtils.NO_AUTHORITIES, token, request.getRequestURI() + "?" + request.getQueryString()));
}
return Optional.empty();
}
@Override
public void init(FilterConfig filterConfig) {
}
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException,
ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
if (!findToken(request).isPresent()) {
chain.doFilter(req, resp);
return;
}
if (LOG.isDebugEnabled()) {
LOG.debug("Request is to process authentication");
}
Authentication authResult;
try {
authResult = attemptAuthentication(request, response);
if (authResult == null) {
// return immediately as subclass has indicated that it hasn't completed
// authentication
return;
}
} catch (InternalAuthenticationServiceException failed) {
LOG.error(
"An internal error occurred while trying to authenticate the user.",
failed);
unsuccessfulAuthentication(request, response, failed);
return;
} catch (AuthenticationException e) {
unsuccessfulAuthentication(request, response, e);
return;
}
if (LOG.isDebugEnabled()) {
LOG.debug("Authentication success. Updating SecurityContextHolder to contain: "
+ authResult);
}
SecurityContextHolder.getContext().setAuthentication(authResult);
chain.doFilter(request, response);
}
protected void unsuccessfulAuthentication(HttpServletRequest request,
HttpServletResponse response, AuthenticationException failed)
throws IOException, ServletException {
SecurityContextHolder.clearContext();
if (LOG.isDebugEnabled()) {
LOG.debug("Authentication request failed: " + failed.toString(), failed);
LOG.debug("Updated SecurityContextHolder to contain null Authentication");
LOG.debug("Delegating to authentication failure handler " + failureHandler);
}
failureHandler.onAuthenticationFailure(request, response, failed);
}
@Override
public void destroy() {
}
}