class QueryFilter extends AbstractAuthenticationProcessingFilter {

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) {
        if (!request.getMethod().equals(httpMethod.name())) {
            throw new AuthMethodNotSupportedException(request.getMethod());
        }

        // Must be already authenticated by certificate
        if (protectedByCertificate &&
            (SecurityContextHolder.getContext().getAuthentication() == null ||
                !(SecurityContextHolder.getContext().getAuthentication().getCredentials() instanceof X509Certificate) ||
                !SecurityContextHolder.getContext().getAuthentication().isAuthenticated())) {
            throw new InvalidCertificateException("Invalid certificate.");
        }

        String token = authenticationService.getJwtTokenFromRequest(request)
            .orElseThrow(() -> new TokenNotProvidedException("Authorization token not provided."));

        Authentication result = this.getAuthenticationManager().authenticate(new TokenAuthentication(token));
        if (result.isAuthenticated()) {
            return result;
        } else {
            throw new TokenNotValidException("JWT Token is not authenticated");
        }
    }

    public  QueryFilter(
        String authEndpoint,
        AuthenticationSuccessHandler successHandler,
        AuthenticationFailureHandler failureHandler,
        AuthenticationService authenticationService,
        HttpMethod httpMethod,
        boolean protectedByCertificate,
        AuthenticationManager authenticationManager);

}