private void filter(final HttpServletRequest request,
                        final HttpServletResponse response,
                        final FilterChain chain)

            throws IOException, ServletException {

        final String servletPath = request.getServletPath();
        final String fullPath = request.getRequestURI();
        final String servletName = NullSafe.get(request.getHttpServletMapping(), HttpServletMapping::getServletName);

        LOGGER.debug(() ->
                LogUtil.message("Filtering request uri: {}, servletPath: {}, servletName: {}",
                        request.getRequestURI(),
                        request.getServletPath(),
                        NullSafe.get(request.getHttpServletMapping(), HttpServletMapping::getServletName)));

        // TODO: 05/12/2022 Need to figure out how we deal with chained proxies where the distant
        //  proxies can only see the downstream and not the IDP.

        if (request.getMethod().equalsIgnoreCase(HttpMethod.OPTIONS)) {
            // We need to allow CORS preflight requests
            LOGGER.debug("Passing on OPTIONS request to next filter, servletName: {}, fullPath: {}, servletPath: {}",
                    servletName, fullPath, servletPath);
            chain.doFilter(request, response);

        } else if (ignoreUri(request.getRequestURI())) {
            // Allow some URIs to bypass authentication checks
            LOGGER.debug("Ignored URI, servletName: {}, fullPath: {}, servletPath: {}",
                    servletName, fullPath, servletPath);
            chain.doFilter(request, response);

        } else if (shouldBypassAuthentication(request, fullPath, servletPath, servletName)) {
            // Unauthenticated paths skip auth here but may handle it themselves
            LOGGER.debug("Bypassed URI, servletName: {}, fullPath: {}, servletPath: {}",
                    servletName, fullPath, servletPath);
            chain.doFilter(request, response);
        } else {
            final boolean isApiRequest = fullPath.contains(ResourcePaths.API_ROOT_PATH);

            if (isApiRequest) {
                if (fullPath.contains(EventResource.BASE_RESOURCE_PATH)) {
                    // Allow all event requests through as security is applied elsewhere.
                    chain.doFilter(request, response);
                } else {
                    // All other rest API resources so authenticate them
                    final Optional<UserIdentity> optUserIdentity = userIdentityFactory.getApiUserIdentity(request);

                    if (optUserIdentity.isPresent()) {
                        LOGGER.debug("Authenticated request to fullPath: {}, servletPath: {}, userIdentity: {}",
                                fullPath, servletPath, optUserIdentity.get());
                        chain.doFilter(request, response);

                    } else {
                        LOGGER.debug("Unauthorised request to fullPath: {}, servletPath: {}", fullPath, servletPath);
                        response.setStatus(Response.Status.UNAUTHORIZED.getStatusCode());
                    }
                }
            } else {
                chain.doFilter(request, response);
            }
        }
    }
<p>
Filter to avoid posts to the wrong place (e.g. the root of the app)
</p>
stroom-proxy/stroom-proxy-app/src/main/java/stroom/proxy/app/servlet/ProxySecurityFilter.java