0

On my Angular app (Local host app with remote server), I get CORS error only in chrome, in Firefox, it works perfectly. Once it worked on both, but suddenly it stopped working on Chrome, I guess it's related to a kind of update (I guess of chrome?? ) Ofcorse, uploading the app to the production server works on both browsers.

My server-side code is in Java (Servlets) and my CORSFilter looks like this:

public class CORSFilter implements Filter {
 
    /**
     * Default constructor.
     */
    public CORSFilter() {
        
    }
 
    /**
     * @see Filter#destroy()
     */
    public void destroy() {
        
    }
 
    private final List<String> allowedOrigins = Arrays.asList("http://localhost:4200");
    
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        // Lets make sure that we are working with HTTP (that is, against HttpServletRequest and HttpServletResponse objects)
        if (req instanceof HttpServletRequest && res instanceof HttpServletResponse) {
            HttpServletRequest request = (HttpServletRequest) req;
            HttpServletResponse response = (HttpServletResponse) res;

            // Access-Control-Allow-Origin
            String origin = request.getHeader("Origin");
            LoggingService.writeToLog("call from origin: "+origin+", will be accepted? "+(allowedOrigins.contains(origin)||origin!=null), LogModule.WebAPI, LogLevel.Debug);
            
            response.setHeader("Access-Control-Allow-Origin", allowedOrigins.contains(origin) ? origin : "");
            response.setHeader("Vary", "Origin");
            
            
            // Access-Control-Allow-Credentials
            response.setHeader("Access-Control-Allow-Credentials", "true");

            // Access-Control-Allow-Methods
            response.setHeader("Access-Control-Allow-Methods", "POST,HEAD, PUT, GET, OPTIONS, DELETE");
                       
            // Access-Control-Allow-Headers
            response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization, X-CSRF-TOKEN");
            if (request.getMethod().equals("OPTIONS")) {
                response.setStatus(HttpServletResponse.SC_ACCEPTED);
                return;
            }
     
        }

        chain.doFilter(req, res);
        
    }
}
    

Any ideas on how to make it working also in Chrome?

Rami Khawaly
  • 126
  • 3
  • 14
  • What cors error are you getting ?, it can be several and the filter looks fine – Javier Toja Sep 23 '21 at 07:38
  • this set-cookie didn't specify a samesite attribute and was default to samesite=lax and was blocked – Rami Khawaly Sep 23 '21 at 08:05
  • I added it to the server code but didn't help – Rami Khawaly Sep 23 '21 at 08:05
  • Well this has nothing to do with cors rather than with the server cookie configuration, you have to check the actual request chain of your application to setup properly the cookie, also maybe the cookies is not from the backend rather than front the frontend app – Javier Toja Sep 23 '21 at 09:29
  • Well, I agree with you that it's an issue of cookies, yet it's related to CORS policy. I'm attaching the solution that I did – Rami Khawaly Sep 26 '21 at 09:05

2 Answers2

0

The problem is related to the last change of the Chrome browser CORS policy of SameSite cookies. For me, because I want to enable the CORS I had to add the SameSite=None parameters. Here is the updated code. Here is the post that helped me to verify what is needed to be done: Set cookies for cross origin requests

Please note that this code is valuable if you really need to enable the CORS option. This is a big decision.

public class CORSFilter implements Filter {
 

 
    private final List<String> allowedOrigins = Arrays.asList("http://localhost:4200");
    
    private final String SESSION_COOKIE_NAME = "JSESSIONID";
    private final String SESSION_PATH_ATTRIBUTE = ";Path=";
    private final String ROOT_CONTEXT = "/";
    private final String SAME_SITE_ATTRIBUTE_VALUES = ";HttpOnly;SameSite=None;Secure";
 
    
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        // Lets make sure that we are working with HTTP (that is, against HttpServletRequest and HttpServletResponse objects)
        if (req instanceof HttpServletRequest && res instanceof HttpServletResponse) {
            HttpServletRequest request = (HttpServletRequest) req;
            HttpServletResponse response = (HttpServletResponse) res;

            // Access-Control-Allow-Origin
            String origin = request.getHeader("Origin");
            LoggingService.writeToLog("call from origin: "+origin+", will be accepted? "+(allowedOrigins.contains(origin)||origin!=null), LogModule.WebAPI, LogLevel.Debug);
            
            response.setHeader("Access-Control-Allow-Origin", allowedOrigins.contains(origin) ? origin : "");
            response.setHeader("Vary", "Origin");
            String requestUrl = request.getRequestURL().toString();
            
            // Access-Control-Max-Age
            //response.setHeader("Access-Control-Max-Age", "3600");

            // Access-Control-Allow-Credentials
            response.setHeader("Access-Control-Allow-Credentials", "true");

            // Access-Control-Allow-Methods
            response.setHeader("Access-Control-Allow-Methods", "POST,HEAD, PUT, GET, OPTIONS, DELETE");
            
            /*
            This the code that i added to the code to use SameSite=None Cookie
            */
            boolean isResourceRequest = requestUrl != null ? StringUtils.isNoneBlank(allowedOrigins.stream().filter(s -> requestUrl.contains(s)).findFirst().orElse(null)) : null;
            if (!isResourceRequest) {
                Cookie[] cookies = ((HttpServletRequest) request).getCookies();
                if (cookies != null && cookies.length > 0) {
                    List<Cookie> cookieList = Arrays.asList(cookies);
                    Cookie sessionCookie = cookieList.stream().filter(cookie -> SESSION_COOKIE_NAME.equals(cookie.getName())).findFirst().orElse(null);
                    if (sessionCookie != null) {
                        String contextPath = request.getServletContext() != null && StringUtils.isNotBlank(request.getServletContext().getContextPath()) ? request.getServletContext().getContextPath() : ROOT_CONTEXT;
                        response.setHeader("Set-Cookie", sessionCookie.getName() + "=" + sessionCookie.getValue() + SESSION_PATH_ATTRIBUTE + contextPath + SAME_SITE_ATTRIBUTE_VALUES);
                    }
                }
            }
            
           /*
            End of new code
           */
            
            // Access-Control-Allow-Headers
            response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization, X-CSRF-TOKEN");
            if (request.getMethod().equals("OPTIONS")) {
                response.setStatus(HttpServletResponse.SC_ACCEPTED);
                return;
            }
     
        }

        chain.doFilter(req, res);
        
    }
    
 
 
}
Rami Khawaly
  • 126
  • 3
  • 14
-2

allow your source origin, in the API call

app.get('/rout',(req,res)=>{
    res.set('Access-Control-Allow-Origin', 'http://localhost:8000');
    res.json(res)
})

http://localhost:8000 replace this with your origin URL

cyberbrain
  • 3,433
  • 1
  • 12
  • 22
  • The OP asked a question to work on his backend code - which is the right place for CORS problems. Your answer seems to target on the Angular App? Where should this code be placed to help exactly? – cyberbrain Apr 03 '22 at 18:32