CORS with Spring Boot 2 [duplicate] - java

This question already has an answer here:
CORS Error: “requests are only supported for protocol schemes: http…” etc
(1 answer)
Closed 3 years ago.
I am attempting to connect my angular app to my new Spring Boot 2 controller. I start everything up and I get:
Access to XMLHttpRequest at 'localhost:8093/restapi/setup' from origin 'http://localhost:4200' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https.
Followed by:
ERROR HttpErrorResponse {headers: HttpHeaders, status: 0, statusText: "Unknown Error", url: "localhost:8093/restapi/setup", ok: false, …}
So this is CORS, right? When I hit localhost:8093/restapi/setup from postman, I get a valid response, as you'd expect.
So I do some research and especially I find this: No 'Access-Control-Allow-Origin' header is present on the requested resource—when trying to get data from a REST API
I finally find this article here:
https://chariotsolutions.com/blog/post/angular-2-spring-boot-jwt-cors_part1/
And that leads me to the following code:
#Configuration
public class ManageConfiguration {
private static final Logger LOGGER = LogManager.getLogger(ManageConfiguration.class);
#Bean
public CorsFilter corsFilter() {
LOGGER.debug("Configuring CORS");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("OPTIONS");
config.addAllowedMethod("GET");
config.addAllowedMethod("POST");
config.addAllowedMethod("PUT");
config.addAllowedMethod("DELETE");
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}
So I think this is straightforward and now try again and I get:
Access to XMLHttpRequest at 'localhost:8093/restapi/setup' from origin 'http://localhost:4200' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https.
Followed by:
ERROR HttpErrorResponse {headers: HttpHeaders, status: 0, statusText: "Unknown Error", url: "localhost:8093/restapi/setup", ok: false, …}
So it doesn't appear to make any difference whatsoever.
Checked and it's running on the right port:
2019-02-27 14:23:21.261 INFO 9814 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8093 (http) with context path ''
Made sure it included my CORS bean:
2019-02-27 14:23:19.608 DEBUG 9814 --- [ main] o.s.b.f.s.DefaultListableBeanFactory : Creating shared instance of singleton bean 'corsFilter'
...
o.springframework.web.filter.CorsFilter : Filter 'corsFilter' configured for use
Per How can you debug a CORS request with cURL?, I did the following curl request to see my pre-flight stuff.
$ curl -H "Origin: http://example.com" --verbose http://localhost:8093/restapi/setup
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8093 (#0)
> GET /restapi/setup HTTP/1.1
> Host: localhost:8093
> User-Agent: curl/7.61.0
> Accept: */*
> Origin: http://example.com
>
< HTTP/1.1 200
< Vary: Origin
< Vary: Access-Control-Request-Method
< Vary: Access-Control-Request-Headers
< Access-Control-Allow-Origin: http://example.com
< Access-Control-Allow-Credentials: true
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 1; mode=block
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate
< Pragma: no-cache
< Expires: 0
< X-Frame-Options: DENY
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Wed, 27 Feb 2019 21:38:28 GMT
<
* Connection #0 to host localhost left intact
{"issueType":["bug","epic","subTask","task","story"]}
Been scratching my head for a day about what to try next and can't come up with anything. Suggestions?

i think you're sending an ajax request without http:// protocol prefix in your request URL, try hitting http://localhost:8093/restapi/setup from ajax.

Add this WebSecurityConfigurerAdapter in your code
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
#EnableWebSecurity
#EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class CustomWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable();
}
}
Also add the following WebMvcConfigurer
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
#Configuration
public class WebMvcConfigurerImpl implements WebMvcConfigurer {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
}
At last add this annotation on top of your rest controller class : #CrossOrigin.
#CrossOrigin
public class RestController {
// Your methods
}
If you have a filter, you can add the following attributes to the response, if you don't have, you can use this one.
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Service;
import org.springframework.web.filter.OncePerRequestFilter;
#Service
public class JwtAuthenticationFilter extends OncePerRequestFilter {
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With, remember-me");
response.setHeader("Access-Control-Expose-Headers", "Content-Length, Authorization");
filterChain.doFilter(request, response);
}
}

#Configuration
public class CorsConfig {
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedMethods("GET", "POST", "PUT", "DELETE").allowedOrigins("*")
.allowedHeaders("*");
}
};
}
}
#Configuration
#EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
}
Please check the tutorial here https://spring.io/blog/2015/06/08/cors-support-in-spring-framework

Related

How do I include endpoints with query params when configuring requestMatchers in Spring security 6?

I have the following code...
import com.purepm.admin.services.authentication.AudienceValidator;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.oauth2.core.DelegatingOAuth2TokenValidator;
import org.springframework.security.oauth2.core.OAuth2TokenValidator;
import org.springframework.security.oauth2.jwt.*;
import org.springframework.security.web.SecurityFilterChain;
#EnableWebSecurity
#Configuration
public class SecurityConfig{
#Value("${auth0.audience}")
private String audience;
#Value("${spring.security.oauth2.resourceserver.jwt.issuer-uri}")
private String issuer;
#Bean
JwtDecoder jwtDecoder() {
NimbusJwtDecoder jwtDecoder = (NimbusJwtDecoder)
JwtDecoders.fromOidcIssuerLocation(issuer);
OAuth2TokenValidator<Jwt> audienceValidator = new AudienceValidator(audience);
OAuth2TokenValidator<Jwt> withIssuer = JwtValidators.createDefaultWithIssuer(issuer);
OAuth2TokenValidator<Jwt> withAudience = new DelegatingOAuth2TokenValidator<>(withIssuer, audienceValidator);
jwtDecoder.setJwtValidator(withAudience);
return jwtDecoder;
}
#Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests()
.requestMatchers("/").permitAll()
.requestMatchers("/person").hasAuthority("SCOPE_blahablah")
.anyRequest().authenticated();
return http.build();
}
}
But when I use the following command to run the request curl http://localhost:8080/person -v I see the expected 403...
* Trying 127.0.0.1:8080...
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /person HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.85.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 403
< Set-Cookie: JSESSIONID=EFD9C400D91760FE8FA2119AC2EB382B; Path=/; HttpOnly
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 0
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate
< Pragma: no-cache
< Expires: 0
< X-Frame-Options: DENY
< Content-Length: 0
< Date: Wed, 11 Jan 2023 21:45:16 GMT
<
* Connection #0 to host localhost left intact
This is as expected since I am not providing an Authorization header (Although I would expect a 401).
But when I add the query param like curl http://localhost:8080/person?email=me#me.co it just lets it right through and I get a 200. Is there a way to use the query string to enforce the 403 when there is a query param as well?

Spring Security Requests are 403

I am currently working on an application with spring, and I currently face the problem that all requests I do return the error 403 - Forbidden. It is not only [post,put,patch,delete], but also get. Also, I have csrf already disabled.
Here my SecurityConfig:
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.anonymous().and()
.authorizeRequests()
.antMatchers("/signin").permitAll()
.antMatchers("/signup").permitAll()
.antMatchers("/rss/feed").permitAll()
.antMatchers("/article/{guid}").permitAll()
.anyRequest().authenticated()
.and()
.exceptionHandling()
.authenticationEntryPoint(authenticationEntryPoint).and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
.csrf().disable().cors();
}
And here one of the endpoints which is not working properly:
#PreAuthorize("hasAnyRole('ADMIN', 'PUBLISHER', 'USER')")
#GetMapping("/users/current")
public User getCurrent(#RequestHeader Map<String, String> headers){
String token = headers.get("Authorization");
System.out.println("Current user request");
return userAuthService.getUserByUsername(jwtUtil.getUser(token).getUsername());
}
And yes, I know that csrf().disable() is dangerous, I disabled it for now to see if it is some problem with csrf.
Here my JwtAuthenticationFilter:
#Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
#Autowired
private JwtUtil jwtUtil;
#Autowired
private UserAuthService userAuthService;
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
String header = request.getHeader("Authorization");
if(header == null){
throw new NullPointerException("No headers");
}
if (!header.startsWith("Bearer")) {
throw new JwtTokenMissingException("No JWT token found in the request headers");
}
String token = header.substring(7);
// Optional - verification
jwtUtil.validateToken(token);
UserVo userVo = jwtUtil.getUser(token);
UserDetails userDetails = userAuthService.loadUserByUsername(userVo.getUsername());
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
usernamePasswordAuthenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
if (SecurityContextHolder.getContext().getAuthentication() == null) {
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
}
filterChain.doFilter(request, response);
}
}
Edit: I enabled Security logging and got the following error on Spring console:
2022-04-04 18:22:26.611 DEBUG 9804 --- [nio-8080-exec-2] o.s.s.a.i.a.MethodSecurityInterceptor : Failed to authorize ReflectiveMethodInvocation: public at.brigot.kainblog.pojos.User at.brigot.kainblog.controller.AuthController.getCurrent(java.util.Map); target is of class [at.brigot.kainblog.controller.AuthController] with attributes [[authorize: 'hasAnyRole('ADMIN', 'PUBLISHER', 'USER')', filter: 'null', filterTarget: 'null']]
Also if needed, here the full request info I got from spring:
************************************************************
Request received for GET '/users/current':
org.apache.catalina.connector.RequestFacade#1d49a6ca
servletPath:/users/current
pathInfo:null
headers:
host: localhost:8080
connection: keep-alive
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="98", "Opera GX";v="84"
accept: application/json, text/plain, */*
authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJnb3RwZWQxNyIsInJvbGVzIjpbIkFETUlOIiwiVVNFUiJdLCJpYXQiOjE2NDkwODkyMDcsImV4cCI6MTY0OTA4OTM4N30.b5vg-azO433Ozk8GoiakQC-T2ULdFVsde6MrJhW8XpIhA5k5AtA_Q6i0vuCGATQV8RwteMzBc86CzKmuQ7kuYA
sec-ch-ua-mobile: ?0
user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.109 Safari/537.36 OPR/84.0.4316.52
sec-ch-ua-platform: "Windows"
origin: http://localhost:3000
sec-fetch-site: same-site
sec-fetch-mode: cors
sec-fetch-dest: empty
referer: http://localhost:3000/
accept-encoding: gzip, deflate, br
accept-language: de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7
Security filter chain: [
WebAsyncManagerIntegrationFilter
SecurityContextPersistenceFilter
HeaderWriterFilter
CorsFilter
LogoutFilter
JwtAuthenticationFilter
RequestCacheAwareFilter
SecurityContextHolderAwareRequestFilter
AnonymousAuthenticationFilter
SessionManagementFilter
ExceptionTranslationFilter
FilterSecurityInterceptor
]
************************************************************

NullPointerException when getting username from principal

When I try to get user name on backend
#CrossOrigin(origins = "*")
#RestController
#RequestMapping("/persons")
public class PersonController {
...
#PostMapping
public ResponseEntity<PersonDto> addPerson(#RequestBody PersonDto objectDto, #AuthenticationPrincipal Principal principal){
System.out.println(principal.getName());
I got an error
2021-10-27 23:30:39.309 ERROR 10744 --- [nio-8081-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.NullPointerException] with root cause
I can see that frontent is sending JWT token (don't look at 'accessToken' I added it manually to header).
POST /persons HTTP/1.1
Host: localhost:8081
Connection: keep-alive
Content-Length: 217
sec-ch-ua: "Chromium";v="94", "Google Chrome";v="94", ";Not A Brand";v="99"
accessToken: eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJHaWVuZWsiLCJpYXQiOjE2MzUzNjg1MjQsImV4cCI6MTYzNTQ1NDkyNH0.leuqnc-8fHNBVhTmukruom-RudxicWP3ykkMyMiapwY8bBVCFLwlNssXNK-gyo0RHig9d-dg83-QG9LDqVO9VA
sec-ch-ua-mobile: ?0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36
Content-Type: application/json
Accept: application/json, text/plain, */*
x-access-token: Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJHaWVuZWsiLCJpYXQiOjE2MzUzNjg1MjQsImV4cCI6MTYzNTQ1NDkyNH0.leuqnc-8fHNBVhTmukruom-RudxicWP3ykkMyMiapwY8bBVCFLwlNssXNK-gyo0RHig9d-dg83-QG9LDqVO9VA
sec-ch-ua-platform: "Windows"
Origin: http://localhost:4200
Sec-Fetch-Site: same-site
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: http://localhost:4200/
Accept-Encoding: gzip, deflate, br
Accept-Language: pl-PL,pl;q=0.9,en-US;q=0.8,en;q=0.7
What is the reason that backend does not see it?
Attaching Security Config - please let me know if you need more details
package pl.portal.randkowy.security;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.core.userdetails.UserDetailsService;
#Configuration
#EnableWebSecurity(debug=true)
#EnableGlobalMethodSecurity(
// securedEnabled = true,
// jsr250Enabled = true,
prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
UserDetailsService userDetailsService;
#Autowired
private AuthEntryPointJwt unauthorizedHandler;
#Bean
public AuthTokenFilter authenticationJwtTokenFilter() {
return new AuthTokenFilter();
}
#Override
public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
authenticationManagerBuilder.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable()
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests().antMatchers("/api/auth/**").permitAll()
.antMatchers("/api/test/**").permitAll()
.antMatchers("/persons").permitAll()
.antMatchers("/persons/**").permitAll()
.antMatchers("/preferences/**").permitAll()
.antMatchers("/interests/**").permitAll()
.antMatchers("/secretdata/**").permitAll()
.anyRequest().authenticated();
http.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);
}
}
When I am trying to check this way
#PostMapping
public ResponseEntity<PersonDto> addPerson(#RequestBody PersonDto objectDto, Principal principal){
//zalogowany użytkownik
Object principal2 = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
System.out.println("--------------------------------------*****************");
if (principal2 instanceof UserDetailsImpl) {
String username = ((UserDetailsImpl)principal2).getUsername();
System.out.println(username);
} else {
String username = principal2.toString();
System.out.println(username);
}
System.out.println("--------------------------------------*****************");
I got
--------------------------------------*****************
anonymousUser
--------------------------------------*****************
Why Spring Security does not read this token? It is sended to frontend after login procedure, so it should be fine. Spring should get in in header from this x-access-token option?
EDIT:
I found out during debugging that jwt is null, but why - I can see that request has inside jwt token from frontend?
Debug into your parseJwt(request) to see how your application extracts the token from the request. The practice for the access token is: it's usually in the Authorization header and starts with Bearer
Request headers
Authorization: Bearer access-token
try changing the webSecurityConfig like this
#Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable()
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests().antMatchers("/api/auth/**").permitAll()
.antMatchers("/api/test/**").permitAll()
.antMatchers("/persons/**").permitAll()
.antMatchers("/preferences/**").permitAll()
.antMatchers("/interests/**").permitAll()
.antMatchers("/secretdata/**").permitAll()
.anyRequest().authenticated();
http.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);
}

Why CorsConfigurationSource's is ignored, no Access-Control-Allow-Origin is present?

My goal is to add Access-Control-Allow-Origins in the header.
The Spring Security Reference's clearly said to
Set a POJO as #EnableWebSecurity's bean.
Override a configure(HttpSecurity http) method.
Create a CorsConfigurationSource's bean.
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) {
http
.cors(withDefaults())
.httpBasic(withDefaults());
}
#Bean
protected CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Collections.singletonList("http://localhost:3000"));
configuration.setAllowedMethods(Arrays.asList("GET", "POST"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
#RestController
public class AccountController {
#GetMapping("/ping")
public String getPing() {
return "PONG";
}
}
What I did:
Run a Spring Boot's application with the above configuration
Send a Fetch request to http://localhost:8080/ping from a React client.
The actual result:
The response does not include Access-Control-Allow-Origin header, I think it should be in the OPTIONS request.
The expected result:
A success response.
I am confused... I did a curl and the Access-Control-Allow-Origin is present. I think there is something wrong with the client side handling the HttpBasic.
curl -v -H "Access-Control-Request-Method: POST" -H "Origin: http://localhost:3000" -X OPTIONS http://localhost:8080/ping
* Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
> OPTIONS /ping HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.55.1
> Accept: */*
> Access-Control-Request-Method: POST
> Origin: http://localhost:3000
>
< HTTP/1.1 200
< Vary: Origin
< Vary: Access-Control-Request-Method
< Vary: Access-Control-Request-Headers
< Access-Control-Allow-Origin: http://localhost:3000
< Access-Control-Allow-Methods: GET,POST
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 1; mode=block
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate
< Pragma: no-cache
< Expires: 0
< X-Frame-Options: DENY
< Content-Length: 0
< Date: Fri, 26 Feb 2021 13:37:15 GMT
<
* Connection #0 to host localhost left intact

Unauthorized request, 401, using Spring if I open a modal or I send an ajax request

I have a problem with Keycloak and Spring Boot..
I developed a web-app with some modal and ajax request, sometimes, and I don't know why, I receive status 401 if I click on an href to open a modal, or if I submit a form via ajax...
I don't see any error log server-side, but I checked the request and I have WWW-Authenticate: Bearer realm="Unknown". I think it is weird.
This is the entire request:
1. Request URL:
MyUrl
2. Request Method:
GET
3. Status Code:
401 Unauthorized
4. Remote Address:
MyIp
5. Referrer Policy:
no-referrer-when-downgrade
Response Headers
1. Cache-Control:
no-cache, no-store, max-age=0, must-revalidate
2. Connection:
Keep-Alive
3. Content-Language:
it
4. Content-Length:
302
5. Content-Type:
text/html;charset=ISO-8859-1
6. Date:
Tue, 08 May 2018 07:32:59 GMT
7. Expires:
0
8. Keep-Alive:
timeout=5, max=99
9. Pragma:
no-cache
10. Server:
Apache/2.4.18 (Ubuntu)
11. WWW-Authenticate:
Bearer realm="Unknown"
12. X-Content-Type-Options:
nosniff
13. X-Frame-Options:
DENY
14. X-XSS-Protection:
1; mode=block
Request Header
1. Accept:
text/html, */*; q=0.01
2. Accept-Encoding:
gzip, deflate
3. Accept-Language:
it-IT,it;q=0.9,en-US;q=0.8,en;q=0.7
4. Connection:
keep-alive
5. Cookie:
JSESSIONID=1F97669EEE8A347CAE145C8D25146512.Tomcat1; _ga=GA1.2.230482432.1486023475
6. DNT:
1
7. Host:
MyHost
8. Referer:
MyUrl
9. User-Agent:
Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36
10. X-Requested-With:
XMLHttpRequest
Query String Parameters
.....
This is my config about keycloak and Spring:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled=true)
#KeycloakConfiguration
public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
#Autowired
public KeycloakClientRequestFactory keycloakClientRequestFactory;
public SecurityConfig() {
SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http
.httpBasic()
.disable();
http
.authorizeRequests()
.anyRequest().hasAuthority("1086")
.and()
.logout()
.logoutUrl("/logout")
.logoutRequestMatcher(new AntPathRequestMatcher("/logout", "GET"))
.permitAll()
.logoutSuccessUrl(URL)
.invalidateHttpSession(true);
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
auth.authenticationProvider(keycloakAuthenticationProvider());
}
#Bean
#Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
}
#Bean
#Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public KeycloakRestTemplate keycloakRestTemplate() {
return new KeycloakRestTemplate(keycloakClientRequestFactory);
}
#Bean
public KeycloakConfigResolver keycloakConfigResolver() {
return new KeycloakSpringBootConfigResolver();
}
#Bean
public FilterRegistrationBean keycloakAuthenticationProcessingFilterRegistrationBean(KeycloakAuthenticationProcessingFilter filter) {
FilterRegistrationBean registrationBean = new FilterRegistrationBean(filter);
registrationBean.setEnabled(false);
return registrationBean;
}
#Bean
public FilterRegistrationBean keycloakPreAuthActionsFilterRegistrationBean(KeycloakPreAuthActionsFilter filter) {
FilterRegistrationBean registrationBean = new FilterRegistrationBean(filter);
registrationBean.setEnabled(false);
return registrationBean;
}
#Bean
public FilterRegistrationBean keycloakAuthenticatedActionsFilterBean(KeycloakAuthenticatedActionsFilter filter) {
FilterRegistrationBean registrationBean = new FilterRegistrationBean(filter);
registrationBean.setEnabled(false);
return registrationBean;
}
#Bean
public FilterRegistrationBean keycloakSecurityContextRequestFilterBean( KeycloakSecurityContextRequestFilter filter) {
FilterRegistrationBean registrationBean = new FilterRegistrationBean(filter);
registrationBean.setEnabled(false);
return registrationBean;
}
#Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers("/resources/**", "/static/**", "/css/**", "/js/**", "/images/**", "/webjars/**");
}
I can continue with the request, if I reload the page, and then I re-click on the href... But why I have to reload the page? and why sometimes?

Categories