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;
}
Related
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 ?
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".
I am new to the spring boot and I am creating a web application. I am bypassing "/auth/login" URL without JWT token authentication.
I have created a controller which handle the login request and give the response.
When I call my web service with URL in my local using URL
http://localhost:9505/auth/login with body param
{
"username":"abcd#g.l",
"password" : "newPassword"
}
It is working fine and does not check for the token but When I export it and create WAR file and deployed on the server then it is giving me 403 Forbidden error.
Below is URL which I use to call API after deploying on tomcat 9 server
http://localhost:9505/myapplicationame/auth/login
Can you please guide me what will be the problem?
Below is my security config method.
#Override
protected void configure(HttpSecurity http) throws Exception {
logger.info("SecurityConfig => configure : Configure in SecurityConfig");
logger.info("http Request Path : ");
logger.info("servletContext.getContextPath()) : " + servletContext.getContextPath());
http
.csrf()
.disable()
.exceptionHandling()
.authenticationEntryPoint(unauthorizedHandler)
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/",
"/favicon.ico",
"/**/*.png",
"/**/*.gif",
"/**/*.svg",
"/**/*.jpg",
"/**/*.html",
"/**/*.css",
"/**/*.js")
.permitAll()
.antMatchers("/auth/**")
.permitAll()
.antMatchers("/auth/login")
.permitAll()
.antMatchers("/permissions")
.permitAll()
.anyRequest()
.authenticated();
// Add our custom JWT security filter
http.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
}
Below is my filter class
#Configuration
#CrossOrigin
#EnableWebSecurity
#EnableMBeanExport(registration=RegistrationPolicy.IGNORE_EXISTING)
#EnableGlobalMethodSecurity(securedEnabled = true, jsr250Enabled = true, prePostEnabled = true)
#Order(SecurityProperties.IGNORED_ORDER)
public class JwtAuthenticationFilter extends OncePerRequestFilter {
#Autowired
JwtTokenProvider tokenProvider;
#Autowired
CustomUserDetailsService customUserDetailsService;
#Autowired
AdminPermissionRepository adminPermissionRepository;
#Autowired
PermissionMasterRepository permissionMasterRepository;
#Autowired
private ServletContext servletContext;
#Override
protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,
FilterChain filterChain) throws IOException, ServletException {
if (StringUtils.hasText(jwt) && isValidToken) {
// Check user email and password
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
adminDetails, null, adminDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpServletRequest));
SecurityContextHolder.getContext().setAuthentication(authentication);
logger.info("Before finish doFilterInternal");
filterChain.doFilter(httpServletRequest, httpServletResponse);
}
filterChain.doFilter(httpServletRequest, httpServletResponse);
}
/**
* To get JWT token from the request
*
* #param httpServletRequest
* #return String
*/
private String getJwtFromRequest(HttpServletRequest httpServletRequest) {
logger.info("JwtAuthenticationFilter => getJwtFromRequest");
String bearerToken = httpServletRequest.getHeader("Authorization");
if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
logger.info("Have token");
return bearerToken.substring(7, bearerToken.length());
}
logger.info("Does not have token");
return null;
}
}
Below is my controller
#RestController
#Transactional(rollbackFor=Exception.class)
public class AuthController {
#PostMapping("/auth/login")
ResponseEntity login(#Valid #RequestBody LoginRequest request)
throws DisabledException, InternalAuthenticationServiceException, BadCredentialsException {
// My logic
return ResponseEntity.ok();
}
}
The problem is with the CORS in my tomcat server.
I have commented below code and it works.
<filter>
<filter-name>CorsFilter</filter-name>
<filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
<init-param>
<param-name>cors.allowed.origins</param-name>
<param-value>http://localhost:9505, http://localhost, www.mydomain.io, http://mydomain.io, mydomain.io</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CorsFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Thanks
Try adding below mention annotations to your class.
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
#Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private ServletContext servletContext;
#Override
protected void configure(HttpSecurity http) throws Exception {
logger.info("SecurityConfig => configure : Configure in SecurityConfig");
logger.info("http Request Path : ");
logger.info("servletContext.getContextPath()) : " + servletContext.getContextPath());
http
.csrf()
.disable()
.exceptionHandling()
.authenticationEntryPoint(unauthorizedHandler)
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/",
"/favicon.ico",
"/**/*.png",
"/**/*.gif",
"/**/*.svg",
"/**/*.jpg",
"/**/*.html",
"/**/*.css",
"/**/*.js")
.permitAll()
.antMatchers("/auth/**")
.permitAll()
.antMatchers("/auth/login")
.permitAll()
.antMatchers("/permissions")
.permitAll()
.anyRequest()
.authenticated();
// Add our custom JWT security filter
http.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
}
}
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
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.