Spring Boot 403 forbidden with POST request in Tomcat 9 - java

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);
}
}

Related

Hilla Spring Security Auth LDAP

Could you help me with setup Hilla + Spring Security (LDAP)?
I have created demo project from https://hilla.dev/docs/getting-started
npx #vaadin/cli init --hilla --auth hilla-with-auth
This project has simple auth, but i would like LDAP auth.
Like in my another application without Hilla:
#Configuration
#EnableAutoConfiguration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
class WebSecurityConfig extends VaadinWebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/logout/**", "/logout-success", "/login/**", "/static/**", "/**.png").permitAll()
.anyRequest()
.authenticated()
.and()
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/grocery", true)
.failureUrl("/login?error=true")
.permitAll()
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessUrl("/login?logout=true")
.invalidateHttpSession(true)
.deleteCookies("JSESSIONID")
.permitAll()
.and()
.exceptionHandling().accessDeniedPage("/403")
.and()
.httpBasic();
http.addFilterAfter(new CsrfLoggerFilter(), CsrfFilter.class);
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder authBuilder) throws Exception {
authBuilder
.ldapAuthentication()
.userSearchFilter(new ParseConfigFile().getConf("AuthenticationManagerBuilder.userSearchFilter"))
.userSearchBase(new ParseConfigFile().getConf("AuthenticationManagerBuilder.userSearchBase"))
.groupSearchBase(new ParseConfigFile().getConf("AuthenticationManagerBuilder.groupSearchBase"))
.groupSearchFilter(new ParseConfigFile().getConf("AuthenticationManagerBuilder.groupSearchFilter"))
.contextSource()
.url(new ParseConfigFile().getConf("AuthenticationManagerBuilder.url"))
.managerDn(new ParseConfigFile().getConf("AuthenticationManagerBuilder.managerDn"))
.managerPassword(new ParseConfigFile().getConf("AuthenticationManagerBuilder.managerPassword"));
}
}
What I must change in config file for get LDAP auth?
LDAP uses a different protocol for communication. So you must have an LDAP server running first and foremost, and then use Spring Security to authenticate using what Spring Security offers.
The spring boot doc have an config file similar to what you may be looking for :Ldap Auth example

Spring security creates infinite loop of 301 and 302 redirects to login page

I have an application with Spring Boot 2.0.4.RELEASE, where some of urls are public, some others require authentication. It works fine, but when I've checked it with this tool -> https://www.redirect-checker.org/ when I'm checking my homepage or any subpage I get:
Result
https://www.myurl.com/
 302 
 https://www.myurl.com/index
 302 
 http://www.myurl.com/index
 301 Moved Permanently
 https://www.myurl.com/index
 302 
 https://www.myurl.com/index
 302 
 http://www.myurl.com/index
 301 Moved Permanently
 https://www.myurl.com/index
 302 
 https://www.myurl.com/index
 302 
 http://www.myurl.com/index
 301 Moved Permanently
 https://www.myurl.com/index
...
Here's my configuration:
#Configuration
#EnableWebSecurity
#EnableAutoConfiguration
#EnableScheduling
public class ApplicationConfig extends WebSecurityConfigurerAdapter {
private static final String[] GET_PUBLIC_URLS = {
"/",
"/resources/**",
...
};
private static final String[] POST_PUBLIC_URLS = {
"/password_reset",
...
};
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.cors().disable()
.authorizeRequests()
.antMatchers(GET, GET_PUBLIC_URLS).permitAll()
.antMatchers(POST, POST_PUBLIC_URLS).permitAll()
.anyRequest()
.authenticated()
.and()
.formLogin()
.successHandler(new AuthenticationSuccessHandler() {
#Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
//do nothing
}
})
.loginPage("/index")
.usernameParameter("email")
.defaultSuccessUrl("/user_account", true)
.and()
.logout()
.permitAll();
}
...
}
I've also added additional settings in application.config
server.tomcat.protocol-header=x-forwarded-proto
server.use-forward-headers=true
In general that's all I could find on StackOverflow to solve my problem, but I'm still having redirect problem. Am I missing something here ?
Ok,
Configuration was not correct. Here's a good one:
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.cors().disable()
.authorizeRequests()
.antMatchers(GET, GET_PUBLIC_URLS).anonymous()
.antMatchers(POST, POST_PUBLIC_URLS).anonymous()
.and()
.formLogin()
.loginPage("/index")
.usernameParameter("email")
.defaultSuccessUrl("/user_account", true)
.and()
.logout()
.permitAll();
}
The problem was that public urls are public for everyone, so .anyRequest().authenticated() was incorrect, should be anonymous() in my case.

Spring boot security JwtAuthentication and OAuth together

i was trying that jwtAuthentication works on all routes except one "/directory/auth" this one i need that works with oauth and return a jwt token but i cant get that both work together
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.csrf().disable()
.cors().configurationSource(corsConfigurationSource());
/// the route "/authenticate" is my jwtAuthentication and "/directory/auth" is my oauth
httpSecurity.authorizeRequests()
.antMatchers("/authenticate",
"/directory/auth").permitAll().
anyRequest().authenticated().and()
.exceptionHandling()
.authenticationEntryPoint(jwtAuthenticationEntryPoint)
.and().sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
// trying to set oauth on one route
.authorizeRequests()
.antMatchers("/directory/auth").authenticated().and()
.oauth2Login()
.userInfoEndpoint()
.oidcUserService(oidcUserService);
//others filters
httpSecurity.addFilterBefore(decryptInterceptor, UsernamePasswordAuthenticationFilter.class);
httpSecurity.addFilterAfter(encryptInterceptor, UsernamePasswordAuthenticationFilter.class);
httpSecurity.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
}
}
Thanks

How to assign auth success handler to multiple spring security realms

I have the following Spring security configuration class for two separate security realms, the admin area and the frontend area:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled=true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private CustomUserDetailsServiceImpl userDetailsService;
#Configuration
#Order(1)
public static class AdminAreaConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
private AuthSuccessAdmin authSuccessAdmin;
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.requestMatcher(new AntPathRequestMatcher("/admin/**"))
.csrf().disable()
.authorizeRequests()
.antMatchers("/admin/login/login.html").permitAll()
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/admin/login.html")
.permitAll()
.successHandler(authSuccessAdmin)
.and()
.logout()
.permitAll();
}
}
#Configuration
#Order(2)
public static class UserAreaConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
private AuthSuccessFrontend authSuccessFrontend;
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.requestMatcher(new AntPathRequestMatcher("/**"))
.csrf().disable()
.authorizeRequests()
.antMatchers("/about", "/register").permitAll()
.antMatchers("/**").hasRole("USER")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.successHandler(authSuccessFrontend)
.and()
.logout()
.permitAll();
}
}
}
When the app is started, the authentication success handler of the admin area is overwritten by the authentication handler of the frontend area, which is loaded after the first. This results in a wrong redirect when logging into the admin area (redirects to url defined in the frontend auth success handler). How can I assign disctinct handlers to the separate configurations?
The issue seems to be in RequestMatcher pattern.
Your USER app has the RequestMatcher pattern '/**'(means anything after / which will include path /admin as well) which will override your ADMIN RequestMatcher pattern /admin/**
Change the user RequestMatcher to /user/**

custom 403 error page with spring security configured via java code

Anyone knows how to configure a customized 403 page in spring security? Looking in the web, all the results I get it's with XML configuration, and I am using Java configuration. That's my SecurityConfig:
#Configuration
#ComponentScan(value="com")
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return new CustomAuthenticationManager();
}
protected void configure(HttpSecurity http) throws Exception {
http
.csrf()
.disable()
.authorizeRequests()
.antMatchers("/resources/**", "/publico/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/acesso/login").permitAll()
.loginProcessingUrl("/login").permitAll()
.usernameParameter("login")
.passwordParameter("senha")
.successHandler(new CustomAuthenticationSuccessHandler())
.failureHandler(new CustomAuthenticationFailureHandler())
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessUrl("/acesso/login").permitAll();
}
}
I have a custom implementation for AccessDeniedHandler too:
public class CustomAccessDeniedHandler implements AccessDeniedHandler {
#Override
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException arg2) throws IOException, ServletException {
response.sendRedirect(request.getContextPath() + "/erro/no_permit");
}
}
If I'm right, to personalize the page 403, you could use the model implemented by this server.
Spring Security : Customize 403 Access Denied Page
Example:
AppConfig.java
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/resources/**", "/signup").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.exceptionHandling().accessDeniedPage("/403")
.and()
.logout().logoutUrl("/logout").logoutSuccessUrl("/")
.and()
.rememberMe()
.and()
.csrf().disable();
}
HomeController.java
#RequestMapping("/403")
public String accessDenied() {
return "errors/403";
}
And the .html, would be a custom page with some message 403.

Categories

Resources