Spring boot app return Access to XMLHttpRequest at "myURL" has been blocked by CORS policy - spring-boot

i'm stuck with this issue: i use a spring boot app in backend and angular app for the front, the issue is when i call a specific rest url in the backend that uses a jar dependency that i have added to the backend as maven system scope dependency i get a cors error. All other backend urls are working fine
here is how i included the jar dependency for the backend:
<dependency>
<groupId>com.ex</groupId>
<artifactId>lib</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/src/main/resources/Utils.jar</systemPath>
</dependency>
note also that i'm using a Zuul dispatcher between the front and the backend
and that i did this config in the backend
#Component
public class CorsFilter extends OncePerRequestFilter {
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "authorization, content-type, xsrf-token, Content-Range, Content-Disposition, Content-Description, GAuth");
response.addHeader("Access-Control-Expose-Headers", "xsrf-token");
if ("OPTIONS".equals(request.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
} else {
filterChain.doFilter(request, response);
}
}
}
any help will be highly appreciated, thanks

Firstly, you need add #CrossOrigin annotation in your controller.
Than here is correct configuration from documentation:
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("*")
.allowedHeaders("*");
}
};
}
You can configure it your own way.
Secondly, if you are using SpringSecurity you need add .cors() to your configuration.
Example:
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.cors().and()
.csrf().disable()
.authorizeRequests()
.anyRequest().permitAll()
.and().httpBasic();
}

Related

How to add CORS to outh2/resource server in Spring Boot 2.x?

I have an oauth server and a resource server that I have created with JWT.
I also created an angular front end with 2 buttons:
The first button calls the auth server and gets the JWT token and adds it to the input box.
The second button calls the rest server with the JWT token as a bearer Authorisation http header.
Calling the 2 services from PostMan works perfectly but I cannot get the CORS setup correctly configured for the back end services.
Both buttons are giving me the below error:
Access to XMLHttpRequest at 'http://localhost:8085/oauth/token' from origin 'http://localhost:4200' has been blocked by CORS policy: Request header field authorization is not allowed by Access-Control-Allow-Headers in preflight response.
I added all 3 of these projects to my public github repo.
I have tried to add CORS with several ways:
The config on the resource rest service is smaller so I will outline that here
I tried adding the default .cors() on the HttpSecurity as well as setting it manually in the corsConfigurationSource() method.
#Configuration
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(final HttpSecurity http) throws Exception {
http.csrf().disable()
.cors()
.and().authorizeRequests().anyRequest().authenticated()
.and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER);
//I tried manually configured the cors as well
/*http.csrf().disable()
.cors().configurationSource(corsConfigurationSource())
.and().authorizeRequests().anyRequest().authenticated();
.and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER);*/
}
/* #Bean
CorsConfigurationSource corsConfigurationSource() {
final CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("*"));
configuration.setAllowedMethods(Arrays.asList("GET", "POST"));
configuration.setAllowCredentials(true);
//the below three lines will add the relevant CORS response headers
configuration.addAllowedOrigin("*");
configuration.addAllowedHeader("*");
configuration.addAllowedMethod("*");
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
*/
}
I also tried adding a servlet filter
#Component #Order(Ordered.HIGHEST_PRECEDENCE) public class
SimpleCorsFilter implements Filter {
#Override
public void init(final FilterConfig filterConfig) throws ServletException {
}
#Override
public void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse, final FilterChain filterChain) throws
IOException, ServletException {
final HttpServletResponse response = (HttpServletResponse) servletResponse;
final HttpServletRequest request = (HttpServletRequest) servletRequest;
response.addHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "content-type, x-requested-with, authorisation");
if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
} else {
filterChain.doFilter(servletRequest, servletResponse);
}
}
#Override
public void destroy() {
} }
Just can't get it to work. Can anyone please give me some guidelines here?
Silly mistake on my end as in both my SimpleCorsFilter.java files I specified that authorisation header tags are allowed but it is not authorisation with an S but with a Z.
Changing both the files in my config server
response.setHeader("Access-Control-Allow-Headers", "content-type,
x-requested-with, Authorization");
Extends your class with withWebMvcConfigurer rather than WebSecurityConfigurerAdapter. The override the following method:
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("*").allowedMethods("GET", "POST", "PUT", "PATCH", "DELETE").allowedHeaders("*");
}
It should add the origin. You can play with '*' and make many combination. I have given you idean now it is your turn to play with this API.

Spring Boot + CometD + CorFilter: An Authentication object was not found in the SecurityContext

My Project is Spring Boot 1.5.19 & Spring Security 4.2.6 & CometD 3.0.9.
In the UI side log is : CometD Subscribe Failed.
In the Services Back-end log is : org.springframework.security.authentication.AuthenticationCredentialsNotFoundException: An Authentication object was not found in the SecurityContext
Location is CorsFilter.java : chain.doFilter(req, resp);
This error seems doesn't impact functions, login and handshake and meta/connect always OK. However, Cometd Subscribe Failed and the page always refresh then the new data will return. This isn't what I want. I want to achieve realtime data.I don't know the SecurityContext Error is the reason of this problem or not.
#Component
#Order(0)
public class CorsFilter implements Filter{
#Override
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) resp;
HttpServletRequest request = (HttpServletRequest) req;
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, authorization, Content-Type, Authorization, credential, X-XSRF-TOKEN");
if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
} else {
chain.doFilter(req, resp);
}
}
#Override
public void destroy() {
}
#Override
public void init(FilterConfig arg0) throws ServletException {
}
}
Hope no errors and CometD realtime data run successfully.
It's just my fault.
In the CometdAuthenticator
#Autowired
private List<AbstractCometDSubscribeVoter> voters = Collections.emptyList();
add the #Autowired, everything works well.

How to enable CORS for Error Response in Spring MVC?

I'm working on application where I use Spring MVC for the Back-end and Angular5 for the Front-end. I have been stuck with implementation of Auth2 security layer including Cross-Origin Resource Sharing. My CORS filter implementation looks like this:
#Component
#Order(Ordered.HIGHEST_PRECEDENCE)
#WebFilter("/*")
public class WebSecurityCorsFilter implements Filter {
#Override
public void init(FilterConfig filterConfig) throws ServletException {
}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletResponse res = (HttpServletResponse) response;
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
res.setHeader("Access-Control-Max-Age", "3600");
res.setHeader("Access-Control-Allow-Headers", "Authorization, Content-Type, Accept, x-requested-with, Cache-Control");
if ("OPTIONS".equalsIgnoreCase(((HttpServletRequest) request).getMethod())) {
res.setStatus(HttpServletResponse.SC_OK);
} else {
chain.doFilter(request, res);
}
}
#Override
public void destroy() {
}
}
I works almost properly, I'm able to obtain access_token and use it to get protected data from ResourcesServer:
{"access_token":"4fcef1f8-4306-4047-9d4d-1c3cf74ecc44","token_type":"bearer","refresh_token":"397016eb-dfb0-4944-a2e0-50c3bd07c250","expires_in":29,"scope":"read
write trust"}
Browser console screenshot
The problem starts when I try to handle the request using expired token. In such case I'm not able to catch the correct ErrorResponeCode by Angular. Instead of 401 i Angular HttpClient got "Unknown Error" with status:0.
It looks like the problem is with CORS policy where the ErrorResponse doesn't include neccessery headers like Access-Control-Allow-Origin (...)
Failed to load http://localhost:8030/api/xxxx: No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://localhost:8070' is therefore not allowed
access. The response had HTTP status code 401.
ErrorResponse Headers - Screenshot
I have searched for how to enable CORS for ErorrResponse (InvalidTokenException etc.) in Spring MVC . I tried with various approach: accessDeniedHandler and setExceptionTranslator but without success. I really made effort to find the solution myself but I'm a beginner in Spring. I am not sure if this is possible at all.
ANGULAR (UPDATE)
#hrdkisback, it's rather not angular issue, anyway this my code :
#Injectable()
export class HttpInterceptorService implements HttpInterceptor {
addToken(req: HttpRequest<any>, oauthService: AuthenticationService): HttpRequest<any> {
if(oauthService.isTokenExist()){
return req.clone({ setHeaders: { Authorization: 'Bearer ' + oauthService.getAccessToken() }})
}
return req;
}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpSentEvent | HttpHeaderResponse | HttpProgressEvent | HttpResponse<any> | HttpUserEvent<any>> {
let oauthService = this.inj.get(AuthenticationService);
return next.handle(this.addToken(req,oauthService))
.do((event: HttpEvent<any>) => {
if (event instanceof HttpResponse) {
// process successful responses here
}
}, (error: any) => {
if (error instanceof HttpErrorResponse) {
// Error
console.log(error);
}
});
}
}
Issue solved after I added my CORS filter on ResourcesServer configuration level like this:
The correct configuration that works for me!
#Configuration
#EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
http
.addFilterAfter(new WebSecurityCorsFilter(), CsrfFilter.class)
...
}
....
}
In my previous configuration I added the filter in the same way but on the top level of MVC Security Configuration and it was the root couse of my issue:
The previous configuration that caused my issue
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
http
.addFilterAfter(new WebSecurityCorsFilter(), CsrfFilter.class)
...
}
....
}
I faced the same problem..I was trying Basic Auth with Angular 5.
The problem is that you don't add the CORS header on error response.
Here is what I did
#Component
public class AuthEntryPoint extends BasicAuthenticationEntryPoint {
#Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authEx)
throws IOException, ServletException {
response.addHeader("WWW-Authenticate", "Basic realm=" +getRealmName());
response.addHeader("Access-Control-Allow-Origin", "http://localhost:4200");
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
PrintWriter writer = response.getWriter();
writer.println("HTTP Status 401 - " + authEx.getMessage());
}
}
That would do the trick!

Angular4 CORS header contains multiple values

please could somebody help to resolve issue:
backend spring application
web.xml
<filter>
<filter-name>corsFilter</filter-name>
<filter-class>package.controllers.auth.CorsFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>corsFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
filter
public class CorsFilter implements Filter {
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletResponse httpResponse = (HttpServletResponse) response;
httpResponse.setHeader("Access-Control-Allow-Origin", "*,*");
httpResponse.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE");
httpResponse.setHeader("Access-Control-Allow-Headers", "Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization,Access-Control-Allow-Origin");
httpResponse.setHeader("Access-Control-Expose-Headers", "Access-Control-Allow-Credentials");
httpResponse.setHeader("Access-Control-Allow-Credentials", "true");
httpResponse.setHeader("Access-Control-Max-Age", "10");
System.out.println("---CORS Configuration Completed---");
chain.doFilter(request, response);
}
Angular frontend:
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
return this.http.post(AppSettings.API_ENDPOINT + '/url', JSON.stringify(user), options)
.map(response => response.json())
}
Browser return issue:
Response to preflight request doesn't pass access control check: The
'Access-Control-Allow-Origin' header contains multiple values
I was also facing same issue. Root cause was that cors header was going multiple times. I commented out
httpResponse.setHeader("Access-Control-Allow-Origin", "*");"
line.
I had only one security config class which looks like below. This class, solved my issue of cors.
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
// your security config here
.authorizeRequests()
.antMatchers(HttpMethod.TRACE, "/**").denyAll()
.antMatchers("/admin/**").authenticated()
.anyRequest().permitAll()
.and().httpBasic()
.and().headers().frameOptions().disable()
.and().csrf().disable()
.headers()
// the headers you want here. This solved all my CORS problems!
/* .addHeaderWriter(new StaticHeadersWriter("Access-Control-Allow-Origin", "*"))*/
.addHeaderWriter(new StaticHeadersWriter("Access-Control-Allow-Methods", "POST, GET"))
.addHeaderWriter(new StaticHeadersWriter("Access-Control-Max-Age", "3600"))
.addHeaderWriter(new StaticHeadersWriter("Access-Control-Allow-Credentials", "true"))
.addHeaderWriter(new StaticHeadersWriter("Access-Control-Allow-Headers", "Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization"));
}
}
In my case, i am just doing POC, and calling Rest resource from angular application. I was facing only issue in CORS .
To solve only cors issue, bare minimum below code is also sufficient.
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
}
}

Invalid CORS request in Spring

I am trying to enable certain IPs to access a particular method.
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/updateDetail")
.allowedOrigins("127.0.0.1", "10.96.33.45")
.allowedMethods("GET", "POST");
}
But when I am trying to call the same method I am getting invalid CORS request. Can anyone help me with this?
"Invalid CORS request" is returned by org.springframework.web.cors.DefaultCorsProcessor when
Spring is configured to use CORS and
browser sends "Origin" header with the request and it does not match with your server domain/port/scheme and
response does not have "Access-Control-Allow-Origin" header and
the request is not a preflight request.
If you don't need CORS, call cors().disable() in your implementation of WebSecurityConfigurerAdapter#configure(HttpSecurity http) (there might be other ways to do this, for example if you use Spring Boot).
Or you could add "Access-Control-Allow-Origin" header to your reponses using e.g. org.springframework.web.cors.CorsConfiguration or addCorsMappings (like you did, but maybe you should add more methods or url or IP doesn't match?).
This class is what are you looking for:
#Component
#Order(Ordered.HIGHEST_PRECEDENCE)
public class SimpleCorsFilter implements Filter {
public SimpleCorsFilter() {
}
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
HttpServletRequest request = (HttpServletRequest) req;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
response.setHeader("Access-Control-Max-Age", "12000");
response.setHeader("Access-Control-Allow-Headers", "Access-Control-Allow-Headers, Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
response.setHeader("Access-Control-Expose-Headers", "*");
if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
} else {
chain.doFilter(req, res);
}
}
#Override
public void init(FilterConfig filterConfig) {
}
#Override
public void destroy() {
}
}
This filter will resolve all your cors issues
I was debugging problem like this for few days. The actual problem was that I had typo in my service uri name /data vs. /daba etc. This cause SpringBoot to fail to retrieve CORS configuration (even when I had /** mapping) so CORS-preflight got status 403, which caused browser not to make the actual request at all - if browser would have fired the request, Spring would have returned "Resource not found" and then I would have noticed the typo much faster.
if you started your application at localhost, the browser formulates the origin as null, so application will not get the origin localhost:8080 or 127.0.0.1, it will get null
I think changing 127.0.0.1 with null will fix your problem
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/updateDetail")
.allowedOrigins("null", "10.96.33.45")
.allowedMethods("GET", "POST");
}

Resources