Why I don't get authorization header? - java

I use the Spring framework. If I send a request using postman, I get the authorization header, but if I use Axois I don't get it. What is the problem?
Axois send:
axios({
method: 'get',
url: 'http://localhost:8081/api/posts',
headers: { 'Authorization': 'Bearer_' + localStorage.getItem("username")} // Cookies.get('Token')
})
Cors in spring
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedHeaders("*")
.exposedHeaders("Authorization", "authorization")
.allowedOrigins("*")
.allowedMethods("*")
.allowCredentials(false).maxAge(3600);;
}
Spring security config:
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic().disable()
.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers(LOGIN_ENDPOINT, REGISTRATION_ENDPOINT).permitAll()
.antMatchers(ADMIN_ENDPOINT).hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.apply(new JwtConfigurer(jwtTokenProvider));
}
Get the headers here:
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain filterChain)
throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) req;
Map<String, List<String>> headersMap = Collections.list(httpRequest.getHeaderNames())
.stream()
.collect(Collectors.toMap(
Function.identity(),
h -> Collections.list(httpRequest.getHeaders(h))
));
Postman request
Headers with postman
Headers with Axios

I added Bean:
#Bean
CorsConfigurationSource corsConfigurationSource() {
final UrlBasedCorsConfigurationSource source = new
UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.addAllowedMethod("*");
source.registerCorsConfiguration("/**", config.applyPermitDefaultValues());
return source;
}

Related

Spring security return 403 if request macher not pass

Is it possible that if AndRequestMatcher which checks if url is orders/notify and request comes from proper IP return 403? Below configuration always passes which shouldnt if IP address don't match.
#Override
public void configure(HttpSecurity http) throws Exception {
AntPathRequestMatcher antRequestMatcher = new AntPathRequestMatcher("/orders/notify/**", HttpMethod.POST.name());
AndRequestMatcher andMatcher = new AndRequestMatcher(new HeaderIPAddressRequestMatcher(ips), antRequestMatcher);
http.cors()
.and()
.httpBasic().disable()
.csrf().disable()
.formLogin().disable()
.logout().disable()
.sessionManagement().disable()
.authorizeRequests()
.requestMatchers(andMatcher).permitAll()
.anyRequest().permitAll();
http.headers()
.httpStrictTransportSecurity().maxAgeInSeconds(YEAR.toSeconds()).includeSubDomains(false);
}
I achieve it by creating custom filter:
public class IPHeaderFilter implements Filter {
private final List<String> ips;
public IPHeaderFilter(List<String> ips) {
this.ips = ips;
}
#Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
var request = (HttpServletRequest) servletRequest;
var response = (HttpServletResponse) servletResponse;
AntPathRequestMatcher antRequestMatcher = new AntPathRequestMatcher("/orders/notify/**", HttpMethod.POST.name());
if (antRequestMatcher.matches(request)) {
HeaderIPAddressRequestMatcher ipHeaderMatcher = new HeaderIPAddressRequestMatcher(ips);
if (!ipHeaderMatcher.matches(request)) {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
} else {
chain.doFilter(request, response);
}
} else {
chain.doFilter(request, response);
}
}
}

CORS in Spring Boot with Spring Security + React

After deploy I got problem with CORS. I can access data directly from my API but when trying fetch it from React app I got problem as in an image:
I tried to add filters to add to every header Access-Control-Allow-Origin and it now return data from API and I can see it in browsers console but react cant get it
WebSecurity.java
#Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable();
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and();
http.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and();
http.authorizeRequests()
.antMatchers("/api/auth/**").permitAll()
.antMatchers("/api/test/**").permitAll()
.anyRequest().authenticated();
http.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);
}
#Bean
public FilterRegistrationBean crosFilterRegistration(){
FilterRegistrationBean registrationBean = new FilterRegistrationBean(new MyCorsFilter());
registrationBean.setName("CORS Filter");
registrationBean.addUrlPatterns("/*");
registrationBean.setOrder(1);
return registrationBean;
}
#Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Collections.singletonList("https://*************"));
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS"));
configuration.setAllowedHeaders(Arrays.asList("Access-Control-Allow-Headers", "Access-Control-Allow-Origin",
"Access-Control-Request-Method", "Access-Control-Request-Headers", "Origin",
"Cache-Control", "Content-Type"));
configuration.setAllowCredentials(true);
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
MyCorseFiltre.java
#Component
#Order(Ordered.HIGHEST_PRECEDENCE)
public class MyCorsFilter implements Filter {
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
final HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", "https://**************");
response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, HEAD, OPTIONS");
response.setHeader("Access-Control-Allow-Headers", "Authorization, Content-Type");
response.setHeader("Access-Control-Max-Age", "3600");
if ("OPTIONS".equalsIgnoreCase(((HttpServletRequest) req).getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
} else {
chain.doFilter(req, res);
}
}
#Override
public void destroy() {
}
#Override
public void init(FilterConfig config) throws ServletException {
}
}
Application.java
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("https://*************");
}
};
}
This row
response.setHeader("Access-Control-Allow-Origin", "https://**************");
adds the duplicated header. So does this row:
configuration.setAllowedOrigins(Collections.singletonList("https://*************"));
One of them is enough. Preferably the latter. The same goes for most of the CORS config you have.

Spring boot + spring security config not working

I'm trying to configure spring security and controller CORS requests, but the preflight request is not working. I have a controller, test, and spring security config which are related to the problem. What I'm doing wrong?)
Java 8, Spring Boot 2.1.4
Controller
#RestController
#RequestMapping("/login")
#CrossOrigin
public class LoginController {
#RequestMapping(path = "/admin", consumes = "application/json", produces = "application/json")
public ResponseEntity<Admin> loginAdmin(#RequestBody Admin admin) {
String username = admin.getUsername();
String password = admin.getPassword();
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
ResponseEntity<Admin> responseEntity;
Admin foundAdmin = adminRepository.findByUsername(username);
if (foundAdmin != null) {
String token = jwtTokenProvider.createToken(username, adminRepository.findByUsername(username).getRoles());
AdminAuthenticatedResponse contractorAuthenticatedResponse = new AdminAuthenticatedResponse(foundAdmin, token);
responseEntity = new ResponseEntity<>(contractorAuthenticatedResponse, HttpStatus.ACCEPTED);
} else {
responseEntity = new ResponseEntity<>(admin, HttpStatus.NOT_FOUND);
}
return responseEntity;
}
}
Security config
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic().disable()
.csrf().disable()
.cors().and().formLogin().and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/login/**").permitAll()
.antMatchers("/register/**").permitAll()
.antMatchers("/h2-console/**").permitAll()
.antMatchers(HttpMethod.GET, "/restapi/customers/**").permitAll()
.antMatchers(HttpMethod.DELETE, "/restapi/customers/**").hasRole("CUSTOMER")
.antMatchers(HttpMethod.PUT, "/restapi/customers/**").hasRole("CUSTOMER")
.antMatchers(HttpMethod.PATCH, "/restapi/customers/**").hasRole("CUSTOMER")
.antMatchers(HttpMethod.GET, "/restapi/contractors/**").permitAll()
.antMatchers(HttpMethod.DELETE, "/restapi/contractors/**").hasRole("CONTRACTOR")
.antMatchers(HttpMethod.PUT, "/restapi/contractors/**").hasRole("CONTRACTOR")
.antMatchers(HttpMethod.PATCH, "/restapi/contractors/**").hasRole("CONTRACTOR")
.antMatchers(HttpMethod.PATCH, "/restapi/workRequests/**").hasAnyRole("CONTRACTOR", "CONTRACTOR", "ADMIN")
.antMatchers(HttpMethod.PUT, "/restapi/workRequests/**").hasAnyRole("CONTRACTOR", "CONTRACTOR", "ADMIN")
.antMatchers(HttpMethod.POST, "/restapi/workRequests/**").hasAnyRole("CONTRACTOR", "CONTRACTOR", "ADMIN")
.antMatchers(HttpMethod.DELETE, "/restapi/workRequests/**").hasAnyRole("CONTRACTOR", "CONTRACTOR", "ADMIN")
.antMatchers(HttpMethod.GET, "/restapi/workRequests/**").hasAnyRole("CONTRACTOR", "CONTRACTOR", "ADMIN")
.anyRequest().authenticated()
.and()
.apply(new JwtConfigurer(jwtTokenProvider))
// Allow pages to be loaded in frames from the same origin; needed for H2-Console
.and()
.headers()
.frameOptions()
.sameOrigin();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(userRepositoryUserDetailsService)
.passwordEncoder(encoder());
}
#Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList(ALL));
configuration.setAllowedMethods(Arrays.asList(ALL));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring()
.antMatchers("/**", "/resources/**", "/index.html", "/login/admin", "/template/**", "/",
"/error/**", "/h2-console", "*/h2-console/*");
}
Test
#Test
public void testLogin() {
Admin admin = new Admin("network", "network");
// adminRepository.save(admin);
String s = adminRepository.findByUsername("network").getUsername();
RequestEntity<Admin> requestEntity =
RequestEntity
.post(uri("/login/admin"))
.contentType(MediaType.APPLICATION_JSON)
.body(admin);
ResponseEntity<Admin> responseEntity = this.restTemplate.exchange(requestEntity, Admin.class);
assertNotNull(responseEntity);
System.out.println(responseEntity.getStatusCode());
}
I'm expecting successful request, but I'm getting INTERNAL SERVER ERROR.
403 Forbidden or No Permission to Access.
A 403 Forbidden error means that you do not have permission to view the requested file or resource
Please attempt the test runs with #WithMockUser
#Test
#WithMockUser
public void corsWithAnnotation() throws Exception {
ResponseEntity<Admin> entity = this.restTemplate.exchange(
...
}
Reference : Preview Spring Security Test: Web Security

Spring API REST and Cors and AngularJS

I have probem with Spring Boot and Cors
After some searches I was able to find solutions (Spring Data Rest and Cors and How to configure CORS in a Spring Boot + Spring Security application?) which I tried but which does not solve my problem.
My code for the Authentication with JWT
public class AuthenticationFilter extends AbstractAuthenticationProcessingFilter
{
private final Logger log = LoggerFactory.getLogger(AuthenticationFilter.class);
private final String tokenHeader = "Authorization";
private final TokenUtils tokenUtils = new TokenUtils();
public AuthenticationFilter()
{
super("/api/v1/**");
tokenUtils.expiration = 86400;
tokenUtils.secret = "papipapo123popo";
}
#Override
public Authentication attemptAuthentication(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws AuthenticationException, IOException, ServletException
{
String header = httpServletRequest.getHeader(tokenHeader);
if(header == null || !header.startsWith("Bearer "))
{
log.error("Not found JWT token in request headers","Not found header Authorization");
throw new JwtTokenMissingException("No JWT token found in request headers");
}
String token = header.substring(7);
JwtAuthentication jwtAuthentication = new JwtAuthentication(token);
boolean isValid = tokenUtils.validateToken(token);
if(!isValid)
{
log.error("JWT token is expired",token);
throw new JwtTokenExpired("JWT token is expired");
}
return this.getAuthenticationManager().authenticate(jwtAuthentication);
}
#Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException
{
super.successfulAuthentication(request, response, chain, authResult);
String token = ((JwtAuthentication)authResult).getToken();
log.info("Token is authenticated : ",token);
chain.doFilter(request, response);
}
#Override
protected AuthenticationManager getAuthenticationManager()
{
return authentication -> (JwtAuthentication) authentication;
}
}
My code for Configuration security
#Configuration
#EnableWebSecurity
#EnableAutoConfiguration
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter
{
#Inject
private EntryPointUnauthorizedHandler entryPointUnauthorizedHandler;
#Inject
private JwtAuthenticationProvider jwtAuthenticationProvider;
#Bean
#Override
public AuthenticationManager authenticationManager() throws Exception
{
return new ProviderManager(Arrays.asList(jwtAuthenticationProvider));
}
#Bean
public AuthenticationFilter authenticationFilter() throws Exception
{
AuthenticationFilter authenticationFilter = new AuthenticationFilter();
authenticationFilter.setAuthenticationManager(authenticationManager());
authenticationFilter.setAuthenticationSuccessHandler(new EntryPointSuccessHandler());
return authenticationFilter;
}
#Bean
public FilterRegistrationBean corsFilter()
{
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedHeader("*");
config.addAllowedMethod("*");
config.addAllowedOrigin("*");
source.registerCorsConfiguration("/**",config);
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new CorsFilter(source));
filterRegistrationBean.setOrder(0);
return filterRegistrationBean;
}
#Override
protected void configure(HttpSecurity http) throws Exception
{
http
.csrf()
.disable()
.exceptionHandling()
.authenticationEntryPoint(entryPointUnauthorizedHandler)
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
.antMatchers(HttpMethod.POST,"/api/auth").permitAll()
.anyRequest().authenticated();
http.addFilterBefore(authenticationFilter(),UsernamePasswordAuthenticationFilter.class);
http.headers().cacheControl();
}
}
I always receive an error 401 refused accesse.
I am a beginner in Spring-Boot.
You can help me.
I solved my problem by adding a Class which implements Filter.
#Component
public class CorsConfig implements Filter
{
#Override
public void init(FilterConfig filterConfig) throws ServletException
{}
#Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException
{
HttpServletRequest request = (HttpServletRequest) servletRequest;
String method = request.getMethod();
if(method.equals("OPTIONS") || method.equals("options"))
{
HttpServletResponse response = (HttpServletResponse) servletResponse;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization");
response.setStatus(200);
filterChain.doFilter(servletRequest, servletResponse);
}
else
{
HttpServletResponse response = (HttpServletResponse) servletResponse;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization");
filterChain.doFilter(servletRequest, servletResponse);
}
}
#Override
public void destroy()
{}
}
First class:
#Configuration
public class MyConfiguration {
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
};
}
}
Second class:
#EnableWebSecurity
#Configuration
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/**").authorizeRequests().requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
.anyRequest().fullyAuthenticated().and().httpBasic().and().csrf().disable();
}
}
And be happy my friend
1: Create a class WebMvcConfig extends WebMvcConfiguration and override addCorsMappings method.
2: Don't forget to make it #Configuration annotation
#Configuration
public class WebMvcCofig implements WebMvcConfigurer{
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/*")
.allowedOrigins("*")
.allowedMethods("*")
.allowedHeaders("*")
.allowCredentials(true);
}
}

Spring security on cross platform in Spring boot application

How to configure spring security on cross-platform, for example I have two application one is server side where all the java code and spring security part I am doing and other client side where all angular js and html files present.
I want to integrate my custom login page which is present at client side with Spring security how can I achieve that, following is my code for Spring security.
public class AppSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/index.html", "/assests/**", "/app/**",
"/**/*.js", "/**/*.css", "/**/*.jpg", "/**/*.png",
"/**/*.jpg", "/**/*.gif", "#/index.html", "/home",).permitAll()
.anyRequest().authenticated()
.and().formLogin()
.loginPage("/login").failureUrl("/login?error")
.usernameParameter("username")
.passwordParameter("password")
.and()
.addFilterBefore(new AppCORSFilter(), ChannelProcessingFilter.class)
.addFilterAfter(new CsrfHeaderFilter(), CsrfFilter.class)
.csrf().disable();
}
}
and this is My CORS filter.
public class AppCORSFilter implements Filter {
private static final String ALLOWED_ORIGINS = "*";
private static final String ALLOWED_HTTP_HEADERS = "accept, x-requested-with, access-control-allow-origin,Content-Type,authorization";
private static final String ALLOWED_HTTP_METHODS = "POST,GET,PUT,OPTIONS,DELETE";
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
//String headerValue = request.getHeaders("Access-Control-Request-Headers");
response.setHeader("Access-Control-Allow-Origin", ALLOWED_ORIGINS);
response.setHeader("Access-Control-Allow-Methods", ALLOWED_HTTP_METHODS);
response.setHeader("Access-Control-Allow-Headers", ALLOWED_HTTP_HEADERS);
response.setHeader("Access-Control-Max-Age", "3600");
HttpServletRequest request = (HttpServletRequest) req;
if (request.getMethod().equals("OPTIONS")) {
try {
response.getWriter().print("OK");
response.getWriter().flush();
} catch (IOException e) {
e.printStackTrace();
}
} else {
chain.doFilter(req, res);
}
}
public void init(FilterConfig filterConfig) {
}
public void destroy() {
}
}
You can share security session between your services by using Redis. Read this documentation. You can also find an example of it from this link.

Categories

Resources