package io.github.jokoframework.security.springex;

import java.io.IOException;
import java.util.Collection;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.web.filter.GenericFilterBean;

import io.github.jokoframework.common.JokoUtils;
import io.github.jokoframework.security.JokoJWTClaims;
import io.github.jokoframework.security.JokoJWTExtension;
import io.github.jokoframework.security.api.JokoAuthorizationManager;
import io.github.jokoframework.security.controller.SecurityConstants;
import io.github.jokoframework.security.services.ITokenService;
import io.jsonwebtoken.JwtException;

/**
 * Comprueba los requests hechos en busca del token de autenticación. El token
 * de autenticación se encuentra siempre en
 * {@value SecurityConstants#AUTH_HEADER_NAME}.
 * 
 * Si se encuentra un token se llamara al autoriza
 * 
 * @author danicricco
 *
 */
public class JokoSecurityFilter extends GenericFilterBean {

    private static final Logger LOGGER = LoggerFactory.getLogger(JokoSecurityFilter.class);
    private ITokenService tokenService;

    private JokoAuthorizationManager jokoAuthorizationManager;

    public JokoSecurityFilter(ITokenService tokenService, JokoAuthorizationManager jokoAuthorizationManager) {
        this.tokenService = tokenService;
        this.jokoAuthorizationManager = jokoAuthorizationManager;
    }

    public static String getTokenFromHeader(HttpServletRequest pRequest) {
        String token = pRequest.getHeader(SecurityConstants.AUTH_HEADER_NAME);
        return token;
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
            throws IOException, ServletException {
        JokoJWTClaims claims = validateToken(request);
        if (claims != null) {

            Collection<? extends GrantedAuthority> baseAuthorizations = JokoSecurityContext
                    .determineAuthorizations(claims);
            Collection<? extends GrantedAuthority> authorities = jokoAuthorizationManager.authorize(claims,
                    baseAuthorizations);

            JokoAuthenticated authentication = new JokoAuthenticated(claims, authorities);
            JokoSecurityContext.setAuthentication(authentication);

            if (LOGGER.isTraceEnabled()) {

                HttpServletRequest httpRequest = (HttpServletRequest) request;
                String uri = httpRequest.getRequestURI();
                LOGGER.trace("Authorized user " + JokoUtils.formatLogString(claims.getSubject()) + " to: "
                        + JokoUtils.join(authorities, ",") + " Request-URI " + uri);
            }

        } else {
            JokoSecurityContext.clearContext();
        }
        filterChain.doFilter(request, response);
        JokoSecurityContext.clearContext();

    }

    /**
     * Si el token es valido retorna un {@link JokoJWTClaims}. Si el token NO es
     * valido retorna null
     * 
     * @param request
     * @return
     */
    private JokoJWTClaims validateToken(ServletRequest request) {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        String token = getTokenFromHeader(httpRequest);
        if (token == null) {
            return null;
        }

        try {
            JokoJWTClaims claims = tokenService.parse(token);
            // En este punto el token ya es valido sino habria tirado una
            // excepcion JwtException
            JokoJWTExtension jokoClaims = claims.getJoko();
            if (jokoClaims.getType().equals(JokoJWTExtension.TOKEN_TYPE.REFRESH)) {
                // Solamente los tokens de refresh se pueden revocar
                if (tokenService.hasBeenRevoked(claims.getId())) {
                    return null;
                }
            }

            return claims;
        } catch (JwtException | IllegalArgumentException e) {

            String uri = httpRequest.getRequestURI();
            String userAgent = httpRequest.getHeader("User-Agent");
            LOGGER.debug(uri + " from User-Agent: " + userAgent + " Unable to authenticate " + e.getClass() + ": "
                    + e.getMessage());
            LOGGER.debug("Token received: " + token);
            LOGGER.trace("Error validando el token.", e);
            return null;
        }
    }

}

@@ -1053,17 +1053,16 @@
 AME%7D.%0A *
- 
 %0A * Si s
@@ -1107,17 +1107,16 @@
 oriza%0A *
- 
 %0A * @aut
@@ -2539,13 +2539,13 @@
 R.is
-Trace
+Debug
 Enab
@@ -2714,21 +2714,21 @@
  LOGGER.
-trace
+debug
 (%22Author
@@ -2880,16 +2880,43 @@
  %22 + uri
+ + %22 jti %22 + claims.getId()
 );%0A     
@@ -3217,23 +3217,22 @@
 na null%0A
+
      *
- 
 %0A     * 

Imprime el 'jti' en método 'doFilter'