Issue
I found that while accessing ReST services from single-page applications that in order to properly allow access to ReST endpoints I had to register a CORS filter before my authentication filter. Is this less secure or a poor security practice?
My security configuration now looks like
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Inject
public void setUserDetailsService(UserDetailsService userDetailsService) {
this.userDetailsService = userDetailsService;
}
private UserDetailsService userDetailsService;
@Override
protected void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
authenticationManagerBuilder.userDetailsService(userDetailsService)
.passwordEncoder(new BCryptPasswordEncoder());
}
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
.antMatchers("/health","/metrics", "/v1/users/register", "/swagger-ui/**", "/v2/api-docs").permitAll()
.antMatchers("/mappings", "/v1/**", "/backend-service/**").authenticated()
.and()
.httpBasic()
.realmName("serviceGateway")
.and()
.csrf()
.disable()
.headers()
.frameOptions().disable()
.and().addFilterBefore(new SimpleCORSFilter(), ChannelProcessingFilter.class);
}
}
And my SimpleCORSFilter looks like
public class SimpleCORSFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
/**
* This method adds specific headers to the HTTP request to enable CORS
* requests
* @param request
* @param response
* @param chain
* @throws IOException
* @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");
chain.doFilter(request, res);
}
@Override
public void destroy() {
}
}
I access the code with a simple $http call in Angular
$scope.login = function() {
$http({
method: 'GET',
url: 'https://myservice.mydomain.com:8095/v1/users/login',
headers: {
'Authorization': 'Basic ' + btoa("username:password")
}
})
.then(successCallback);
};
I am thinking that putting the CORS filter before security only means that the CORS headers will be added to every request, which doesn't seem like much of a security hole since I send no sensitive data in headers, excepting the Authorization header.
Am I thinking right here or is there something I am not seeing?
Solution
I think this is perfectly fine. In fact when your JavaScript code posts to a resource in another origin, the browser will issue a pre-flight request (OPTIONS
verb) without the authorization
header.
If your authentication code runs before the CORS handler, it has to make an exception for this request, to avoid returning 401 Unauthorized
on the pre-flight.
Answered By - MvdD
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.