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
]
************************************************************
Related
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);
}
I am trying to call the API in Backend but I have some error that I have not an idea from what is causing by.
The problem started after I config the spring security in the backend.
The call should activate Preflighted requests OPTION
In my backend file, I have
#Configuration
#EnableWebSecurity
public class SpringSecurityConfigurationBasicAuth extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS,"/**").permitAll()
.anyRequest().authenticated()
.and()
// .formLogin().and()
.httpBasic();
}
}
and in the frontend, I have this part of the code.
executeHelloWorldServiceWithPathVariable(name) {
const basicAuthHeaderString = this.createBasicAuthenticationHttpHeader();
const headers = new HttpHeaders({
Authorization: basicAuthHeaderString
});
return this.http.get<HelloWorldBean>(`http://localhost:8080/hello-world/path-variable/${name}`,
{headers});
}
createBasicAuthenticationHttpHeader() {
const username = 'start';
const password = 'end';
const basicAuthHeaderString = 'Basic ' + window.btoa(username + ':' + password);
return basicAuthHeaderString;
}
In the backend, I have already include
#CrossOrigin(origins = "http://localhost:4200")
but still, I am not able to call this API
in the console, I should get something like an OPTION method but in fact, I get those:
General
Request URL: http://localhost:8080/hello-world/path-variable/start
Referrer Policy: no-referrer-when-downgrade
Response Header
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Connection: keep-alive
Content-Length: 0
Date: Tue, 28 Jan 2020 11:11:49 GMT
Expires: 0
Keep-Alive: timeout=60
Pragma: no-cache
WWW-Authenticate: Basic realm="Realm"
WWW-Authenticate: Basic realm="Realm"
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
request head
Accept: application/json, text/plain, /
Accept-Encoding: gzip, deflate, br
Accept-Language: en,cs;q=0.9,en-US;q=0.8
Authorization: Basicc3RhcnQ6ZWVuZA==
Connection: keep-alive
Host: localhost:8080
Origin: http://localhost:4200
Referer: http://localhost:4200/welcome/start
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36
and in console, I see this error
Try to add cors policy in your security configuration:
#Configuration
#EnableWebSecurity
public class SpringSecurityConfigurationBasicAuth extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.cors();
http.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS,"/**").permitAll()
.anyRequest().authenticated()
.and()
// .formLogin().and()
.httpBasic();
}
}
to the class SpringSecurityConfigurationBasicAuth try to add this method
#Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("http://localhost:4200"));
configuration.setAllowedMethods(Arrays.asList("GET","POST"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
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
Got a websocket - see the authToken in the Cookie, in Java Spring how do you validate this authToken? I understand this authToken is passed down from the http layer to the websocket so I'm trying to validate that the websocket is being opened by our app and not by some other source.
Headers for Websocket:
GET ws://localhost:9999/somePath/websocket HTTP/1.1
Host: localhost:9999
Connection: Upgrade
Pragma: no-cache
Cache-Control: no-cache
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36
Upgrade: websocket
Origin: http://localhost
Sec-WebSocket-Version: 13
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Cookie: authToken=elFKMk5TckR0ZUNvdnZySUJxc2ZMdz09OklEZENrRFRySkp0U0ltVFdKU1RIZVE9PQ
Sec-WebSocket-Key: e//VDAjHSRjE810tCbIEyw==
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
Sec-WebSocket-Protocol: v10.stomp, v11.stomp, v12.stomp
I would like to validate that authToken in the HttpHandshakeInterceptor.beforeHandshake
#Configuration
#EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer
registry.addEndpoint(stompEndPoint).addInterceptors(new HttpHandshakeInterceptor()).setAllowedOrigins("*").withSockJS();
public class HttpHandshakeInterceptor implements HandshakeInterceptor
Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map attributes) throws Exception {
if (request instanceof ServletServerHttpRequest) {
ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;
HttpSession session = servletRequest.getServletRequest().getSession();
attributes.put("sessionId", session.getId());
// validate token logic
}
return true;
}
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?