0

In the method in my resource class, I am accepting a request header value

@GET
@Path(value = "/identifiers")
@Produces(MediaType.APPLICATION_JSON)
public Response getXXX (@HeaderParam("Authorization") String authHeader){...}

I also have a servlet filter defined in web.xml for all incoming requests. The way my application flow works is - User requests my rest API and sends an Authorization header in request. My servlet filter will intercept the request and validate the Authorization header and for some users, it replaces this Authorization header with a new value. The request then goes to the resource class and it uses this authorization header and does some action.

For the users whose Authorization header is changed by the filter, I noticed that the authHeader variable still has the original value. E.g. - User makes a request containing Authorization header with a value "QwErTyUiOp". The servlet filter injects a new Authorization header in the request with a value "aSdFgHjKl". However, authHeader parameter still has "QwErTyUiOp".

When I iterated through the request object in my method, I could see that the request has the new Authorization header values ("aSdFgHjKl") so the filter is doing its job.

Can someone help me understand why is @HeaderParam capturing the header value before servlet filter has processed the request and if there is any way to alter this behavior?

Here is the web.xml from my application -

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" 
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>library-api</display-name>
<filter>
    <filter-name>libUserFilter</filter-name>
    <filter-class>org.rajiv.library.logic.filter.LibraryUserAuthFilter</filter-class>       
</filter>
<filter-mapping>
    <filter-name>libUserFilter</filter-name>
    <url-pattern>/v1/*</url-pattern>
</filter-mapping>
<servlet>
    <servlet-name>Library API App</servlet-name>
    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
    <init-param>
        <param-name>jersey.config.server.provider.packages</param-name>
        <param-value>org.rajiv.library.resources</param-value>
    </init-param> 
    <init-param>
        <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
        <param-value>true</param-value>
    </init-param>       
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet>
    <servlet-name>AdminServlet</servlet-name>
    <servlet-class>org.rajiv.library.admin.AdminServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>Library API App</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>AdminServlet</servlet-name>
    <url-pattern>/restricted/*</url-pattern>
</servlet-mapping>
</web-app>

and the filter class is -

public class LibraryUserAuthFilter implements Filter{

@Override
public void destroy() {
    LOG.info("{} Destroyed", getClass());
}

@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
    HttpServletRequest httpRequest = (HttpServletRequest) servletRequest;
    HttpServletResponse httpResponse = (HttpServletResponse) servletResponse;
    IdsRequest idsRequest = IdsRequest.from(httpRequest);

    try (LoggingContext context = LoggingContext.create()) {
        TokenResolver.INSTANCE
                .extractTokenFromHeaderOrCookie(idsRequest)
                .map(TokenDigester.INSTANCE::computeTokenDigest)
                .ifPresent(digestedToken -> context.put(CustomLoggingContext.SESSION.toString(), digestedToken));

        Optional<HttpServletRequest> modifiedRequest = Optional.empty();
        try (LoggingContext libAuthContext = LoggingContext.create()) {
            libAuthContext.put(CustomLoggingContext.COMPONENT.toString(), SdkComponents.SDK_LIB_AUTH.toString());
            LOG.info("Validation started for request to path:{}", httpRequest.getRequestURI().toString());
            modifiedRequest = Optional.of(validate(idsRequest));

        } catch (IdentityServicesSdkException ex) {
            context.put(CustomLoggingContext.INCIDENT_ID.toString(), ex.getIncidentId());
            ProblemResponseWriter.INSTANCE.writeStatusAndProblem(idsRequest, httpResponse, ex);
            LOG.warn("Validation failed: {}", ex.getErrorCode());
        }

        if(modifiedRequest.isPresent()) {
            chain.doFilter(modifiedRequest.get(), servletResponse);
        }
    }
}

@Override
public void init(FilterConfig filterConfig) throws ServletException {
    initializeScheme(filterConfig);
    initializeHost(filterConfig);
    initializePort(filterConfig);

    String serviceName = filterConfig.getServletContext().getContextPath().replaceAll("/", "").trim();

    if(serviceName.isEmpty()) {
        serviceName = Optional
                .ofNullable(System.getenv("SERVICE_NAME"))
                .orElseGet(() -> "service-name-unavailable");
    }

    LOG.info("{} Initialized", getClass());
}

private void initializeScheme(FilterConfig filterConfig) {
    String initParam = filterConfig.getInitParameter(PROXY_SCHEME_ENVIRONMENT_VARIABLE);
    if(Strings.isNullOrEmpty(initParam)) {
        initParam = loadAuthNSchemeFromEnvVar();
    }
    scheme = initParam;
    LOG.info("HOST_SCHEME: {}", scheme);
}

private void initializeHost(FilterConfig filterConfig) {
    String initParam = filterConfig.getInitParameter(PROXY_HOST_ENVIRONMENT_VARIABLE);
    if(Strings.isNullOrEmpty(initParam)) {
        initParam = loadAuthNHostFromEnvVar();
    }
    host = initParam;
    LOG.info("HOST: {}", host);
}

private void initializePort(FilterConfig filterConfig) {
    String initParam = filterConfig.getInitParameter(PROXY_PORT_ENVIRONMENT_VARIABLE);
    Integer parsedInitParam = null;
    if(!Strings.isNullOrEmpty(initParam)) {
        parsedInitParam = Integer.valueOf(initParam);
    }

    if(parsedInitParam == null) {
        parsedInitParam = loadAuthNPortFromEnvVar();
    }
    port = parsedInitParam;
    LOG.info("HOST_PORT: {}", port);
}

}

user2185805
  • 255
  • 4
  • 17
  • Where are you modifying the header value of your request in that code? – pandaadb Sep 16 '16 at 12:51
  • You are also using a ServletFilter instead of a containerRequestFilter (which is what I used). The containerRequestFilter allows you to directly modify headers, while a normal servletFilter does not allow that, see http://stackoverflow.com/questions/2811769/adding-an-http-header-to-the-request-in-a-servlet-filter – pandaadb Sep 16 '16 at 13:04

0 Answers0