session timeout in spring boot + React - java

I am able to configure session timeout in web.xml, but after session timeout getting errors from react side.
using spring security and jwt token.
WebSecurity.java
#Configuration
#EnableWebSecurity
public class WebSecurity extends WebSecurityConfigurerAdapter {
#Autowired
UserDetailServiceImpl userDetails;
#Autowired
JWTAuthenticationFilter jwtRequestFilter;
#Autowired
public void configAuthentication(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetails).passwordEncoder(getPasswordEncoder());
}
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.csrf().disable().authorizeRequests()
.antMatchers(HttpMethod.GET, "/index*", "/static/**", "/*.js", "/*.json", "/*.ico", "/*.png")
.permitAll().antMatchers("/resources/**", "/login", "/", "/actuator").permitAll()
.antMatchers("/authenticate/**", "/identity/**").permitAll().anyRequest().authenticated().and().cors().and()
.exceptionHandling().and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
httpSecurity.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
web.xml
<session-config>
<session-timeout>1</session-timeout>
</session-config>
I tried sessionManagement().InvalidSessionURL("url") but on login it always redirect to invalid url only.
There is no api for login, we are loading from React directly.
Please let me know how to redirect to login page on session timeout ? and how to handle errors from react side ?

Related

How to fix BasicAuth for Spring Boot?

I'm writing an SpringBoot app. When I do requests with Postman - I get this error VERY OFTEN:
java.lang.NullPointerException: null
at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.authenticationIsRequired(BasicAuthenticationFilter.java:222) ~[spring-security-web-5.2.1.RELEASE.jar:5.2.1.RELEASE]
at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilterInternal(BasicAuthenticationFilter.java:166) ~[spring-security-web-5.2.1.RELEASE.jar:5.2.1.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.2.RELEASE.jar:5.2.2.RELEASE]
Here is my SecurityConfig:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private UserService userService;
#Autowired
private PasswordEncoder passwordEncoder;
#Bean
public PasswordEncoder getPasswordEncoder() {
return new BCryptPasswordEncoder(8);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/", "/registration", "/restaurants").permitAll()
.anyRequest().authenticated()
.and()
.httpBasic()
.and()
.rememberMe()
.and()
.logout()
.permitAll();
//Set enable when frontend added
http.csrf().disable();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userService)
.passwordEncoder(passwordEncoder);
}
}
How to fix it? I need to do request from Postman, so I can't change the login form.
Go to the Authorization tab in your Postman window ( it's under the request type ) and select 'Basic Auth' and fill in your credentials if you're doing any request other than "/", "/registration", "/restaurants".

${_csrf.token} on jsp always null with spring-security

I am working on a legacy Spring MVC application and I need to pass the _csrf token to a javascript but, after introducing spring-security (in particular auth0 user authentication), these two rows are always null:
<meta name="_csrf" content="${_csrf.token}"/>
<meta name="_csrf_header" content="${_csrf.headerName}"/>
This is how I override the configure(HttpSecurity http):
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
#PropertySources(#PropertySource("classpath:auth0.properties"))
#Order(-2 /* SecurityProperties.ACCESS_OVERRIDE_ORDER */)
public class AppConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/download/**", "/resources/**", "/plugins/**", "/js/**", "/css/**", "/colors/**", "/callback", "/login", "/loggedout").permitAll()
.antMatchers("/**").authenticated()
.and()
.logout().permitAll();
}
}
I have removed the DelegationgFilterProxy from the web.xml because it should be created extending the WebSecurityConfigurerAdapter and in according with this SO question ${_csrf.parameterName} and ${_csrf.token} return null I should re-add but, if I do, I get a startup error (missing springSecurityFilterChain).
So, the question is, why my token are null if I have implemented WebSecurityConfigurerAdapter and I do not disable the csrf?

Spring boot returns 404 on login.jsp

The login.jsp is located under /WEB-INF/views/ and the URL https://myprog.at.something:8080/login returns the "404 not found-message".
If I enter another URL, as for example https://myprog.at.something:8080/logout, I got a "302 found" message.
Console and debug mode shows no error. It is strange that this happens only on my computer, when a colleague is running the same spring boot application, it is starting without any problems on the login page.
Part of SpringConfigRootApplication.java
#Bean
public InternalResourceViewResolver getInternalResourceViewResolver() {
final InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
resolver.setRequestContextAttribute("requestContext");
resolver.setExposeContextBeansAsAttributes(true);
return resolver;
}
#Override
public void addViewControllers(final ViewControllerRegistry registry) {
registry.addViewController("/login").setViewName("login");
}
Part of SpringConfigSecurity.java
#Configuration
#EnableWebSecurity
public class SpringConfigSecurity extends WebSecurityConfigurerAdapter {
#Autowired
private UserDetailsService userDetailsService;
#Override
#Autowired
public void configure(final AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(NoOpPasswordEncoder.getInstance());
}
#Override
public void configure(final WebSecurity web) throws Exception {
web.ignoring().antMatchers("/resources/**", "/console/**", "/ping");
}
#Override
protected void configure(final HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin().loginPage("/login")
.loginProcessingUrl("/authcheck")
.usernameParameter("username")
.passwordParameter("password")
.defaultSuccessUrl("/", true)
.failureUrl("/login?failed=true")
.permitAll()
.and()
.logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout")).logoutSuccessUrl("/login");
}
}
Part of application.properties
server.error.whitelabel.enabled=false
spring.view.prefix: /WEB-INF/views/
spring.view.suffix: .jsp

Spring Security for Rest #PreAuthorize 500 error

I want basic security for rest ,this is my config:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private PacijentUserDetailsService pacijent;
#Autowired
private FizioterapeutUserDetailsService fizioterapeut;
#Autowired
private FizijatarUserDetailsService fizijatar;
#Override
protected void configure(AuthenticationManagerBuilder
auth) throws Exception {
auth.userDetailsService(pacijent)
.passwordEncoder(new
BCryptPasswordEncoder());
auth.userDetailsService(fizioterapeut).passwordEncoder(new
BCryptPasswordEncoder());
auth.userDetailsService(fizijatar).passwordEncoder(new
BCryptPasswordEncoder());
}
#Override
protected void configure(HttpSecurity http) throws Exception
{
http
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/pacijent/", "/fizijatar/","/fizioterapeut/").permitAll()
.antMatchers("/pacijent/**","/fizijatar/**","/fizioterapeut/**").authenticated()
.and()
.httpBasic()
.realmName("Ordinacija")
.and()
.csrf()
.disable();
}
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
I have 3 implements of userdetailservice this is one example:
#Component
public class PacijentUserDetailsService implements UserDetailsService {
#Autowired
private PacijentService pacijentService;
#Override
public UserDetails loadUserByUsername(String jmbg) throws UsernameNotFoundException {
Pacijent pacijent = pacijentService.vratiPacijenta(jmbg);
if (pacijent == null) {
throw new UsernameNotFoundException(String.format("Pacijent nije pronadjen", jmbg));
}
List<GrantedAuthority> authorities = new ArrayList<>();
if (pacijentService.postojiPacijentPoJmbgu(jmbg)) {
authorities = AuthorityUtils.createAuthorityList("ROLE_USER");
}
UserDetails userDetails = new org.springframework.security.core.userdetails.User(pacijent.getJmbg(),
pacijent.getSifra(), authorities);
return userDetails;
}
}
And my web xml file:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/dispatcher-servlet.xml</param-value>
</context-param>
org.springframework.web.context.ContextLoaderListener
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet- class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
When i start my app and go to rest method which have #PreAuthorize method i have error 500:
Request processing failed; nested exception is org.springframework.security.authentication.AuthenticationCredentialsNotFoundException: An Authentication object was not found in the SecurityContex.
i write the answer to help others.
If you have a Filter like OncePerRequestFilter where you check authentication, so when you check for authentication and it fails you can set this:
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
Otherwise if you let manage authentication to spring you can use the exception handler:
#ControllerAdvice
#RestController
public class CustomExceptionHandler extends ResponseEntityExceptionHandler {
#ExceptionHandler({AccessDeniedException.class})
public final
ResponseEntity<Object> handleUserNotFoundException(EntityNotFoundException ex, WebRequest request){
return new ResponseEntity<>("Unauthorized", HttpStatus.UNAUTHORIZED);
}
}
Try to change your configuration something like this.
.authorizeRequests()
.antMatchers(permitAllEndpointList.toArray(new String[permitAllEndpointList.size()]))
.permitAll()
.and()
.authorizeRequests()
.antMatchers(API_ROOT_URL).authenticated()
I hope this solves your issue.

Both isAnonymous() and isAuthenticated() are returning false

I have a simple page which is displays simple text depending on whether the user is logged in or not.
<sec:authorize access="isAnonymous()">
No, you failed!
</sec:authorize>
<sec:authorize access="isAuthenticated()">
yes, logged in. Well done!
</sec:authorize>
The above code displays nothing! which means both isAuthenticated() and isAnonymous() have returned false.
It is suggested here (Both isAnonymous() and isAuthenticated() return false on error page) that I must use this configuration for my filter mapping:
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<!-- apply Spring Security authentication to error-pages -->
<dispatcher>ERROR</dispatcher>
</filter-mapping>
I am not using XML, but my configuration is the same:
EnumSet<DispatcherType> dispatcherTypes = EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD);
characterEncoding.addMappingForUrlPatterns(dispatcherTypes, true, "/*");
FilterRegistration.Dynamic security = servletContext.addFilter("springSecurityFilterChain", new DelegatingFilterProxy());
security.addMappingForUrlPatterns(dispatcherTypes, true, "/*");
Why else would this happen?
Edit:
This is my security context:
#Configuration
#EnableWebSecurity
public class SecurityContext extends WebSecurityConfigurerAdapter {
#Autowired
private UserRepository userRepository;
#Override
public void configure(WebSecurity web) throws Exception {
web
//Spring Security ignores request to static resources such as CSS or JS files.
.ignoring()
.antMatchers("/static/**");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
//Configures form login
.formLogin()
.loginPage("/login")
.loginProcessingUrl("/login/authenticate")
.failureUrl("/login?error=bad_credentials")
//Configures the logout function
.and()
.logout()
.deleteCookies("JSESSIONID")
.logoutUrl("/logout")
.logoutSuccessUrl("/login")
//Configures url based authorization
.and()
.authorizeRequests()
//Anyone can access the urls
.antMatchers(
"/auth/**",
"/login",
"/signin/**",
"/signup/**",
"/user/register/**"
).permitAll()
//The rest of the our application is protected.
.antMatchers("/**").hasRole("USER")
//Adds the SocialAuthenticationFilter to Spring Security's filter chain.
.and()
.apply(new SpringSocialConfigurer());
}
/**
* Configures the authentication manager bean which processes authentication
* requests.
*/
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(userDetailsService())
.passwordEncoder(passwordEncoder());
}
/**
* This is used to hash the password of the user.
*/
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(10);
}
/**
* This bean is used to load the user specific data when social sign in
* is used.
*/
#Bean
public SocialUserDetailsService socialUserDetailsService() {
return new SimpleSocialUserDetailsService(userDetailsService());
}
/**
* This bean is load the user specific data when form login is used.
*/
#Bean
public UserDetailsService userDetailsService() {
return new RepositoryUserDetailsService(userRepository);
}
}
This the page controller:
#Controller
public class LoginController {
private static final Logger LOGGER = LoggerFactory.getLogger(LoginController.class);
protected static final String VIEW_NAME_LOGIN_PAGE = "user/login";
#RequestMapping(value = "/login", method = RequestMethod.GET)
public String showLoginPage() {
LOGGER.debug("Rendering login page.");
return VIEW_NAME_LOGIN_PAGE;
}
}
Make sure you are not bypassing security for that URL like as follows:
<http pattern="/xyz.xx" security="none" />
The ApplicationContext must contain
#ComponentScan(basePackages = {
"com.social.user.detail.service"
})
In this package I have the my user class containing the following:
public interface UserService {
public User registerNewUserAccount(RegistrationForm userAccountData) throws DuplicateEmailException;
}

Categories

Resources