SKP_Dev
SKP_Dev

Reputation: 41

Ajax CORS request with basicauth gives 401 error on browser

I know there are lots of posts regarding the same problem, but none of it resolve my issue.

I have a springboot microservice application with the following API

@RestController
@RequestMapping({ "/sample" })
public class SampleController {


    @CrossOrigin(origins = "http://192.168.0.31:8080", allowCredentials = "false", allowedHeaders = "*")
    //@CrossOrigin//(allowCredentials = "false")
    @RequestMapping(value="/welcome" , method=RequestMethod.POST, produces={"application/json"})
    public JSONObject getWelcomeResponse(@RequestParam Map<String,String> request){
        JSONObject response=new JSONObject();

        response.put("response", "Welcome user");
        System.out.println("Complterd ****");
        return response;
    }
}

properties file

server.port=8081
security.user.name=test
security.user.password=test123
#security.basic.enabled=false

And my client code is

 $(document).ready(function(){
            $.ajax({
                url: "http://192.168.0.31:8081/sample/welcome",
                type : "POST",
                crossDomain:true,
                crossOrigin:true,

                beforeSend: function (xhr) {
                    // Use BASIC Authentication
                    xhr.setRequestHeader ("Authorization", "Basic " + btoa("test:test123"));
                },
                error: function(xhr, status, errorThrown) {
                    alert(status, errorThrown);
                    // Error block
                    console.log("xhr: " + xhr);
                    console.log("status: " + status);
                    console.log("errorThrown: " + errorThrown);
                }
            })
            .then(function(data, status, xhr) {
                alert(data);
                console.log("xhr: " + xhr);
                console.log("status: " + status);
                console.log("data: "+ data);

                $('.message').append(JSON.stringify(data));

            });
        });

When I disable the basic auth, The cors request is works fine. But if it enabled it gives 401 preflight request error.

I have tried @CrossOrigin with default as well as customized way also. But getting the same error. Also tried with a filter class like below.

@EnableWebMvc
public class MyAppConfigurations  implements Filter {

       @Override
       public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)

                     throws IOException, ServletException {

              HttpServletResponse httpResponse = (HttpServletResponse) response;

              HttpServletRequest httpRequest = (HttpServletRequest) request;

              if("OPTIONS".equalsIgnoreCase(httpRequest.getMethod())) {

                     httpResponse.setStatus(HttpServletResponse.SC_OK);
                     System.out.println("filterde response");

              } else {

                     chain.doFilter(request, response);

              }
       }
}

Can somebody help me to figure out, what I am missing on this code.

Upvotes: 1

Views: 449

Answers (3)

Afsun Khammadli
Afsun Khammadli

Reputation: 2068

You have to create CORS FILTER for your Spring MicroService

import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;


@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CorsFilter implements Filter {

    @Override
    public void doFilter(ServletRequest req, ServletResponse res,
                         FilterChain filterChain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        HttpServletRequest request = (HttpServletRequest) req;

        if (response instanceof HttpServletResponse) {
            addCorsHeader(response);
            if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
                response.setStatus(HttpServletResponse.SC_OK);
            } else {
                filterChain.doFilter(req, res);
            }
        }
    }

    private void addCorsHeader(HttpServletResponse response) {
        response.addHeader("Access-Control-Allow-Origin", "http://localhost:4200"); // Update with yours
        response.addHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, HEAD");
        response.addHeader("Access-Control-Allow-Credentials", "true");
        response.addHeader("Access-Control-Allow-Headers", "Authorization, X-PINGOTHER, Origin, X-Requested-With, Content-Type, Accept");
        response.addHeader("Access-Control-Max-Age", "1728000");
    }

    @Override
    public void destroy() {
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
}

Upvotes: 1

Ortomala Lokni
Ortomala Lokni

Reputation: 62615

According to the CORS specification, the CORS preflight request must be accepted without any authentication.

You have to configure your web server or Spring Security to disable authentication on all OPTIONS requests related to preflight.

Upvotes: 0

DadyByte
DadyByte

Reputation: 914

Add @CrossOrigin before class like

@RequestMapping({ "/sample" })
@CrossOrigin(origins = "http://192.168.0.31:8080")
public class SampleController {

try adding in your /welcome Rest Controller

response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "x-requested-with");

Upvotes: 0

Related Questions