1

I got stuck with a cross origin cors issue with my project. I have to send a get request from my Angular2 app running on localhost:4200 to my Spring Boot backend running on localhost:8080 with some header attributes. the request i want to send looks like this:

test() {
  let jwt = localStorage.getItem('token');
  let headers = new Headers({
        'Content-Type': 'application/json; charset=utf-8',
        'Authorization': 'Bearer ' + jwt 
    });

    let options = new RequestOptions({ headers: headers });
    this.http.get('http://localhost:8080/service/events/byTeamId/1', options)
        .map((response: Response) => response.json())
        .subscribe(
            data => console.log('Response: '+data),
            err => console.log('error: '+err),
            () => console.log('Secret Quote Complete')
        );


}

But this request doesn't arrive on the server side how i'd like to have it. With Postman to test the api it works.

My Spring Boot Backend looks like this:

WebSecurityConfig.java:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();

    @Autowired
private SimpleCorsFilter simpleCorsFilter;

@Resource
private UserDetailsServiceImpl userDetailsService;

@Resource
private JwtAuthenticationProvider jwtAuthenticationProvider;

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
            .authorizeRequests()
                .antMatchers("/", "/home", "/login", "/register").permitAll()
                .anyRequest().authenticated()
                .and()
            .addFilterBefore(simpleCorsFilter, ChannelProcessingFilter.class)
            .addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
            .logout()
                .permitAll()
            .and().csrf().disable();

}...

My SimpleCorsFilter looks like this:

    @Component
public class SimpleCorsFilter implements Filter {

    private final Logger log = LoggerFactory.getLogger(SimpleCorsFilter.class);

    public SimpleCorsFilter() {
        log.info("SimpleCORSFilter init");
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;
        response.setHeader("Access-Control-Allow-Origin", "http://localhost:4200");
        //response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With, remember-me, Authorization");

        chain.doFilter(req, res);
    }

    @Override
    public void init(FilterConfig filterConfig) {
    }

    @Override
    public void destroy() {
    }

}

Wit Postman it works properly:

Postman Get Request

But when I test it on my chrome browser I get:

Chrome Request

So to me it looks like i don't receive the header properties like "Authorization" at my backend. I also see this by debugging the request in the spring boot backend. I just see "null" as header of this request.

Does anyone have an idea why i don't get my request headers correct at the api endpoint?

I already had a look here:

restlet.com/blog/2016/09/27/how-to-fix-cors-problems/

and looked into several similar issues posted on stackoverflow.

4
  • Have you tried changing "Access-Control-Allow-Origin", "http://localhost:4200" to "Access-Control-Allow-Origin", "*" Commented Dec 26, 2016 at 17:10
  • 1
    It works with this solution: add this to spring security config: .antMatchers(org.springframework.http.HttpMethod.OPTIONS, "/service/**").permitAll() stackoverflow.com/questions/36142155/… Commented Dec 26, 2016 at 17:15
  • Ant thanks for your input. Yes I also tried it with ` "Access-Control-Allow-Origin", "*" ` Commented Dec 26, 2016 at 17:22
  • Great that you figured it out! :) Let's up your answer, you deserve it :D Commented Dec 26, 2016 at 17:24

2 Answers 2

2

To me it works with this solution: add this to spring security config:

.antMatchers(org.springframework.http.HttpMethod.OPTIONS, "/service/**").permitAll()

http
.authorizeRequests()
                .antMatchers("/", "/home", "/login", "/register").permitAll()
                .antMatchers(org.springframework.http.HttpMethod.OPTIONS, "/service/**").permitAll()
                .anyRequest().authenticated()
                .and()
            .addFilterBefore(simpleCorsFilter, ChannelProcessingFilter.class)
            .addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
            .logout()
                .permitAll()
            .and().csrf().disable();

(jwt token is still required, how i want to have it)

from:

CORS Origin Spring Boot Jhipster - pre-flight fails

Sign up to request clarification or add additional context in comments.

1 Comment

waisted 4hrs thinking my header is not correct.Nothing worked even after enabling CROS. .antMatchers(org.springframework.http.HttpMethod.OPTIONS, "/service/**") workes BUT why does this still required JWT auth even though we have set . permitALL()?
0

I have had this same issue and i am using spring boot for my api and Angular 2.3.1. Im not sure if you are using Npm and Angular Cli. If you are using npm for development then the following can be done to fix this issue. You can proxy the api calls to your backend.

Step 1: create a file called proxy.conf.json in the same directory as package.json with the following content

{
  "/api": {
    "target": "http://localhost:8080",
    "secure": false,
    "pathRewrite": {"^/api" : ""}
  }
}

so instead of using http://localhost:8080/service/events/byTeamId/1 for your api requests you will use /api/service/events/byTeamId/1

Notice the added "/api" and the removal of "http://localhost:8080". This means that any request being made that starts with /api will be proxied. This is what you want because you don't just want any url being proxied. The line "pathRewrite": {"^/api" : ""} ensures that "/api" is removed so that in the end your actual url is being requested.

Step 2: Update package.json

Update the line "start": "ng serve", and change it to "start": "ng serve --proxy-config proxy.conf.json", this will ensure that the proxy is configured and used

Step 3: Use npm start

While using angular cli and making sure you are in the project directory you can now start your application where your requests are proxied using

npm start

Angular Cli documentation

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.