Spring Boot 2 Security downloading font file upon login - spring-boot

I've setup a spring boot 2 application with a login form, however, when you login, instead of redirecting to /admin like it's supposed to, it downloads a font file referenced by the stylesheet via an #import.
Here is my security setup;
#Configuration
#EnableWebSecurity()
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
UserService userService;
#Bean
public PasswordEncoder passwordEncoder() {
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userService).passwordEncoder(passwordEncoder());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
// These pages don't require the user to be logged in
http.authorizeRequests()
.antMatchers("/", "/login", "/logout", "/report/**").permitAll()
.requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()
.anyRequest().authenticated();
// When the user has logged in as XX.
// But access a page that requires role YY,
// AccessDeniedException will be thrown.
http.authorizeRequests().and().exceptionHandling().accessDeniedPage("/403");
// Config for Login Form
http.authorizeRequests().and().formLogin()//
// Submit URL of login page.
.loginProcessingUrl("/j_spring_security_check") // Submit URL
.loginPage("/login")//
.defaultSuccessUrl("/admin")//
.failureUrl("/login?error=true")//
.usernameParameter("username")//
.passwordParameter("password")
// Config for Logout Page
.and().logout().logoutUrl("/logout").logoutSuccessUrl("/login?logout=true");
}
}
Where am I going wrong? From what I can see, I'm enabling access to Spring resources that are stored in the static folder.

I figured this one out, I read the code that allows access to resources and noticed it said 'atCommonLocations', and guess this adds access to folders such as css, js, img, images etc. I had fonts in a folder labelled webfonts, so I updated my security configuration;
http.authorizeRequests()
.antMatchers("/", "/login", "/logout", "/report/**", "/webfonts/**").permitAll()
.requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()
.anyRequest().authenticated();

Related

Spring security - Specific session creation policy per matchers

I'm trying to implement SessionCreationPolicy.ALWAYS for the /testMVCController/** endpoint and SessionCreationPolicy.STATELESS for rest of endpoints (/**).
Expected scenario:
When accessing to /testMVCController/displayUsers the user logs in once and the log I have implemented in UserDetailsService logs the authorities associated to that user.
After that, all the requests to /testMVCController/displayUsers or other URL under /testMVCController/** will not log the authorities again because the session creation policy is always and the user is already logged in.
This works when I don't specify the 2nd security configuration (X509ClientSessionCreationPolicyStateless) but when I add it, all the requests become session stateless.
It is not working with the current security configuration because after I log in with my client certificate, at any request executed under /testMVCController/** endpoint (e.g. /testMVCController/displayUsers), the authenticationUserDetailsService is consulted and the list of authorities is logged for each file request the browser makes (.js file, .css files, ...), even after the initial login.
So, if there are 3 requests (/testMVCController/displayUsers, displayUsers.js, displayUsers.css) the list of authorities log present in authenticationUserDetailsService is logged 3 times.
I configured SecurityConfiguration as shown below but it is not working:
#Configuration
#EnableGlobalMethodSecurity(prePostEnabled = true)
#EnableWebSecurity
public class SecurityConfiguration {
#Configuration
#Order(1)
public static class X509ClientSessionCreationPolicyAlways extends WebSecurityConfigurerAdapter {
#Autowired
private X509CUDService x509CUDService;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/testMVCController/**")
.csrf().disable()
.authorizeRequests()
.anyRequest().authenticated()
.and()
.x509()
.authenticationUserDetailsService(x509CUDService)
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.ALWAYS);
}
}
#Configuration
#Order(2)
public static class X509ClientSessionCreationPolicyStateless extends WebSecurityConfigurerAdapter {
#Autowired
private X509CUDService X509CUDService ;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/**")
.csrf().disable()
.authorizeRequests()
.anyRequest().authenticated()
.and()
.x509()
.authenticationUserDetailsService(X509CUDService);
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
}
I've searched this issue and I found various links (e.g. Spring session creation policy per-request?, Spring Session: How to create separate session management policies for different URLs and Multiple HttpSecurity) but none of them worked.
Thanks in advance!
I was missing some details on my configuration. I was catching all the requests to /testMVCController/** and that was working, but in addition to catch the requests to any endpoint of the type /testMVCController/** (e.g.: /testMVCController/usersList), I also have to catch the requests that these pages make to get their scripts (.js files, .css files, .png files).
What was happening was: the request to /testMVCController/usersList), was configured with SessionCreationPolicy.ALWAYS, but the subsequent requests such as usersList.js, usersList.css, etc were configured with SessionCreationPolicy.STATELESS, and in these cases the X509CustomUserDetailsService was always consulted.
Example:
GET request to /testMVCController/usersList works, but there also requests in this usersList page to usersList.js, usersList.css, etc.
So, once I included these resource paths in the antMatchers all worked perfectly.

Spring security - Simple Multi Security now working [duplicate]

This question already has answers here:
Spring Security : Multiple HTTP Config not working
(2 answers)
Closed 1 year ago.
I am dealing with this, since 7 hours ago ,and I cant find an explanation, for simplicity, I just did the example a little smaller.
I need some URLs with security access (JWT), and other path (dashboard) with a form login.
This is my code:
#EnableWebSecurity
public class MultiHttpSecurityConfig {
#Autowired
private UserDetailsService jwtUserDetailsService;
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(jwtUserDetailsService)
.passwordEncoder(passwordEncoder());
}
#Bean
public PasswordEncoder passwordEncoder() {
return NoOpPasswordEncoder.getInstance();
}
#Configuration
#Order(1)
public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
#Autowired
private JwtRequestFilter jwtRequestFilter;
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
// Get Request and /Authenticate do not need authentication
.authorizeRequests()
.antMatchers("/authenticate", "/authenticate/**").permitAll()
.antMatchers(HttpMethod.GET, "/api/**").permitAll()
// all others do need authentication
.anyRequest().authenticated()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
}
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
#Configuration
public static class FormLoginWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/dashboard/index.html").authenticated()
.and()
.formLogin();
}
}
This example is working, the JWT mechanism works great.
The only thing it does not work, is the form login. When I hit the browser localhost:8080/dashboard/index.html, the file appears.
This is what I need:
/authorize --> Anyone can hit that URL to get the JWT token
/api --> Get methods do not need authorization
/api --> All others verbs, do need a token.
/dashboard/index.html --> A form login should appear.
I know that anyRequest().authenticated(), it is in the first configuration but if I even comment that line, the second Order is totally ignored.
What should I add or remove to accomplish my idea?
In your FormLoginWebSecurityConfigurerAdapter, the antMatchers() should be called before authorizeRequests() - this indicate that this filter chain only apply request to /dashboard/index.html.
http.antMatcher("/dashboard/index.html")
.authorizeRequests()
.anyRequest().authenticated() // since this filter chain only apply to /dashboard/index.html, don't need use antMatchers() to check again
.and()
.formLogin();
For more info: https://docs.spring.io/spring-security/site/docs/current/reference/html5/#multiple-httpsecurity
The second issue is that the Order of yourFormLoginWebSecurityConfigurerAdapter must be before (less than) ApiWebSecurityConfigurationAdapter. WebSecurityConfigurerAdapter has a default #Order of 100, so you should annotate #Order(0) on your FormLoginWebSecurityConfigurerAdapter.

Spring Security redirecting custom login page to itself - Too Many Redirects

I'm currently developing a custom login-page for my Spring Boot Application but I just can't get it to work. Using the default one works fine but as soon as I try to use my custom file, it just repeatedly redirects me until my Browser give up.
Other posts suggest permitting access to the login-path to erveryone but this also doesn't seem to work.
Here is my code:
WebSecurityConfig
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
}
And Controller for login-page
#Controller
public class WebController {
#GetMapping("/login")
public String login () {
return "login";
}
}
Any ideas what I'm missing?
You are probably using a lot of CSS and JS file link links, according to your code Spring Boot must first authenticate all the links, which is why it redirects to your login page many times.
add following code to bypass security authentication of resource link
public void configure(WebSecurity web) {
web.ignoring()
.antMatchers("/bower_components/**", "/dist/**", "/plugins/**"); //write your resource directory name
}

Spring Security - Redirect to custom login page without going through controller

I am currently using Spring Boot + Spring Security to develop a simple website that need user to login to access it. I have created my own custom static login page under resources/templates1/bruceLogin1.html. Any unathenticated access to my website to first be redirected to the login page URL which is http://localhost:8080/templates1/bruceLogin1.html
Note: that I am NOT creating any controller for this login URL, hence I am expecting the bruceLogin1.html to be accessed directly bypassing controller. Because i directly allow access to this html page without going thru controller, I assume no view resolver (e.g thymleaf) is required.
I open my browser, and enter http://localhost:8080/blablabl, and browser redirect me to http://localhost:8080/templates1/bruceLogin1.html , but sadly, i got error
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Sat Jan 11 12:40:37 SGT 2020
There was an unexpected error (type=Not Found, status=404).
No message available
Below is my configuration,
#SpringBootApplication
#EnableWebSecurity
public class SpringSecurityCatalogApplication implements WebMvcConfigurer {
public static void main(String[] args) {
SpringApplication.run(SpringSecurityCatalogApplication.class, args);
}
#EnableWebSecurity
#Order(Ordered.HIGHEST_PRECEDENCE)
class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/resources/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/templates1/bruceLogin1.html")
.permitAll();
}
}
}
Think instead of putting under resources/template1 folder, i will just put the custom login page into either resources/static or resources/public folder.
Then configure as shown below
#EnableWebSecurity
#Order(Ordered.HIGHEST_PRECEDENCE)
class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/resources/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/bruceLogin1.html")
.permitAll();
}
}
Open browser and access any URL, you will be redirected to http://localhost:8080/bruceLogin1.html. And thats it!
Note that this does not require any controller nor view resolver.

Custom login page in Spring Security 5 using oauth2 returns null

I am developing custom login page in Spring Security 5 using oauth2. So I have customized settings:
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests().antMatchers("/").permitAll()
.anyRequest().authenticated()
.and()
.oauth2Login().loginPage("/login/oauth2").permitAll();
}
and creating controller with #RequestMapping("/login/oauth2"):
#GetMapping("/")
public String index() {
return "index";
}
#GetMapping("/login/oauth2")
public String login(Model model, OAuth2AuthenticationToken authentication) {
return "login";
}
The login.html page is a regular form which redirect to login method from controller:
<h1>Logowanie</h1>
<a>ZALOGUJ</a>
<a class="btn" href="/login/oauth2/code/google">Login</a>
With this configuration OAuth2AuthenticationToken authentication is null and therefore authentication can't be applied. With default Spring Security 5 configuration everything works fine. The example on which I based is described here: https://docs.spring.io/spring-security/site/docs/5.0.0.RELEASE/reference/htmlsingle/#oauth2login-advanced-login-page; section 31.1 OAuth 2.0 Login Page.
In my app to work I had to create my custom WebMvc configuration:
#Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login").setViewName("login");
registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
}
}
Then in WebSecurityConfig:
#Override
protected void configure(final HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/login").permitAll()
.anyRequest().authenticated()
.and().formLogin()
.loginPage("/login")
.permitAll()
.and().csrf().disable()
.logout().permitAll();
}
I think in this case You don't need custom controller.
I wrote a blog post about silent token refresh in implicit flow, but there You will find full working app with custom login page:
https://regulargeek.blogspot.com/2018/05/angular-5-springboot-2-oauth2-and.html

Resources