6

I am new to angular and spring-security.I am having problem with CORS when trying to log in from angular login-form page using basic authentication to the rest endpoint. My Angular code is running on http://localhost:4200 and rest end point on http://localhost:8181. My angular login-form tries to make request to http://localhost:8181/token which I have specified in my login controller. Even though I have added cors configuration in server side, I get this error :-

Failed to load http://localhost:8181/token: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:4200' is therefore not allowed access. The response had HTTP status code 403.

(angular) login.service.ts:-

@Injectable()
export class LoginService {
  constructor(private http: Http) {}

  sendCredential(username: string, password: string) {
    const url = 'http://localhost:8181/token';
    const encodedCredential = username + ':' + password;
    const basicHeader = 'Basic ' + btoa(encodedCredential);
    const headers = new Headers();
    headers.append('Content-Type', 'application/x-wwww-form-urlencoded');
    headers.append('Authorization' ,  basicHeader);
    const opts = new RequestOptions({headers: headers});
    return this.http.get(url, opts);
  }

}

(spring) SecurityConfig.java

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

private static final String[] PUBLIC_MATCHERS = {
            "/css/**",
            "/js/**",
            "/image/**",
            "/book/**",
            "/user/**"
    };

@Override
    protected void configure(HttpSecurity http) throws Exception{
        http
                .cors().and()
                .csrf().disable()
                .httpBasic()
                .and()
                .authorizeRequests()
                .antMatchers(PUBLIC_MATCHERS)
                .permitAll()
                .anyRequest()
                .authenticated();
    }
 @Bean
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("*"));
        configuration.setAllowedMethods(Arrays.asList("GET","POST","DELETE","PUT","OPTIONS"));
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userSecurityService).passwordEncoder(passwordEncoder());
    }

LoginController.java

@RestController
public class LoginController {

    @Autowired
    private UserService userService;

    @RequestMapping("/token")
    public Map<String, String> token(HttpSession session, HttpServletRequest request) {
        String remoteHost = request.getRemoteHost();
        int portNumber = request.getRemotePort();
        String remoteAddr = request.getRemoteAddr();

        System.out.println(remoteHost + ":" + portNumber);
        System.out.println(remoteAddr);


        return Collections.singletonMap("token", session.getId());
    }
}
4
  • CORS seems to be deactivated (spring.io/understanding/CORS) Commented Nov 1, 2017 at 14:56
  • I have added CORS configuration in SecurityConfig class as shown above in code block Commented Nov 1, 2017 at 14:58
  • problem is with your authentication mechanism, somehow it's not able to authenticate user. So it returns 403 status Commented Nov 1, 2017 at 15:03
  • when i use traditional approach where the class implement Filter interface and perform filterChain.doFilter for every request/response for cors handling instead of spring CorConfigurationSource it works fine. Commented Nov 1, 2017 at 15:15

5 Answers 5

8

Try this configuration. It should work fine for you.

@Bean
CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("*"));
        configuration.setAllowedMethods(Arrays.asList("GET", "POST", "OPTIONS", "DELETE", "PUT", "PATCH"));
        configuration.setAllowedHeaders(Arrays.asList("X-Requested-With", "Origin", "Content-Type", "Accept", "Authorization"));
        configuration.setAllowCredentials(true);
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }

Since you are using spring security / authentication. You should use setAllowCredentials(true).

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

3 Comments

No matter what I do I'm getting 403. I am using KeycloakWebSecurityConfigurerAdapter with your code, I've tried a bunch of similar code.
@ancm - it is very difficult to understand the exact problem without looking at the stack trace. Perhaps stackoverflow.com/questions/42153070/… or stackoverflow.com/questions/53493809/… or stackoverflow.com/questions/45051923/… might be helpful for you.
Setting the [allowedOrigins = *] is a very bad idea (unless that's exactly what you want). Modern browsers follow the [Same-origin policy] to (somewhat) prevent "website A" from making requests to / loading resources from "website B" unless "website B"'s backend explicitly allows it. Setting [allowedOrigins = *] basically allows anyone to bypass this Same-origin policy. There's more to it, but this is the gist of it. Useful links: developer.mozilla.org/en-US/docs/Web/Security/… developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CORS
4

I was stuck with this problem for 2 days and by adding @CrossOrigin("*") in controller solved my problem.

note: you can put your origin address instead of *

1 Comment

Thank you, I was searching for a solution for this problem, for almost 6 hours.
1

Use

@CrossOrigin("http://your-foreign-site/")
@RequestMapping("/token")

instead.

1 Comment

But I want to add cors configuration in global level. Not in the controller.
0

Add

<mvc:cors>
    <mvc:mapping path="/**" />
</mvc:cors>

to your web.xml to allow connections from all hosts

Origin: https://spring.io/blog/2015/06/08/cors-support-in-spring-framework

Comments

-1

inside your controller use the value from a .properties file

@Value("${cors.site.enable}") private String site;

use @crossOrigin(site)

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.