I am getting a "Circular View Path Error" but I don't know why. If I am understanding it correctly this error occurs when you are stuck in a infinite loop. But I don't see an infinite Loop in my code. I googled the error, and tested every solution I found, but nothing worked.
MyUserDetails:
package de.gabriel.vertretungsplan.models;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
public class MyUserDetails implements UserDetails {
private String userName;
private String password;
private boolean active;
private List<GrantedAuthority> authorities;
public MyUserDetails(User user) {
this.userName = user.getUserName();
this.password = user.getPassword();
this.active = user.isActive();
this.authorities = Arrays.stream(user.getRoles().split(","))
.map(SimpleGrantedAuthority::new)
.collect(Collectors.toList());
System.out.println(userName);
System.out.println(password);
System.out.println(active);
System.out.println(authorities);
}
#Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return authorities;
}
#Override
public String getPassword() {
return password;
}
#Override
public String getUsername() {
return userName;
}
#Override
public boolean isAccountNonExpired() {
return true;
}
#Override
public boolean isAccountNonLocked() {
return true;
}
#Override
public boolean isCredentialsNonExpired() {
return true;
}
#Override
public boolean isEnabled() {
return active;
}
}
User:
package de.gabriel.vertretungsplan.models;
import javax.persistence.*;
#Entity
#Table(name = "lehrer", schema = "public")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String userName;
private String password;
private boolean active;
private String roles;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public boolean isActive() {
return active;
}
public void setActive(boolean active) {
this.active = active;
}
public String getRoles() {
return roles;
}
public void setRoles(String roles) {
this.roles = roles;
}
}
Rest Controller/ HomeResource:
package de.gabriel.vertretungsplan;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class HomeResource {
#GetMapping("/")
public String home(){
return ("<h1>Hier wird der Vertretungsplan einsehbar sein</h1>");
}
#GetMapping("/lehrer")
public String lehrer(){
return ("<h1>Hier wird das Formular einsehbar sein</h1>");
}
#GetMapping("/admin")
public String admin(){
return ("<h1>Hier wird die Admin Übersicht einsehbar sein</h1>");
}
}
MyUserDetailsService:
package de.gabriel.vertretungsplan;
import de.gabriel.vertretungsplan.models.MyUserDetails;
import de.gabriel.vertretungsplan.models.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import java.util.Optional;
#Service
public class MyUserDetailsService implements UserDetailsService {
#Autowired
UserRepository userRepository;
#Override
public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
Optional<User> user = userRepository.findByUserName(userName);
user.orElseThrow(() -> new UsernameNotFoundException("Username " + userName + " not found!"));
return user.map(MyUserDetails::new).get();
}
}
User Repository:
package de.gabriel.vertretungsplan;
import de.gabriel.vertretungsplan.models.User;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.Optional;
public interface UserRepository extends JpaRepository<User, Integer> {
Optional<User> findByUserName(String userName);
}
Security Configuration:
package de.gabriel.vertretungsplan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
UserDetailsService userDetailsService;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(getPasswordEncoder());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/admin").hasRole("ADMIN")
.antMatchers("/lehrer").hasAnyRole("ADMIN","LEHRER")
.antMatchers("/").permitAll()
.and().formLogin();
}
#Bean
public PasswordEncoder getPasswordEncoder(){
return new BCryptPasswordEncoder();
}
}
And finally, this is my main:
package de.gabriel.vertretungsplan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
#SpringBootApplication
#EnableJpaRepositories(basePackageClasses = UserRepository.class)
public class VertretungsplanApplication {
public static void main(String[] args) {
SpringApplication.run(VertretungsplanApplication.class, args);
}
}
I don't think, the errors origin can be in the database, but if it is, here is the contents of the "lehrer" table in the database "vertretungsplan":
Here is the error log:
2022-04-17 00:50:57.562 ERROR 14740 --- [nio-8080-exec-6] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] threw exception
javax.servlet.ServletException: Circular view path [error]: would dispatch back to the current handler URL [/error] again. Check your ViewResolver setup! (Hint: This may be the result of an unspecified view, due to default view name generation.)
at org.springframework.web.servlet.view.InternalResourceView.prepareForRendering(InternalResourceView.java:210) ~[spring-webmvc-5.3.18.jar:5.3.18]
at org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(InternalResourceView.java:148) ~[spring-webmvc-5.3.18.jar:5.3.18]
at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:316) ~[spring-webmvc-5.3.18.jar:5.3.18]
at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1401) ~[spring-webmvc-5.3.18.jar:5.3.18]
at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1145) ~[spring-webmvc-5.3.18.jar:5.3.18]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1084) ~[spring-webmvc-5.3.18.jar:5.3.18]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963) ~[spring-webmvc-5.3.18.jar:5.3.18]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.18.jar:5.3.18]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) ~[spring-webmvc-5.3.18.jar:5.3.18]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:655) ~[tomcat-embed-core-9.0.60.jar:4.0.FR]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.18.jar:5.3.18]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:764) ~[tomcat-embed-core-9.0.60.jar:4.0.FR]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
at org.springframework.boot.web.servlet.filter.ErrorPageSecurityFilter.doFilter(ErrorPageSecurityFilter.java:80) ~[spring-boot-2.6.6.jar:2.6.6]
at org.springframework.boot.web.servlet.filter.ErrorPageSecurityFilter.doFilter(ErrorPageSecurityFilter.java:70) ~[spring-boot-2.6.6.jar:2.6.6]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:327) ~[spring-security-web-5.6.2.jar:5.6.2]
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:106) ~[spring-security-web-5.6.2.jar:5.6.2]
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:81) ~[spring-security-web-5.6.2.jar:5.6.2]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.6.2.jar:5.6.2]
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:122) ~[spring-security-web-5.6.2.jar:5.6.2]
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:116) ~[spring-security-web-5.6.2.jar:5.6.2]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.6.2.jar:5.6.2]
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:87) ~[spring-security-web-5.6.2.jar:5.6.2]
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:81) ~[spring-security-web-5.6.2.jar:5.6.2]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.6.2.jar:5.6.2]
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:109) ~[spring-security-web-5.6.2.jar:5.6.2]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.6.2.jar:5.6.2]
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:149) ~[spring-security-web-5.6.2.jar:5.6.2]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.6.2.jar:5.6.2]
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63) ~[spring-security-web-5.6.2.jar:5.6.2]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.6.2.jar:5.6.2]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:102) ~[spring-web-5.3.18.jar:5.3.18]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.6.2.jar:5.6.2]
at org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter.doFilter(DefaultLoginPageGeneratingFilter.java:237) ~[spring-security-web-5.6.2.jar:5.6.2]
at org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter.doFilter(DefaultLoginPageGeneratingFilter.java:223) ~[spring-security-web-5.6.2.jar:5.6.2]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.6.2.jar:5.6.2]
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:219) ~[spring-security-web-5.6.2.jar:5.6.2]
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:213) ~[spring-security-web-5.6.2.jar:5.6.2]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.6.2.jar:5.6.2]
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:103) ~[spring-security-web-5.6.2.jar:5.6.2]
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:89) ~[spring-security-web-5.6.2.jar:5.6.2]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.6.2.jar:5.6.2]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:102) ~[spring-web-5.3.18.jar:5.3.18]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.6.2.jar:5.6.2]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:102) ~[spring-web-5.3.18.jar:5.3.18]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.6.2.jar:5.6.2]
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:110) ~[spring-security-web-5.6.2.jar:5.6.2]
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:80) ~[spring-security-web-5.6.2.jar:5.6.2]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.6.2.jar:5.6.2]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:102) ~[spring-web-5.3.18.jar:5.3.18]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.6.2.jar:5.6.2]
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:211) ~[spring-security-web-5.6.2.jar:5.6.2]
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:183) ~[spring-security-web-5.6.2.jar:5.6.2]
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:354) ~[spring-web-5.3.18.jar:5.3.18]
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:267) ~[spring-web-5.3.18.jar:5.3.18]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.18.jar:5.3.18]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.18.jar:5.3.18]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:102) ~[spring-web-5.3.18.jar:5.3.18]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:102) ~[spring-web-5.3.18.jar:5.3.18]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:711) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:461) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:385) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:313) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
at org.apache.catalina.core.StandardHostValve.custom(StandardHostValve.java:403) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
at org.apache.catalina.core.StandardHostValve.status(StandardHostValve.java:249) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:360) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:399) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:889) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1743) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
at java.base/java.lang.Thread.run(Thread.java:833) ~[na:na]
Here are the debug logs(they are too long, so I posted the longs of when the error happend):
2022-04-17 00:58:48.395 DEBUG 12924 --- [nio-8080-exec-4] o.s.security.web.FilterChainProxy : Securing POST /login
2022-04-17 00:58:48.395 DEBUG 12924 --- [nio-8080-exec-4] s.s.w.c.SecurityContextPersistenceFilter : Set SecurityContextHolder to empty SecurityContext
Hibernate:
select
user0_.id as id1_0_,
user0_.active as active2_0_,
user0_.password as password3_0_,
user0_.roles as roles4_0_,
user0_.user_name as user_nam5_0_
from
public.lehrer user0_
where
user0_.user_name=?
admin
$2a$12$E8STVE26N/QpoL90VfoOAuFRnYvbfzHKlbGRe.KVOMYCqKtDKNK2G
true
[ADMIN]
2022-04-17 00:58:48.796 DEBUG 12924 --- [nio-8080-exec-4] o.s.s.a.dao.DaoAuthenticationProvider : Authenticated user
2022-04-17 00:58:48.797 DEBUG 12924 --- [nio-8080-exec-4] .s.ChangeSessionIdAuthenticationStrategy : Changed session id from CD2D5F40C901F8A7CF32826E28A596C9
2022-04-17 00:58:48.797 DEBUG 12924 --- [nio-8080-exec-4] o.s.s.w.csrf.CsrfAuthenticationStrategy : Replaced CSRF Token
2022-04-17 00:58:48.798 DEBUG 12924 --- [nio-8080-exec-4] w.a.UsernamePasswordAuthenticationFilter : Set SecurityContextHolder to UsernamePasswordAuthenticationToken [Principal=de.gabriel.vertretungsplan.models.MyUserDetails#69c46690, Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=CD2D5F40C901F8A7CF32826E28A596C9], Granted Authorities=[ADMIN]]
2022-04-17 00:58:48.798 DEBUG 12924 --- [nio-8080-exec-4] o.s.s.web.DefaultRedirectStrategy : Redirecting to http://localhost:8080/admin
2022-04-17 00:58:48.798 DEBUG 12924 --- [nio-8080-exec-4] w.c.HttpSessionSecurityContextRepository : Stored SecurityContextImpl [Authentication=UsernamePasswordAuthenticationToken [Principal=de.gabriel.vertretungsplan.models.MyUserDetails#69c46690, Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=CD2D5F40C901F8A7CF32826E28A596C9], Granted Authorities=[ADMIN]]] to HttpSession [org.apache.catalina.session.StandardSessionFacade#35a28abb]
2022-04-17 00:58:48.798 DEBUG 12924 --- [nio-8080-exec-4] w.c.HttpSessionSecurityContextRepository : Stored SecurityContextImpl [Authentication=UsernamePasswordAuthenticationToken [Principal=de.gabriel.vertretungsplan.models.MyUserDetails#69c46690, Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=CD2D5F40C901F8A7CF32826E28A596C9], Granted Authorities=[ADMIN]]] to HttpSession [org.apache.catalina.session.StandardSessionFacade#35a28abb]
2022-04-17 00:58:48.798 DEBUG 12924 --- [nio-8080-exec-4] s.s.w.c.SecurityContextPersistenceFilter : Cleared SecurityContextHolder to complete request
2022-04-17 00:58:48.801 INFO 12924 --- [nio-8080-exec-6] Spring Security Debugger :
************************************************************
Request received for GET '/admin':
org.apache.catalina.connector.RequestFacade#328dbcd1
servletPath:/admin
pathInfo:null
headers:
host: localhost:8080
connection: keep-alive
cache-control: max-age=0
upgrade-insecure-requests: 1
user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36
accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
sec-fetch-site: same-origin
sec-fetch-mode: navigate
sec-fetch-user: ?1
sec-fetch-dest: document
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="100", "Google Chrome";v="100"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
referer: http://localhost:8080/login
accept-encoding: gzip, deflate, br
accept-language: de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7
cookie: Webstorm-bca5ba46=692b9f6e-b03a-4cb4-8435-ea3fef371fc4; JSESSIONID=A90C1A49C3CF4D7943EE0ABBD989B1D4
Security filter chain: [
WebAsyncManagerIntegrationFilter
SecurityContextPersistenceFilter
HeaderWriterFilter
CsrfFilter
LogoutFilter
UsernamePasswordAuthenticationFilter
DefaultLoginPageGeneratingFilter
DefaultLogoutPageGeneratingFilter
RequestCacheAwareFilter
SecurityContextHolderAwareRequestFilter
AnonymousAuthenticationFilter
SessionManagementFilter
ExceptionTranslationFilter
FilterSecurityInterceptor
]
************************************************************
2022-04-17 00:58:48.802 DEBUG 12924 --- [nio-8080-exec-6] o.s.security.web.FilterChainProxy : Securing GET /admin
2022-04-17 00:58:48.802 DEBUG 12924 --- [nio-8080-exec-6] w.c.HttpSessionSecurityContextRepository : Retrieved SecurityContextImpl [Authentication=UsernamePasswordAuthenticationToken [Principal=de.gabriel.vertretungsplan.models.MyUserDetails#69c46690, Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=CD2D5F40C901F8A7CF32826E28A596C9], Granted Authorities=[ADMIN]]]
2022-04-17 00:58:48.802 DEBUG 12924 --- [nio-8080-exec-6] s.s.w.c.SecurityContextPersistenceFilter : Set SecurityContextHolder to SecurityContextImpl [Authentication=UsernamePasswordAuthenticationToken [Principal=de.gabriel.vertretungsplan.models.MyUserDetails#69c46690, Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=CD2D5F40C901F8A7CF32826E28A596C9], Granted Authorities=[ADMIN]]]
2022-04-17 00:58:48.802 DEBUG 12924 --- [nio-8080-exec-6] o.s.s.w.s.HttpSessionRequestCache : Loaded matching saved request http://localhost:8080/admin
2022-04-17 00:58:48.803 DEBUG 12924 --- [nio-8080-exec-6] o.s.s.w.a.i.FilterSecurityInterceptor : Failed to authorize filter invocation [GET /admin] with attributes [hasRole('ROLE_ADMIN')]
2022-04-17 00:58:48.803 DEBUG 12924 --- [nio-8080-exec-6] o.s.s.w.access.AccessDeniedHandlerImpl : Responding with 403 status code
2022-04-17 00:58:48.803 DEBUG 12924 --- [nio-8080-exec-6] s.s.w.c.SecurityContextPersistenceFilter : Cleared SecurityContextHolder to complete request
2022-04-17 00:58:48.805 INFO 12924 --- [nio-8080-exec-6] Spring Security Debugger :
************************************************************
Request received for GET '/error':
org.apache.catalina.core.ApplicationHttpRequest#1f38c9b6
servletPath:/error
pathInfo:null
headers:
host: localhost:8080
connection: keep-alive
cache-control: max-age=0
upgrade-insecure-requests: 1
user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36
accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
sec-fetch-site: same-origin
sec-fetch-mode: navigate
sec-fetch-user: ?1
sec-fetch-dest: document
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="100", "Google Chrome";v="100"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
referer: http://localhost:8080/login
accept-encoding: gzip, deflate, br
accept-language: de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7
cookie: Webstorm-bca5ba46=692b9f6e-b03a-4cb4-8435-ea3fef371fc4; JSESSIONID=A90C1A49C3CF4D7943EE0ABBD989B1D4
Security filter chain: [
WebAsyncManagerIntegrationFilter
SecurityContextPersistenceFilter
HeaderWriterFilter
CsrfFilter
LogoutFilter
UsernamePasswordAuthenticationFilter
DefaultLoginPageGeneratingFilter
DefaultLogoutPageGeneratingFilter
RequestCacheAwareFilter
SecurityContextHolderAwareRequestFilter
AnonymousAuthenticationFilter
SessionManagementFilter
ExceptionTranslationFilter
FilterSecurityInterceptor
]
************************************************************
You get this error, because you did not fully configure Spring MVC, namely error handling part (and probably others).
Chain of events is as follows:
Call API and get 403 forbidden resource
2022-04-17 00:58:48.803 DEBUG 12924 --- [nio-8080-exec-6] o.s.s.w.a.i.FilterSecurityInterceptor : Failed to authorize filter invocation [GET /admin] with attributes [hasRole('ROLE_ADMIN')] 2022-04-17 00:58:48.803 DEBUG 12924 --- [nio-8080-exec-6] o.s.s.w.access.AccessDeniedHandlerImpl : Responding with 403 status code
Spring redirects to /error view:
Request received for GET '/error': org.apache.catalina.core.ApplicationHttpRequest#1f38c9b6 servletPath:/error
Here something happens (it was not found, or something is missing), it leads to another error -> and here is when exception happens:
javax.servlet.ServletException: Circular view path [error]: would dispatch back to the current handler URL [/error] again. Check your ViewResolver setup! (Hint: This may be the result of an unspecified view, due to default view name generation.)
Solution:
Try to search by "springboot mvc set up white lable error page".
And also check why you get 403 status in the first place, as according to logs, you logged in as admin user. Please, read about spring security adding ROLE_ prefix. Most probably, in the DB it has to be ROLE_ADMIN and in the code hasRole('ADMIN')
Hope, it helped
Related
After successful basic authentication (login/password in body) when I access to an other secured controller's method I have a 401 error.
I'm not sure but it seems the security context is not set.
Do you have an idea or a line of research?
Use case with swagger
call http://localhost:8080/api/v1/auth/login as admin => success and SecurityContextHolder.getContext() has an authentication as UsernamePasswordAuthenticationToken
call http://localhost:8080/api/v1/auth/me => success. authentication is always UsernamePasswordAuthenticationToken and the user admin is returned
call http://localhost:8080/api/v1/distributors/isauthenticated => failed and return a 401 http status.
The step 3 logs
2023-01-10 10:16:48,523 [http-nio-8080-exec-1] DEBUG o.s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to fr.gregoire.passpro.backend.controller.DistributorsController#test()
2023-01-10 10:16:48,524 [http-nio-8080-exec-1] INFO Spring Security Debugger :
************************************************************
Request received for GET '/api/v1/distributors/isauthenticated':
org.apache.catalina.connector.RequestFacade#5d0e637c
servletPath:/api/v1/distributors/isauthenticated
pathInfo:null
headers:
host: localhost:8080
user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:108.0) Gecko/20100101 Firefox/108.0
accept: */*
accept-language: fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3
accept-encoding: gzip, deflate, br
referer: http://localhost:8080/swagger-ui/index.html
connection: keep-alive
cookie: JSESSIONID=F6F38EADC8BA2ADF82A519C33507D25F
sec-fetch-dest: empty
sec-fetch-mode: cors
sec-fetch-site: same-origin
Security filter chain: no match
************************************************************
2023-01-10 10:16:48,524 [http-nio-8080-exec-1] DEBUG o.s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to fr.gregoire.passpro.backend.controller.DistributorsController#test()
2023-01-10 10:16:48,524 [http-nio-8080-exec-1] DEBUG org.springframework.web.servlet.DispatcherServlet : GET "/api/v1/distributors/isauthenticated", parameters={}
2023-01-10 10:16:48,524 [http-nio-8080-exec-1] DEBUG o.s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to fr.gregoire.passpro.backend.controller.DistributorsController#test()
2023-01-10 10:16:48,524 [http-nio-8080-exec-1] DEBUG o.s.s.a.m.AuthorizationManagerBeforeMethodInterceptor : Authorizing method invocation ReflectiveMethodInvocation: public void fr.gregoire.passpro.backend.controller.DistributorsController.test() throws java.lang.Exception; target is of class [fr.gregoire.passpro.backend.controller.DistributorsController]
2023-01-10 10:16:48,525 [http-nio-8080-exec-1] DEBUG o.s.w.s.m.m.a.ExceptionHandlerExceptionResolver : Using #ExceptionHandler fr.gregoire.passpro.backend.resterror.RestExceptionHandler#handleAuthenticationException(AuthenticationException)
2023-01-10 10:16:48,526 [http-nio-8080-exec-1] DEBUG o.s.w.s.m.m.annotation.HttpEntityMethodProcessor : Using 'application/json', given [*/*] and supported [application/json, application/*+json]
2023-01-10 10:16:48,526 [http-nio-8080-exec-1] DEBUG o.s.w.s.m.m.annotation.HttpEntityMethodProcessor : Writing [fr.gregoire.passpro.backend.resterror.RestErrors#55eb7689]
2023-01-10 10:16:48,527 [http-nio-8080-exec-1] DEBUG o.s.w.s.m.m.a.ExceptionHandlerExceptionResolver : Resolved [org.springframework.security.authentication.AuthenticationCredentialsNotFoundException: An Authentication object was not found in the SecurityContext]
2023-01-10 10:16:48,528 [http-nio-8080-exec-1] DEBUG org.springframework.web.servlet.DispatcherServlet : Completed 401 UNAUTHORIZED
Quick info
spring boot 3
spring security 6
Code
package fr.gregoire.passpro.backend.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.HttpStatusEntryPoint;
import org.springframework.security.web.context.DelegatingSecurityContextRepository;
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
import org.springframework.security.web.context.RequestAttributeSecurityContextRepository;
import org.springframework.security.web.context.SecurityContextRepository;
import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
#Configuration
#EnableWebSecurity(debug = true)
#EnableMethodSecurity(securedEnabled = true)
public class SecurityConfig {
#Autowired
UserDetailsService userDetailsService;
#Bean
public SecurityContextRepository securityContextRepository() {
return new HttpSessionSecurityContextRepository();
}
#Bean
public AuthenticationManager authenticationManager(UserDetailsService userDetailsService) throws Exception {
return new ProviderManager(daoAuthenticationProvider());
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Bean
public DaoAuthenticationProvider daoAuthenticationProvider() {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setUserDetailsService(userDetailsService);
provider.setPasswordEncoder(passwordEncoder());
return provider;
}
#Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
HttpSessionRequestCache requestCache = new HttpSessionRequestCache();
requestCache.setMatchingRequestParameterName("continue");
// #formatter:off
http
.headers().frameOptions().disable().and()
.cors().and()
.csrf().disable()
.formLogin().disable()
.exceptionHandling().authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED)).and()
.securityMatcher("/api/*/auth/**")
.authorizeHttpRequests(authz -> authz.requestMatchers("/api/*/auth/**").permitAll()
.requestMatchers("/api/v1/auth/me").permitAll()
.requestMatchers("/api/*/public/**").permitAll()
.requestMatchers("/api/*/catalogs/*/documents/*/file").permitAll()
.requestMatchers(req -> req.getRequestURI().contains("mail-images")).permitAll()
.requestMatchers(req -> req.getRequestURI().contains("api-docs")).permitAll()
.requestMatchers(req -> req.getRequestURI().contains("swagger-ui")).permitAll()
.requestMatchers(req -> req.getRequestURI().contains("h2-console")).permitAll()
.anyRequest().authenticated())
.authenticationProvider(daoAuthenticationProvider())
.securityContext((securityContext) -> securityContext.requireExplicitSave(false)) // Spring secu 5.8
.securityContext((securityContext) -> securityContext.securityContextRepository(new DelegatingSecurityContextRepository(
new RequestAttributeSecurityContextRepository(),
securityContextRepository()
)))
;
// #formatter:on
return http.build();
}
}
package fr.gregoire.passpro.backend.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.session.SessionAuthenticationException;
import org.springframework.security.web.context.SecurityContextRepository;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import fr.gregoire.passpro.backend.dto.LoginDto;
import fr.gregoire.passpro.backend.dto.UserDto;
import fr.gregoire.passpro.backend.exception.NotFoundException;
import fr.gregoire.passpro.backend.mapper.UserDtoMapper;
import fr.gregoire.passpro.backend.model.UserEntity;
import fr.gregoire.passpro.backend.service.UserService;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
#Validated
#RestController
#RequestMapping(path = "/api/v1/auth", produces = MediaType.APPLICATION_JSON_VALUE)
public class AuthenticationController {
#Autowired
private SecurityContextRepository securityContextRepository;
#Autowired
private AuthenticationManager authenticationManager;
#Autowired
private UserService userService;
#Autowired
private UserDtoMapper userDtoMapper;
#PostMapping("/login")
public ResponseEntity<UserDto> login(#NotNull #Valid #RequestBody LoginDto loginDto, HttpServletRequest request, HttpServletResponse response) {
final Authentication authentication = this.authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(loginDto.getLogin(), loginDto.getPassword()));
SecurityContextHolder.getContext()
.setAuthentication(authentication);
securityContextRepository.saveContext(SecurityContextHolder.getContext(), request, response);
return ResponseEntity.ok(this.userDtoMapper.modelToDto((UserEntity) authentication.getPrincipal()));
}
#PostMapping("/logout")
#ResponseStatus(HttpStatus.NO_CONTENT)
public void logout() {
SecurityContextHolder.clearContext();
}
#GetMapping("/me")
public ResponseEntity<UserDto> getAuthenticatedUser() throws NotFoundException {
Authentication authentication = SecurityContextHolder.getContext()
.getAuthentication();
if (null == authentication || !authentication.isAuthenticated() || !(authentication.getPrincipal() instanceof UserEntity)) {
throw new SessionAuthenticationException("UNAUTHORIZED");
}
return ResponseEntity.ok(this.userDtoMapper.modelToDto(this.userService.findById(((UserEntity) authentication.getPrincipal()).getId())));
}
}
#Validated
#RestController
#RequestMapping(path = "/api/v1/distributors", produces = MediaType.APPLICATION_JSON_VALUE)
public class DistributorsController {
#GetMapping("/isauthenticated")
#Secured(RoleEnumConstants.ROLE_ADMIN)
public void test() throws Exception {
Authentication authentication = SecurityContextHolder.getContext()
.getAuthentication();
System.out.println(authentication.getClass()
.getCanonicalName());
System.out.println(authentication.getCredentials());
System.out.println(authentication.isAuthenticated());
System.out.println(authentication.getDetails());
System.out.println(authentication.getAuthorities());
}
}
Thanks for your help and have a nice day,
Nicolas
Here is the full stacktrace AuthenticationCredentialsNotFoundException thrown at step 3 (when I tried to access to http://localhost:8080/api/v1/distributors/isauthenticated as admin)
org.springframework.security.authentication.AuthenticationCredentialsNotFoundException: An Authentication object was not found in the SecurityContext
at org.springframework.security.authorization.method.AuthorizationManagerBeforeMethodInterceptor.lambda$getAuthentication$3(AuthorizationManagerBeforeMethodInterceptor.java:266)
at org.springframework.security.authorization.AuthorityAuthorizationManager.check(AuthorityAuthorizationManager.java:142)
at org.springframework.security.authorization.method.SecuredAuthorizationManager.check(SecuredAuthorizationManager.java:55)
at org.springframework.security.authorization.method.SecuredAuthorizationManager.check(SecuredAuthorizationManager.java:40)
at org.springframework.security.config.annotation.method.configuration.DeferringObservationAuthorizationManager.check(DeferringObservationAuthorizationManager.java:47)
at org.springframework.security.authorization.method.AuthorizationManagerBeforeMethodInterceptor.attemptAuthorization(AuthorizationManagerBeforeMethodInterceptor.java:252)
at org.springframework.security.authorization.method.AuthorizationManagerBeforeMethodInterceptor.invoke(AuthorizationManagerBeforeMethodInterceptor.java:198)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:752)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:703)
at fr.gregoire.passpro.backend.controller.DistributorsController$$SpringCGLIB$$0.test(<generated>)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:207)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:152)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:884)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:797)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1080)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:973)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1010)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:902)
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:705)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:884)
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:814)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:223)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158)
at fr.gregoire.passpro.backend.config.JwtAuthFilter.doFilterInternal(JwtAuthFilter.java:36)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158)
at org.springframework.web.servlet.resource.ResourceUrlEncodingFilter.doFilter(ResourceUrlEncodingFilter.java:66)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:219)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:191)
at org.springframework.security.web.debug.DebugFilter.invokeWithWrappedRequest(DebugFilter.java:90)
at org.springframework.security.web.debug.DebugFilter.doFilter(DebugFilter.java:78)
at org.springframework.security.web.debug.DebugFilter.doFilter(DebugFilter.java:67)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:351)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:267)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:177)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:119)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:400)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:859)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1734)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.base/java.lang.Thread.run(Thread.java:833)
2023-01-10 11:35:33,537 [http-nio-8080-exec-2] DEBUG o.s.w.s.m.m.annotation.HttpEntityMethodProcessor : Using 'application/json', given [*/*] and supported [application/json, application/*+json]
2023-01-10 11:35:33,537 [http-nio-8080-exec-2] DEBUG o.s.w.s.m.m.annotation.HttpEntityMethodProcessor : Writing [fr.gregoire.passpro.backend.resterror.RestErrors#31570bd6]
2023-01-10 11:35:33,538 [http-nio-8080-exec-2] DEBUG o.s.w.s.m.m.a.ExceptionHandlerExceptionResolver : Resolved [org.springframework.security.authentication.AuthenticationCredentialsNotFoundException: An Authentication object was not found in the SecurityContext]
2023-01-10 11:35:33,538 [http-nio-8080-exec-2] DEBUG org.springframework.web.servlet.DispatcherServlet : Completed 401 UNAUTHORIZED
I'm trying to restrict access to an endpoint based on roles. I searched here on stackoverflow for a solution and tried a few but was not successful in solving my problem. I tried to make the restriction both in the global configuration (WebSecurityConfig) and also with PreAuthorize Annotation, both returned 403 when called. My test user has the SYS_ADMIN role, I have already validated this flow and it actually has the role. Below are my sources.
Global WebSecurityConfig
#Configuration
#EnableWebSecurity
#EnableAutoConfiguration
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
#Autowired
private UserDetailsService jwtUserDetailsService;
#Autowired
private JwtRequestFilter jwtRequestFilter;
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(jwtUserDetailsService).passwordEncoder(passwordEncoder());
}
#Override
#Bean
protected AuthenticationManager authenticationManager() throws Exception {
return super.authenticationManager();
}
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.headers().frameOptions().disable();
httpSecurity.cors().and()
.csrf().disable()
.authorizeRequests()
.antMatchers("/spring-security-rest/**").permitAll().and()
.authorizeRequests()
.antMatchers(HttpMethod.POST, "/api/authentication/**").permitAll()
.antMatchers(HttpMethod.POST, "/api/persons/**").hasRole("SYS_ADMIN")
.antMatchers(HttpMethod.GET, "/api/roles/**").permitAll()
.anyRequest().authenticated().and()
.headers().frameOptions().sameOrigin().and()
.exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint).and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
httpSecurity.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
}
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().mvcMatchers(HttpMethod.OPTIONS, "/**");
web.ignoring().mvcMatchers("/swagger-ui.html/**", "/configuration/**", "/swagger-resources/**", "/v2/api-docs",
"/webjars/**");
}
#Bean
public PasswordEncoder passwordEncoder() {
return NoOpPasswordEncoder.getInstance();
}
#Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("*"));
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
Person Controller
package br.com.aquamain.backend.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.annotation.Secured;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import br.com.aquamain.backend.exception.InvalidPersonException;
import br.com.aquamain.backend.model.CustomPage;
import br.com.aquamain.backend.model.Person;
import br.com.aquamain.backend.service.PersonService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
#RestController
#RequestMapping("/api/persons")
#Api(tags = "Persons")
public class PersonController {
#Autowired
private PersonService personService;
...
#PostMapping(path = "new", consumes = "application/json")
#ApiOperation(value = "Create a new person.")
public ResponseEntity<?> save(#RequestBody Person person) {
try {
CustomPage<Person> persons = this.personService.save(person);
return new ResponseEntity<CustomPage<Person>>(persons, HttpStatus.CREATED);
} catch (InvalidPersonException error) {
return new ResponseEntity<String>(error.getMessage(), HttpStatus.BAD_REQUEST);
}
}
...
}
Role Model
package br.com.aquamain.backend.model;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
#Entity
#JsonIgnoreProperties({ "hibernateLazyInitializer", "handler" })
#Table(name = "AQUARIUM_MAINTANCE_MONITOR_ROLE")
public class Role {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "ID_ROLE", nullable = false, precision = 9, scale = 0)
private Integer id;
#JsonIgnoreProperties(value = {"roles"})
#ManyToMany(fetch = FetchType.LAZY, mappedBy = "roles")
#JsonInclude(Include.NON_NULL)
private List<User> users;
#Column(name = "CODE_ROLE", nullable = true, length = 255)
private String code;
#Column(name = "DESCRIPTION_ROLE", nullable = true, length = 255)
private String description;
#Column(name = "NAME_ROLE", nullable = true, length = 255)
private String name;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public List<User> getUsers() {
return users;
}
public void setUsers(List<User> users) {
this.users = users;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Update:
JwtRequestFilter
package br.com.aquamain.backend.security;
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.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import br.com.aquamain.backend.security.service.JwtUserDetailsService;
import br.com.aquamain.backend.security.utils.JwtTokenUtils;
import io.jsonwebtoken.ExpiredJwtException;
#Component
public class JwtRequestFilter extends OncePerRequestFilter {
#Autowired
private JwtUserDetailsService jwtUserDetailsService;
#Autowired
private JwtTokenUtils jwtTokenUtil;
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
final String requestTokenHeader = request.getHeader("Authorization");
String username = null;
String jwtToken = null;
if (requestTokenHeader != null && requestTokenHeader.startsWith("Bearer ")) {
jwtToken = requestTokenHeader.substring(7);
try {
username = jwtTokenUtil.getUsernameFromToken(jwtToken);
} catch (IllegalArgumentException e) {
System.out.println("Unable to get JWT Token");
} catch (ExpiredJwtException e) {
System.out.println("JWT Token has expired");
}
} else {
logger.warn("JWT Token does not begin with Bearer String");
}
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = this.jwtUserDetailsService.loadUserByUsername(username);
if (jwtTokenUtil.validateToken(jwtToken, userDetails)) {
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
usernamePasswordAuthenticationToken
.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
}
}
chain.doFilter(request, response);
}
}
Log:
[32m2022-04-12 11:14:54 TRACE o.s.security.web.FilterChainProxy - Trying to match request against DefaultSecurityFilterChain [RequestMatcher=Mvc [pattern='/**', OPTIONS], Filters=[]] (1/7)
[0;39m[32m2022-04-12 11:14:54 TRACE o.s.security.web.FilterChainProxy - Trying to match request against DefaultSecurityFilterChain [RequestMatcher=Mvc [pattern='/swagger-ui.html/**'], Filters=[]] (2/7)
[0;39m[32m2022-04-12 11:14:54 TRACE o.s.security.web.FilterChainProxy - Trying to match request against DefaultSecurityFilterChain [RequestMatcher=Mvc [pattern='/configuration/**'], Filters=[]] (3/7)
[0;39m[32m2022-04-12 11:14:54 TRACE o.s.security.web.FilterChainProxy - Trying to match request against DefaultSecurityFilterChain [RequestMatcher=Mvc [pattern='/swagger-resources/**'], Filters=[]] (4/7)
[0;39m[32m2022-04-12 11:14:54 TRACE o.s.security.web.FilterChainProxy - Trying to match request against DefaultSecurityFilterChain [RequestMatcher=Mvc [pattern='/v2/api-docs'], Filters=[]] (5/7)
[0;39m[32m2022-04-12 11:14:54 TRACE o.s.security.web.FilterChainProxy - Trying to match request against DefaultSecurityFilterChain [RequestMatcher=Mvc [pattern='/webjars/**'], Filters=[]] (6/7)
[0;39m[32m2022-04-12 11:14:54 TRACE o.s.security.web.FilterChainProxy - Trying to match request against DefaultSecurityFilterChain [RequestMatcher=any request, Filters=[org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter#6d29e44e, org.springframework.security.web.context.SecurityContextPersistenceFilter#431fc40, org.springframework.security.web.header.HeaderWriterFilter#72dd71b5, org.springframework.web.filter.CorsFilter#258798b6, org.springframework.security.web.authentication.logout.LogoutFilter#48124669, br.com.aquamain.backend.security.JwtRequestFilter#4efcbbde, org.springframework.security.web.savedrequest.RequestCacheAwareFilter#293ce7b0, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter#7879d247, org.springframework.security.web.authentication.AnonymousAuthenticationFilter#5e7f5483, org.springframework.security.web.session.SessionManagementFilter#4ce3c16a, org.springframework.security.web.access.ExceptionTranslationFilter#58ad93f, org.springframework.security.web.access.intercept.FilterSecurityInterceptor#6f778913]] (7/7)
[0;39m[32m2022-04-12 11:14:54 DEBUG o.s.security.web.FilterChainProxy - Securing POST /api/persons/new
[0;39m[32m2022-04-12 11:14:54 TRACE o.s.security.web.FilterChainProxy - Invoking WebAsyncManagerIntegrationFilter (1/12)
[0;39m[32m2022-04-12 11:14:54 TRACE o.s.security.web.FilterChainProxy - Invoking SecurityContextPersistenceFilter (2/12)
[0;39m[32m2022-04-12 11:14:54 DEBUG o.s.s.w.c.SecurityContextPersistenceFilter - Set SecurityContextHolder to empty SecurityContext
[0;39m[32m2022-04-12 11:14:54 TRACE o.s.security.web.FilterChainProxy - Invoking HeaderWriterFilter (3/12)
[0;39m[32m2022-04-12 11:14:54 TRACE o.s.security.web.FilterChainProxy - Invoking CorsFilter (4/12)
[0;39m[32m2022-04-12 11:14:54 TRACE o.s.security.web.FilterChainProxy - Invoking LogoutFilter (5/12)
[0;39m[32m2022-04-12 11:14:54 TRACE o.s.s.w.a.logout.LogoutFilter - Did not match request to Or [Ant [pattern='/logout', GET], Ant [pattern='/logout', POST], Ant [pattern='/logout', PUT], Ant [pattern='/logout', DELETE]]
[0;39m[32m2022-04-12 11:14:54 TRACE o.s.security.web.FilterChainProxy - Invoking JwtRequestFilter (6/12)
[0;39mHibernate:
/* select
generatedAlias0
from
User as generatedAlias0
where
generatedAlias0.username=:param0 */ select
user0_.ID_USER as id_user1_3_,
user0_.LAST_LOGIN_DATE as last_log2_3_,
user0_.PASSWORD_USER as password3_3_,
user0_.RESET_PASSWORD_TOKEN as reset_pa4_3_,
user0_.USERNAME_USER as username5_3_
from
AQUARIUM_MAINTANCE_MONITOR_USER user0_
where
user0_.USERNAME_USER=?
Hibernate:
/* load br.com.aquamain.backend.model.Person */ select
person0_.ID_PERSON as id_perso1_0_1_,
person0_.BIRTHDAY_PERSON as birthday2_0_1_,
person0_.NAME_PERSON as name_per3_0_1_,
person0_.ID_USER as id_user4_0_1_,
user1_.ID_USER as id_user1_3_0_,
user1_.LAST_LOGIN_DATE as last_log2_3_0_,
user1_.PASSWORD_USER as password3_3_0_,
user1_.RESET_PASSWORD_TOKEN as reset_pa4_3_0_,
user1_.USERNAME_USER as username5_3_0_
from
AQUARIUM_MAINTANCE_MONITOR_PERSON person0_
left outer join
AQUARIUM_MAINTANCE_MONITOR_USER user1_
on person0_.ID_USER=user1_.ID_USER
where
person0_.ID_USER=?
[32m2022-04-12 11:14:54 TRACE o.s.security.web.FilterChainProxy - Invoking RequestCacheAwareFilter (7/12)
[0;39m[32m2022-04-12 11:14:54 TRACE o.s.security.web.FilterChainProxy - Invoking SecurityContextHolderAwareRequestFilter (8/12)
[0;39m[32m2022-04-12 11:14:54 TRACE o.s.security.web.FilterChainProxy - Invoking AnonymousAuthenticationFilter (9/12)
[0;39m[32m2022-04-12 11:14:54 TRACE o.s.s.w.a.AnonymousAuthenticationFilter - Did not set SecurityContextHolder since already authenticated UsernamePasswordAuthenticationToken [Principal=Id:1
Username:tony.stark
Last Login:2022-04-12T11:14:30.058-03:00
, Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=null], Granted Authorities=[]]
[0;39m[32m2022-04-12 11:14:54 TRACE o.s.security.web.FilterChainProxy - Invoking SessionManagementFilter (10/12)
[0;39m[32m2022-04-12 11:14:54 TRACE o.s.s.w.a.s.CompositeSessionAuthenticationStrategy - Preparing session with ChangeSessionIdAuthenticationStrategy (1/1)
[0;39m[32m2022-04-12 11:14:54 TRACE o.s.security.web.FilterChainProxy - Invoking ExceptionTranslationFilter (11/12)
[0;39m[32m2022-04-12 11:14:54 TRACE o.s.security.web.FilterChainProxy - Invoking FilterSecurityInterceptor (12/12)
[0;39m[32m2022-04-12 11:14:54 TRACE o.s.s.w.a.e.ExpressionBasedFilterInvocationSecurityMetadataSource - Did not match request to Ant [pattern='/spring-security-rest/**'] - [permitAll] (1/5)
[0;39m[32m2022-04-12 11:14:54 TRACE o.s.s.w.a.e.ExpressionBasedFilterInvocationSecurityMetadataSource - Did not match request to Ant [pattern='/api/authentication/**', POST] - [permitAll] (2/5)
[0;39m[32m2022-04-12 11:14:54 TRACE o.s.s.w.a.i.FilterSecurityInterceptor - Did not re-authenticate UsernamePasswordAuthenticationToken [Principal=Id:1
Username:tony.stark
Last Login:2022-04-12T11:14:30.058-03:00
, Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=null], Granted Authorities=[]] before authorizing
[0;39m[32m2022-04-12 11:14:54 TRACE o.s.s.w.a.i.FilterSecurityInterceptor - Authorizing filter invocation [POST /api/persons/new] with attributes [hasRole('ROLE_SYS_ADMIN')]
[0;39m[32m2022-04-12 11:14:54 TRACE o.s.s.w.a.e.WebExpressionVoter - Voted to deny authorization
[0;39m[32m2022-04-12 11:14:54 TRACE o.s.s.w.a.i.FilterSecurityInterceptor - Failed to authorize filter invocation [POST /api/persons/new] with attributes [hasRole('ROLE_SYS_ADMIN')] using AffirmativeBased [DecisionVoters=[org.springframework.security.web.access.expression.WebExpressionVoter#4f47d6c4], AllowIfAllAbstainDecisions=false]
[0;39m[32m2022-04-12 11:14:54 TRACE o.s.s.w.a.ExceptionTranslationFilter - Sending UsernamePasswordAuthenticationToken [Principal=Id:1
Username:tony.stark
Last Login:2022-04-12T11:14:30.058-03:00
, Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=null], Granted Authorities=[]] to access denied handler since access is denied
[0;39morg.springframework.security.access.AccessDeniedException: Access is denied
at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:73)
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.attemptAuthorization(AbstractSecurityInterceptor.java:238)
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:208)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:113)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:81)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:121)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:115)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:126)
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:81)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:105)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:149)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
at br.com.aquamain.backend.security.JwtRequestFilter.doFilterInternal(JwtRequestFilter.java:64)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:103)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:89)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:91)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90)
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:110)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:80)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:55)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:211)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:183)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:190)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:163)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:190)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:163)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:382)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:893)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1723)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.base/java.lang.Thread.run(Thread.java:833)
[32m2022-04-12 11:14:54 DEBUG o.s.s.w.a.AccessDeniedHandlerImpl - Responding with 403 status code
[0;39m[32m2022-04-12 11:14:54 TRACE o.s.s.w.h.writers.HstsHeaderWriter - Not injecting HSTS header since it did not match request to [Is Secure]
[0;39m[32m2022-04-12 11:14:54 DEBUG o.s.s.w.c.SecurityContextPersistenceFilter - Cleared SecurityContextHolder to complete request
[0;39m[32m2022-04-12 11:14:54 TRACE o.s.security.web.FilterChainProxy - Trying to match request against DefaultSecurityFilterChain [RequestMatcher=Mvc [pattern='/**', OPTIONS], Filters=[]] (1/7)
[0;39m[32m2022-04-12 11:14:54 TRACE o.s.security.web.FilterChainProxy - Trying to match request against DefaultSecurityFilterChain [RequestMatcher=Mvc [pattern='/swagger-ui.html/**'], Filters=[]] (2/7)
[0;39m[32m2022-04-12 11:14:54 TRACE o.s.security.web.FilterChainProxy - Trying to match request against DefaultSecurityFilterChain [RequestMatcher=Mvc [pattern='/configuration/**'], Filters=[]] (3/7)
[0;39m[32m2022-04-12 11:14:54 TRACE o.s.security.web.FilterChainProxy - Trying to match request against DefaultSecurityFilterChain [RequestMatcher=Mvc [pattern='/swagger-resources/**'], Filters=[]] (4/7)
[0;39m[32m2022-04-12 11:14:54 TRACE o.s.security.web.FilterChainProxy - Trying to match request against DefaultSecurityFilterChain [RequestMatcher=Mvc [pattern='/v2/api-docs'], Filters=[]] (5/7)
[0;39m[32m2022-04-12 11:14:54 TRACE o.s.security.web.FilterChainProxy - Trying to match request against DefaultSecurityFilterChain [RequestMatcher=Mvc [pattern='/webjars/**'], Filters=[]] (6/7)
[0;39m[32m2022-04-12 11:14:54 TRACE o.s.security.web.FilterChainProxy - Trying to match request against DefaultSecurityFilterChain [RequestMatcher=any request, Filters=[org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter#6d29e44e, org.springframework.security.web.context.SecurityContextPersistenceFilter#431fc40, org.springframework.security.web.header.HeaderWriterFilter#72dd71b5, org.springframework.web.filter.CorsFilter#258798b6, org.springframework.security.web.authentication.logout.LogoutFilter#48124669, br.com.aquamain.backend.security.JwtRequestFilter#4efcbbde, org.springframework.security.web.savedrequest.RequestCacheAwareFilter#293ce7b0, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter#7879d247, org.springframework.security.web.authentication.AnonymousAuthenticationFilter#5e7f5483, org.springframework.security.web.session.SessionManagementFilter#4ce3c16a, org.springframework.security.web.access.ExceptionTranslationFilter#58ad93f, org.springframework.security.web.access.intercept.FilterSecurityInterceptor#6f778913]] (7/7)
[0;39m[32m2022-04-12 11:14:54 DEBUG o.s.security.web.FilterChainProxy - Securing POST /error
[0;39m[32m2022-04-12 11:14:54 TRACE o.s.security.web.FilterChainProxy - Invoking WebAsyncManagerIntegrationFilter (1/12)
[0;39m[32m2022-04-12 11:14:54 TRACE o.s.security.web.FilterChainProxy - Invoking SecurityContextPersistenceFilter (2/12)
[0;39m[32m2022-04-12 11:14:54 DEBUG o.s.s.w.c.SecurityContextPersistenceFilter - Set SecurityContextHolder to empty SecurityContext
[0;39m[32m2022-04-12 11:14:54 TRACE o.s.security.web.FilterChainProxy - Invoking HeaderWriterFilter (3/12)
[0;39m[32m2022-04-12 11:14:54 TRACE o.s.security.web.FilterChainProxy - Invoking CorsFilter (4/12)
[0;39m[32m2022-04-12 11:14:54 TRACE o.s.security.web.FilterChainProxy - Invoking LogoutFilter (5/12)
[0;39m[32m2022-04-12 11:14:54 TRACE o.s.s.w.a.logout.LogoutFilter - Did not match request to Or [Ant [pattern='/logout', GET], Ant [pattern='/logout', POST], Ant [pattern='/logout', PUT], Ant [pattern='/logout', DELETE]]
[0;39m[32m2022-04-12 11:14:54 TRACE o.s.security.web.FilterChainProxy - Invoking JwtRequestFilter (6/12)
[0;39m[32m2022-04-12 11:14:54 TRACE o.s.security.web.FilterChainProxy - Invoking RequestCacheAwareFilter (7/12)
[0;39m[32m2022-04-12 11:14:54 TRACE o.s.security.web.FilterChainProxy - Invoking SecurityContextHolderAwareRequestFilter (8/12)
[0;39m[32m2022-04-12 11:14:54 TRACE o.s.security.web.FilterChainProxy - Invoking AnonymousAuthenticationFilter (9/12)
[0;39m[32m2022-04-12 11:14:54 TRACE o.s.s.w.a.AnonymousAuthenticationFilter - Set SecurityContextHolder to AnonymousAuthenticationToken [Principal=anonymousUser, Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=null], Granted Authorities=[ROLE_ANONYMOUS]]
[0;39m[32m2022-04-12 11:14:54 TRACE o.s.security.web.FilterChainProxy - Invoking SessionManagementFilter (10/12)
[0;39m[32m2022-04-12 11:14:54 TRACE o.s.security.web.FilterChainProxy - Invoking ExceptionTranslationFilter (11/12)
[0;39m[32m2022-04-12 11:14:54 TRACE o.s.security.web.FilterChainProxy - Invoking FilterSecurityInterceptor (12/12)
[0;39m[32m2022-04-12 11:14:54 DEBUG o.s.security.web.FilterChainProxy - Secured POST /error
[0;39m[32m2022-04-12 11:14:54 DEBUG o.s.s.w.c.SecurityContextPersistenceFilter - Cleared SecurityContextHolder to complete request
I have a problem with my Spring Security JWT Application. I am getting an error because my JWT is expired, but I can't find, where it gets the 2022-04-12 as an expiration date. I can't find a single piece of code, which says that the expiration date is the 2022-04-12. After my understanding, it is creating a new token, each time I am logging in with a new expiration time, which also has to be true, because in my output I get a new token everytime. But because the 2022-04-12 has already passed, I am getting a "io.jsonwebtoken.ExpiredJwtException". So where does it get the 2022-04-12 from???
I am just providing the parts of my code, I think are neccesary, but if you need more code, just let me know!( I am using Spring Security, if that matters)
Filter:
package de.gabriel.springsecurityjwt.filters;
import de.gabriel.springsecurityjwt.services.MyUserDetailsService;
import de.gabriel.springsecurityjwt.util.JwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
#Component
public class JwtRequestFilter extends OncePerRequestFilter {
#Autowired
private MyUserDetailsService userDetailsService;
#Autowired
private JwtUtil jwtUtil;
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
final String authorizationHeader = request.getHeader("Authorization");
String username = null;
String jwt = null;
if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
jwt = authorizationHeader.substring(7);
username = jwtUtil.extractUsername(jwt);
}
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
if (jwtUtil.validateToken(jwt, userDetails)) { // If token is valid
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
usernamePasswordAuthenticationToken
.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
}
}
chain.doFilter(request, response);
}
}
Util class for JWT:
package de.gabriel.springsecurityjwt.util;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
#Service
public class JwtUtil { // JwtUtil is a class that is used to create and parse JWT tokens
private final String SECRET_KEY = "secret";
public String extractUsername(String token) {
return extractClaim(token, Claims::getSubject);
}
public Date extractExpiration(String token) {
return extractClaim(token, Claims::getExpiration);
}
public <T> T extractClaim(String token, Function<Claims, T> claimsResolver) {
final Claims claims = extractAllClaims(token);
return claimsResolver.apply(claims);
}
private Claims extractAllClaims(String token) {
return Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody();
}
private Boolean isTokenExpired(String token) {
return extractExpiration(token).before(new Date());
}
public String generateToken(UserDetails userDetails) {
Map<String, Object> claims = new HashMap<>();
return createToken(claims, userDetails.getUsername());
}
private String createToken(Map<String, Object> claims, String subject) {
return Jwts.builder().setClaims(claims).setSubject(subject).setIssuedAt(new Date(System.currentTimeMillis()))
.setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 10))
.signWith(SignatureAlgorithm.HS256, SECRET_KEY).compact();
}
public Boolean validateToken(String token, UserDetails userDetails) {
final String username = extractUsername(token);
return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
}
}
Rest Controller class:
package de.gabriel.springsecurityjwt;
import de.gabriel.springsecurityjwt.models.AuthenticationRequest;
import de.gabriel.springsecurityjwt.models.AuthenticationResponse;
import de.gabriel.springsecurityjwt.services.MyUserDetailsService;
import de.gabriel.springsecurityjwt.util.JwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.Date;
#RestController
public class HelloResource {
#Autowired
private AuthenticationManager authenticationManager;
#Autowired
private JwtUtil jwtTokenUtil;
#Autowired
private MyUserDetailsService userDetailsService;
#RequestMapping( "/hello" )
public String hello() {
return "Hello World";
}
#RequestMapping(value = "/authenticate", method = RequestMethod.POST)
public ResponseEntity<?> createAuthenticationToken(#RequestBody AuthenticationRequest authenticationRequest) throws Exception {
try {
authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(authenticationRequest.getUsername(), authenticationRequest.getPassword())
);
}
catch (BadCredentialsException e) {
throw new Exception("Incorrect username or password", e);
}
final UserDetails userDetails = userDetailsService
.loadUserByUsername(authenticationRequest.getUsername());
final String jwt = jwtTokenUtil.generateToken(userDetails);
return ResponseEntity.ok(new AuthenticationResponse(jwt)); // Return token
}
}
Security Configurer class:
package de.gabriel.springsecurityjwt;
import de.gabriel.springsecurityjwt.filters.JwtRequestFilter;
import de.gabriel.springsecurityjwt.services.MyUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
#EnableWebSecurity
public class SecurityConfigurer extends WebSecurityConfigurerAdapter {
#Autowired
private UserDetailsService myUserDetailsService;
#Autowired
private JwtRequestFilter jwtRequestFilter;
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(myUserDetailsService);
}
#Bean
public PasswordEncoder passwordEncoder() {
return NoOpPasswordEncoder.getInstance();
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.csrf().disable()
.authorizeRequests().antMatchers("/authenticate").permitAll().
anyRequest().authenticated().and().
exceptionHandling().and().sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
httpSecurity.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
}
}
Here is the error log:
io.jsonwebtoken.ExpiredJwtException: JWT expired at 2022-04-12T21:27:05Z. Current time: 2022-04-14T22:20:23Z, a difference of 175998276 milliseconds. Allowed clock skew: 0 milliseconds.
at io.jsonwebtoken.impl.DefaultJwtParser.parse(DefaultJwtParser.java:385) ~[jjwt-0.9.1.jar:0.9.1]
at io.jsonwebtoken.impl.DefaultJwtParser.parse(DefaultJwtParser.java:481) ~[jjwt-0.9.1.jar:0.9.1]
at io.jsonwebtoken.impl.DefaultJwtParser.parseClaimsJws(DefaultJwtParser.java:541) ~[jjwt-0.9.1.jar:0.9.1]
at de.gabriel.springsecurityjwt.util.JwtUtil.extractAllClaims(JwtUtil.java:31) ~[classes/:na]
at de.gabriel.springsecurityjwt.util.JwtUtil.extractClaim(JwtUtil.java:27) ~[classes/:na]
at de.gabriel.springsecurityjwt.util.JwtUtil.extractUsername(JwtUtil.java:19) ~[classes/:na]
at de.gabriel.springsecurityjwt.filters.JwtRequestFilter.doFilterInternal(JwtRequestFilter.java:41) ~[classes/:na]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.18.jar:5.3.18]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.6.2.jar:5.6.2]
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:103) ~[spring-security-web-5.6.2.jar:5.6.2]
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:89) ~[spring-security-web-5.6.2.jar:5.6.2]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.6.2.jar:5.6.2]
at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90) ~[spring-security-web-5.6.2.jar:5.6.2]
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75) ~[spring-security-web-5.6.2.jar:5.6.2]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.18.jar:5.3.18]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.6.2.jar:5.6.2]
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:110) ~[spring-security-web-5.6.2.jar:5.6.2]
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:80) ~[spring-security-web-5.6.2.jar:5.6.2]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.6.2.jar:5.6.2]
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:55) ~[spring-security-web-5.6.2.jar:5.6.2]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.18.jar:5.3.18]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.6.2.jar:5.6.2]
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:211) ~[spring-security-web-5.6.2.jar:5.6.2]
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:183) ~[spring-security-web-5.6.2.jar:5.6.2]
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:354) ~[spring-web-5.3.18.jar:5.3.18]
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:267) ~[spring-web-5.3.18.jar:5.3.18]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.18.jar:5.3.18]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.18.jar:5.3.18]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.18.jar:5.3.18]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.18.jar:5.3.18]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.18.jar:5.3.18]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.18.jar:5.3.18]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:360) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:399) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:889) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1743) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
at java.base/java.lang.Thread.run(Thread.java:833) ~[na:na]
This is the token used:
eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJmb28iLCJleHAiOjE2NTAwMDIyOTEsImlhdCI6MTY0OTk2NjI5MX0.tzfB0Wy9Dp3Y9pl-5_Oc4gwPClOHlIjE8kHUcgvKhUs
And this is the token (payload) decoded:
{
"sub": "foo",
"exp": 1650002291, (2022-04-15)
"iat": 1649966291
}
This is a
image of the decoded JWT from jwt.io
And this this is the request I use
I made a mistake, while sending the request in Postman. Instead of passing the JWT in the Header I passed it as an Parameter, which of course won't work because I have nothing that extracts the JWT from the URL🤦♂️
I want to enable Keycloak in my Spring Boot REST API APP but without success and i'm still getting null pointer error on any request. I try different configuration of keycloak. App works without Security Config.
Here is my application.properties
keycloak.realm=realm
keycloak.resource=realm-pi
keycloak.public-client=true
keycloak.auth-server-url=http://10.240.1.10:8087/auth/realms/realm/
And KeycloackSecurity class
import org.keycloak.adapters.springsecurity.KeycloakSecurityComponents;
import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationProvider;
import org.keycloak.adapters.springsecurity.config.KeycloakWebSecurityConfigurerAdapter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
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.core.authority.mapping.SimpleAuthorityMapper;
import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy;
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
#Configuration
#EnableWebSecurity
#ComponentScan(basePackageClasses = KeycloakSecurityComponents.class)
class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
#Autowired
public void configureGlobal(
AuthenticationManagerBuilder auth) {
KeycloakAuthenticationProvider keycloakAuthenticationProvider
= keycloakAuthenticationProvider();
keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(
new SimpleAuthorityMapper());
auth.authenticationProvider(keycloakAuthenticationProvider);
}
#Bean
#Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new RegisterSessionAuthenticationStrategy(
new SessionRegistryImpl());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.authorizeRequests()
.antMatchers("/api/product-anon/**").permitAll();
http.csrf().disable();
}
}
KeycloakConfigResolver i've added it in sepearate class because when it was in SecurityConfig it causes error with circular dependency.
import org.keycloak.adapters.springboot.KeycloakSpringBootConfigResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
#Configuration
public class KeycloakConfiguration {
#Bean
public KeycloakSpringBootConfigResolver KeycloakConfigResolver() {
return new KeycloakSpringBootConfigResolver();
}
}
and Stack Trace
2022-02-04 11:07:27.308 ERROR 34372 --- [nio-8080-exec-2] o.a.c.c.C.[Tomcat].[localhost] : Exception Processing ErrorPage[errorCode=0, location=/error]
java.lang.NullPointerException: null
at org.keycloak.adapters.KeycloakDeploymentBuilder.internalBuild(KeycloakDeploymentBuilder.java:57) ~[keycloak-adapter-core-15.0.1.jar:15.0.1]
at org.keycloak.adapters.KeycloakDeploymentBuilder.build(KeycloakDeploymentBuilder.java:202) ~[keycloak-adapter-core-15.0.1.jar:15.0.1]
at org.keycloak.adapters.springboot.KeycloakSpringBootConfigResolver.resolve(KeycloakSpringBootConfigResolver.java:41) ~[keycloak-spring-boot-adapter-core-15.0.1.jar:15.0.1]
at org.keycloak.adapters.springsecurity.config.KeycloakSpringConfigResolverWrapper.resolve(KeycloakSpringConfigResolverWrapper.java:40) ~[keycloak-spring-security-adapter-15.0.1.jar:15.0.1]
at org.keycloak.adapters.AdapterDeploymentContext.resolveDeployment(AdapterDeploymentContext.java:89) ~[keycloak-adapter-core-15.0.1.jar:15.0.1]
at org.keycloak.adapters.springsecurity.filter.KeycloakPreAuthActionsFilter.doFilter(KeycloakPreAuthActionsFilter.java:82) ~[keycloak-spring-security-adapter-15.0.1.jar:15.0.1]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.6.1.jar:5.6.1]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:102) ~[spring-web-5.3.15.jar:5.3.15]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.6.1.jar:5.6.1]
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:110) ~[spring-security-web-5.6.1.jar:5.6.1]
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:80) ~[spring-security-web-5.6.1.jar:5.6.1]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.6.1.jar:5.6.1]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:102) ~[spring-web-5.3.15.jar:5.3.15]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.6.1.jar:5.6.1]
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:211) ~[spring-security-web-5.6.1.jar:5.6.1]
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:183) ~[spring-security-web-5.6.1.jar:5.6.1]
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:354) ~[spring-web-5.3.15.jar:5.3.15]
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:267) ~[spring-web-5.3.15.jar:5.3.15]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.56.jar:9.0.56]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.56.jar:9.0.56]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.15.jar:5.3.15]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.15.jar:5.3.15]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.56.jar:9.0.56]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.56.jar:9.0.56]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:102) ~[spring-web-5.3.15.jar:5.3.15]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.56.jar:9.0.56]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.56.jar:9.0.56]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:102) ~[spring-web-5.3.15.jar:5.3.15]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.56.jar:9.0.56]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.56.jar:9.0.56]
at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:711) ~[tomcat-embed-core-9.0.56.jar:9.0.56]
at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:461) ~[tomcat-embed-core-9.0.56.jar:9.0.56]
at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:385) ~[tomcat-embed-core-9.0.56.jar:9.0.56]
at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:313) ~[tomcat-embed-core-9.0.56.jar:9.0.56]
at org.apache.catalina.core.StandardHostValve.custom(StandardHostValve.java:403) ~[tomcat-embed-core-9.0.56.jar:9.0.56]
at org.apache.catalina.core.StandardHostValve.status(StandardHostValve.java:249) ~[tomcat-embed-core-9.0.56.jar:9.0.56]
at org.apache.catalina.core.StandardHostValve.throwable(StandardHostValve.java:344) ~[tomcat-embed-core-9.0.56.jar:9.0.56]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:169) ~[tomcat-embed-core-9.0.56.jar:9.0.56]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.56.jar:9.0.56]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[tomcat-embed-core-9.0.56.jar:9.0.56]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357) ~[tomcat-embed-core-9.0.56.jar:9.0.56]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:382) ~[tomcat-embed-core-9.0.56.jar:9.0.56]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.56.jar:9.0.56]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:895) ~[tomcat-embed-core-9.0.56.jar:9.0.56]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1732) ~[tomcat-embed-core-9.0.56.jar:9.0.56]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.56.jar:9.0.56]
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) ~[tomcat-embed-core-9.0.56.jar:9.0.56]
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-9.0.56.jar:9.0.56]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.56.jar:9.0.56]
at java.base/java.lang.Thread.run(Thread.java:829) ~[na:na]
In the new version for example keycloak 17.0.0. They removed the part from the url "auth".
If you use this version then change in your application.properties next line.
keycloak.auth-server-url=http://10.240.1.10:8087
But if you want to know what is your token_endpoint according your keycloak version then choose your realm -> Realm Settings -> EndPoints and Click on OpenID Endpoint Configuration. You can see all the information.
I'm trying to use Oauth2 in authorization to get access to my javafx spring boot based application.
I looked around a lot of tutorials in github to get started using spring cloud, I successfully setup an eureka server with zuul as gateway that are working fine
I have this authorization server implementation:
#SpringBootApplication
#EnableAuthorizationServer
#EnableEurekaClient
#RestController
#SessionAttributes("authorizationRequest")
public class AuthorizationApplication {
public static void main(String[] args) {
SpringApplication.run(AuthorizationApplication.class, args);
}
#Configuration
static class MvcConfig extends WebMvcConfigurerAdapter {
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("login").setViewName("login");
registry.addViewController("/oauth/confirm_access").setViewName("authorize");
registry.addViewController("/").setViewName("index");
}
}
#Configuration
static class LoginConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin().loginPage("/login").permitAll()
.successHandler(new AuthenticationSuccessHandler() {
#Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
response.getWriter().write("writting a success message here");
}
}).failureHandler(new AuthenticationFailureHandler() {
#Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
response.getWriter().write("failure message Bad Credentials");
}
})
.and()
.requestMatchers()
.antMatchers("/", "/login", "/oauth/authorize", "/oauth/confirm_access")
.and()
.authorizeRequests()
.anyRequest().authenticated()
.and().httpBasic().and().csrf().disable();
}
#Autowired
MDSUserDetailService mdsUserServiceDetail;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(mdsUserServiceDetail);
}
}
#Profile("!cloud")
#Bean
RequestDumperFilter requestDumperFilter() {
return new RequestDumperFilter();
}
}
this is the userServiceDetail implementation
#Service
class MDSUserDetailService implements UserDetailsService {
#Autowired
private UserRepository repository;
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
demo.User user = repository.findByUtilisateur(username);
String password =user.getPassword();
boolean enabled = user.isEtatUtilisateur();
boolean accountNonExpired = user.getDateFin().after(repository.getCurrentTime());
boolean accountNonLocked = user.isEtatUtilisateur();
Collection<? extends GrantedAuthority> authorities = new ArrayList();
return new User(username, password, enabled, accountNonExpired, true, accountNonLocked, authorities);
}
}
finally this is my authorization service yml
spring:
application:
name: uaa
security:
oauth2:
client:
client-id: mds_group
client-secret: mds_group
scope: read, write
auto-approve-scopes: .*
authorization:
check-token-access: permitAll()
server:
port: 18080
context-path: /uaa
logging:
level:
org.springframework.security: DEBUG
Now I will present my javafx client which is pretty simple a login form
#SpringBootApplication
#EnableOAuth2Sso
#EnableEurekaClient
#RibbonClients(
{
#RibbonClient(name = "uaa"),
#RibbonClient(name = "article")
}
)
public class ClientApplication extends Application{
ConfigurableApplicationContext applicationContext;
public static void main(String[] args) {
ClientApplication.launch(args);
}
#Bean
#LoadBalanced
OAuth2RestTemplate oauth2RestTemplate(OAuth2ClientContext oauth2ClientContext, OAuth2ProtectedResourceDetails details) {
return new OAuth2RestTemplate(details, oauth2ClientContext);
}
#Profile("!cloud")
#Bean
RequestDumperFilter requestDumperFilter() {
return new RequestDumperFilter();
}
#Override
public void start(Stage stage) throws Exception {
//launching java fx app here
applicationContext = SpringApplication.run(ClientApplication.class);
Parent root = FXMLLoader.load(getClass().getResource("/fxml/Login.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.setTitle("javafx oauth2 tutorial");
stage.show();
}
#Override
public void stop() throws Exception {
applicationContext.close();
}
}
here is my controller of the Login.fxml
#Component
public class LoginController implements Initializable {
#Autowired
private RestTemplate restTemplate;
/**
* Initializes the controller class.
*/
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
#FXML
private void doConnect(ActionEvent event) {
if(validate()){
Map<String,String> values = new HashMap<>();
values.put("username",username.getText());
values.put("password",password.getText());
restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new StringHttpMessageConverter());
//https://localhost:9999/oauth/token?grant_type=password?username=user&password=user
ResponseEntity<String> request = restTemplate.postForEntity("http://localhost:9999/uaa/login?username="+username.getText()+"&password="+password.getText(), values, String.class);
request = restTemplate.getForEntity("http://localhost:9999/uaa/oauth/token?grant_type=password?username="+username.getText()+"&password="+password.getText(), String.class , values);
//ResponseEntity<String> postForEntity = restTemplate.postForEntity(loginUrl, values, String.class);
System.out.println("post response "+request.getStatusCode().getReasonPhrase());
System.out.println("post response "+request.toString());
System.out.println("post response "+request.getHeaders().values());
}
}
private boolean validate() {
return true;
}
}
After running the first post is working just fine I'm getting a jsessionID but since I'm trying to use OAUTH2 the second get is not working fine and I'm getting this log exception in my authorization server
2018-07-23 15:55:13.002 DEBUG 10328 --- [io-18080-exec-9] o.s.security.web.FilterChainProxy : /oauth/token?password=HyiUucZK8elkbOiuSf5nx05CZwVNEYLiqW%2FzagK6iwg%3D&grant_type=password%3Fusername%3Dadministrateur at position 5 of 11 in additional filter chain; firing Filter: 'BasicAuthenticationFilter'
2018-07-23 15:55:13.002 DEBUG 10328 --- [io-18080-exec-9] o.s.security.web.FilterChainProxy : /oauth/token?password=HyiUucZK8elkbOiuSf5nx05CZwVNEYLiqW%2FzagK6iwg%3D&grant_type=password%3Fusername%3Dadministrateur at position 6 of 11 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
2018-07-23 15:55:13.002 DEBUG 10328 --- [io-18080-exec-9] o.s.security.web.FilterChainProxy : /oauth/token?password=HyiUucZK8elkbOiuSf5nx05CZwVNEYLiqW%2FzagK6iwg%3D&grant_type=password%3Fusername%3Dadministrateur at position 7 of 11 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
2018-07-23 15:55:13.002 DEBUG 10328 --- [io-18080-exec-9] o.s.security.web.FilterChainProxy : /oauth/token?password=HyiUucZK8elkbOiuSf5nx05CZwVNEYLiqW%2FzagK6iwg%3D&grant_type=password%3Fusername%3Dadministrateur at position 8 of 11 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
2018-07-23 15:55:13.002 DEBUG 10328 --- [io-18080-exec-9] o.s.s.w.a.AnonymousAuthenticationFilter : Populated SecurityContextHolder with anonymous token: 'org.springframework.security.authentication.AnonymousAuthenticationToken#905571d8: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails#0: RemoteIpAddress: 192.168.44.1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS'
2018-07-23 15:55:13.002 DEBUG 10328 --- [io-18080-exec-9] o.s.security.web.FilterChainProxy : /oauth/token?password=HyiUucZK8elkbOiuSf5nx05CZwVNEYLiqW%2FzagK6iwg%3D&grant_type=password%3Fusername%3Dadministrateur at position 9 of 11 in additional filter chain; firing Filter: 'SessionManagementFilter'
2018-07-23 15:55:13.002 DEBUG 10328 --- [io-18080-exec-9] o.s.security.web.FilterChainProxy : /oauth/token?password=HyiUucZK8elkbOiuSf5nx05CZwVNEYLiqW%2FzagK6iwg%3D&grant_type=password%3Fusername%3Dadministrateur at position 10 of 11 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
2018-07-23 15:55:13.003 DEBUG 10328 --- [io-18080-exec-9] o.s.security.web.FilterChainProxy : /oauth/token?password=HyiUucZK8elkbOiuSf5nx05CZwVNEYLiqW%2FzagK6iwg%3D&grant_type=password%3Fusername%3Dadministrateur at position 11 of 11 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
2018-07-23 15:55:13.003 DEBUG 10328 --- [io-18080-exec-9] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/oauth/token'; against '/oauth/token'
2018-07-23 15:55:13.003 DEBUG 10328 --- [io-18080-exec-9] o.s.s.w.a.i.FilterSecurityInterceptor : Secure object: FilterInvocation: URL: /oauth/token?password=HyiUucZK8elkbOiuSf5nx05CZwVNEYLiqW%2FzagK6iwg%3D&grant_type=password%3Fusername%3Dadministrateur; Attributes: [fullyAuthenticated]
2018-07-23 15:55:13.003 DEBUG 10328 --- [io-18080-exec-9] o.s.s.w.a.i.FilterSecurityInterceptor : Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken#905571d8: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails#0: RemoteIpAddress: 192.168.44.1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS
2018-07-23 15:55:13.004 DEBUG 10328 --- [io-18080-exec-9] o.s.s.access.vote.AffirmativeBased : Voter: org.springframework.security.web.access.expression.WebExpressionVoter#2d8c2c29, returned: -1
2018-07-23 15:55:13.005 DEBUG 10328 --- [io-18080-exec-9] o.s.s.w.a.ExceptionTranslationFilter : Access is denied (user is anonymous); redirecting to authentication entry point
org.springframework.security.access.AccessDeniedException: Access is denied
at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:84) ~[spring-security-core-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:233) ~[spring-security-core-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:124) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:114) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137) [spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111) [spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:170) [spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63) [spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilterInternal(BasicAuthenticationFilter.java:158) [spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116) [spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64) [spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105) [spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56) [spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214) [spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177) [spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346) [spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262) [spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) [spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:105) [spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81) [spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) [spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.springframework.boot.actuate.autoconfigure.MetricsFilter.doFilterInternal(MetricsFilter.java:106) [spring-boot-actuator-1.5.6.RELEASE.jar:1.5.6.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:624) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:799) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1455) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.16.jar:8.5.16]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_131]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_131]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.16.jar:8.5.16]
at java.lang.Thread.run(Thread.java:748) [na:1.8.0_131]
What should I do to get the AccessToken and avoid this exception?
Please refer to this developer guide for Spring's OAuth client implementation.
https://projects.spring.io/spring-security-oauth/docs/oauth2.html
The answer you might be looking for is below.
#Bean
public OAuth2RestOperations restTemplate() {
OAuth2RestTemplate template = new OAuth2RestTemplate(resource(), new
DefaultOAuth2ClientContext(accessTokenRequest));
AccessTokenProviderChain provider = new AccessTokenProviderChain(Arrays.asList(new
AuthorizationCodeAccessTokenProvider()));
provider.setClientTokenServices(clientTokenServices());
return template;
}.
Use the above bean for Spring's OAuth rest client it will request for a token and then eventually pass that token for authentication. You dont have to worry about getting a token and pass it as a header, spring will do it for you with the above rest template. More details can be found in the document.