Ajax login with spring and CORS security
I followed this tutorial to implement the api with spring-security. It works well locally, but when I deploy it to a remote server, the entry endpoint is not available due to cors policy (server: 80 is trying to reach server: 8080).
I added cors filters to handle this, but it seems that the login method (and possibly protected methods, I can't test it since I can't login) is not using my custom filter. Endpoints accessible to unregistered users work well
The request is preprogrammed, but the server is not adding the correct headers on the remote server.
First, here is the request and response for the requested request before reaching the public endpoint
Request:
Host: 01.02.03.04:8080
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Access-Control-Request-Method: GET
Access-Control-Request-Headers: x-requested-with
Origin: http://01.02.03.04
Connection: keep-alive
Cache-Control: max-age=0
Answer:
Access-Control-Allow-Methods: GET,HEAD,POST
Access-Control-Allow-Origin: http://01.02.03.04
Access-Control-Max-Age: 1800
Allow: GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH
Content-Length: 0
Date: Mon, 10 Jul 2017 10:40:32 GMT
Vary: Origin
access-control-allow-credentials: true
access-control-allow-headers: x-requested-with
Here is the request and response for a pre-flight request before reaching the entry endpoint:
Request:
Host: 01.02.03.04:8080
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Access-Control-Request-Method: POST
Access-Control-Request-Headers: content-type,x-requested-with
Origin: http://01.02.03.04
Connection: keep-alive
Answer:
Allow: GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH
Content-Length: 20
Date: Mon, 10 Jul 2017 11:18:40 GMT
We can easily see that when trying to reach / login, the server doesn't respond correctly.
Here is an ajax test to achieve / login:
Login.prototype.login = function(){
var self = this;
return function(){
$.ajax({
url:properties.serverUrl+'login',
beforeSend:function(xhr) {
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
},
type : 'POST',
dataType:"json",
contentType: 'application/json',
data:JSON.stringify({
username:"username",
password:"password"
}),
success:self.handleToken(),
error:utils.displayError
});
}
}
Here's a way to configure the WebSecurityConfigurerAdapter:
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable() // We don't need CSRF for JWT based authentication
.exceptionHandling()
.authenticationEntryPoint(this.authenticationEntryPoint)
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers(FORM_BASED_LOGIN_ENTRY_POINT).permitAll() // Login end-point
.antMatchers(TOKEN_REFRESH_ENTRY_POINT).permitAll() // Token refresh end-point
.and()
.authorizeRequests()
.antMatchers(TOKEN_BASED_AUTH_ENTRY_POINT).authenticated() // Protected API End-points
.and()
.addFilterBefore(new CustomCorsFilter(), UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(buildAjaxLoginProcessingFilter(), UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(buildJwtTokenAuthenticationProcessingFilter(), UsernamePasswordAuthenticationFilter.class);
}
And here is a custom cors filter:
public class CustomCorsFilter extends CorsFilter {
public CustomCorsFilter() {
super(configurationSource());
}
private static UrlBasedCorsConfigurationSource configurationSource() {
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.setMaxAge(36000L);
config.setAllowedMethods(Arrays.asList("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return source;
}
}
Thank you for your responses,
Emmanuel
source to share
No one has answered this question yet
Check out similar questions: