Redirect to HTTPS fails Spring Security - spring

I got the following setup for my security:
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/admin/**", "/registration/**").access("hasRole('ROLE_USER') or hasRole('ROLE_ADMIN')")
.anyRequest().permitAll()
.and()
.requiresChannel().anyRequest().requiresSecure()
.and()
.exceptionHandling().accessDeniedPage("/denied")
.and()
.formLogin()
.loginPage("/login")
.failureUrl("/error-login");
}
Now problem is when i deploy it on production server when i try open demo.com or http://demo.com or combination of such, i get too many redirects and it fails.
On Chrome: ERR_TOO_MANY_REDIRECTS
On Firefox: The page isn't redirecting properly
In other words it redirects until it fails.
Any advice on what could be wrong here or what i could do to figure out the problem?
EDIT 1:
Controller request
#Controller
public class BaseController {
#RequestMapping(value = {"/", "/index"})
public String home() {
return "index";
}
}
Log: No entries (other than standard bootup sequence)

You have to specify port mapping in your WebSecurityConfigurer with the corresponding HTTP and HTTPS ports of your application:
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/admin/**", "/registration/**").access("hasRole('ROLE_USER') or hasRole('ROLE_ADMIN')")
.anyRequest().permitAll()
.and()
.requiresChannel().anyRequest().requiresSecure()
.and()
.portMapper()
.http(8080).mapsTo(8443);
.and()
.exceptionHandling().accessDeniedPage("/denied")
.and()
.formLogin()
.loginPage("/login")
.failureUrl("/error-login");
}
http.portMapper().http(8080).mapsTo(8443) maps your HTTP 8080 port to HTTPS 8443 port to correctly perform the redirect.
Read more:
https://myshittycode.com/2014/06/12/spring-security-forcing-urls-to-use-https/
http://www.rmarcello.it/spring-security-aumomatic-redirect-on-https/

Related

How to throw user to a page other than /login if user is not authenticated in spring security

I wanted to throw users out on signup page instead of login page when they are not authenticated. One workaroud I did was to pass "/signup" in .loginPage() function in Security configuration of spring boot application.
But now I also need to put a .rememberMe() feature for login page. because of that I have to pass "/login" in .loginPage(). So that I can add .rememberMe() functionality.
To summarize, How can I throw non-authenticated users to /signup page as well as keeping the rememberMe functionality on login page?
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/game*/**").authenticated()
.antMatchers("/contest*/**").authenticated()
.antMatchers("/badges_awards").authenticated()
.antMatchers("/admin*/**").hasRole("ADMIN")
.and()
.formLogin()
.loginPage("/login")
.usernameParameter("emailAddress")
.passwordParameter("password")
.permitAll()
.and()
.rememberMe()
.key("remember-me")
.rememberMeParameter("remember-me")
.rememberMeCookieName("rememberlogin")
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessUrl("/")
.permitAll();
http.csrf().disable();
http.headers().frameOptions().disable();
}
Start your configuration like this to tell Spring Security that /signup URL does not need authentication and therefore won't be redirect to your login page :
http.authorizeRequests()
.antMatchers("/signup").permitAll()
try this
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/login.html").permitAll()
.antMatchers("/signup*/**").permitAll()
.and()
.formLogin()
.loginPage("/login")
.failureHandler(LoginAuthFailureHandler)
.and()
.exceptionHandling()
.accessDeniedPage("/signup.html");
}
#Component
public class LoginAuthFailureHandler extends SimpleUrlAuthenticationFailureHandler {
#Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception) throws IOException, ServletException {
getRedirectStrategy().sendRedirect(request, response, "/signup.html");
}
}

Why the character ';' is added the end of request in OAuth2

There are Authorization Server(UAA) and Resource Server and Gateway applications that have been working correctly. The scenario for authentication is authorization_code. In the first time after authentication, the end of request is added ;jesessionid=[value], so its result is exception from HttpFirewall of Gateway application, because of having ';' in the request.
My question is that what is it and why jessionid is added the end of request? and how is it adaptable with HttpFirewall.
I have found a way around but I know it has some risks. It is like this:
#Bean
public HttpFirewall allowUrlEncodedSlashHttpFirwall() {
StrictHttpFirewall firewall = new StrictHttpFirewall();
firewall.setAllowSemicolon(true);
return firewall;
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf()
.disable()
.headers().cacheControl().disable()
.and()
.headers()
.cacheControl()
.disable()
.frameOptions()
.sameOrigin()
.and()
.httpBasic().disable()
.authorizeRequests()
.requestMatchers(EndpointRequest.toAnyEndpoint()).permitAll()
.requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()
.mvcMatchers("/uaa/**", "/login**", "/favicon.ico", "/error**").permitAll()
.anyRequest().authenticated()
.and()
.logout()
.permitAll();
}
#Override
public void configure(WebSecurity web) throws Exception {
super.configure(web);
web.httpFirewall(allowUrlEncodedSlashHttpFirwall());
}
As above configuration, the ; is skipped but it is not right and it has some risks.
What is the correct way and config to solve this problem?

How to log out sucessfully

My login page is http://localhost:8080/nradmin/welcome
and my home page (after successful log in) is http://localhost:8080/nradmin/home
I'd like to log out and not anymore be able anymore to access any other page like the home page but only the welcome (login) page. If I type http://localhost:8080/nradmin/home on the browser after logout I continue to have access to the home page without logging in.
I've implemented the following methods overriden from the abstract class WebSecurityConfigurerAdapter:
#Override
protected void configure(HttpSecurity http) throws Exception { http
.authorizeRequests()
.antMatchers("/welcome").permitAll()
.antMatchers("/home", "/account/**", "/price/**").hasRole("ADMIN")
.antMatchers("/home", "/account/**", "/price/**").access("hasRole('ROLE_ADMIN')")
.anyRequest()
.authenticated()
.and()
.formLogin()
.loginPage("/welcome")
.defaultSuccessUrl("/home")
.and()
.logout()
.invalidateHttpSession(true)
.clearAuthentication(true)
.logoutSuccessUrl("/welcome")
.logoutUrl("/welcome")
.deleteCookies()
.permitAll()
.and()
.exceptionHandling()
.accessDeniedPage("/welcome")
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);
}
#Override
protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication() .withUser("username").password(passwordEncoder().encode("12345")).roles(LoginDataConstants.ROLE_ADMIN)
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
Does anyone have an idea how to do it?
I guess it may be due to having the same url in the methods logoutUrl and logoutSuccessUrl.
I suggest you to change logoutUrl to other path, for example just /logout and then try to perform the logout hitting that url. It should complete the logout task and the redirect to the logoutSuccessUrl, which is /welcome
Add CSRF
Reference from spring docs.
Will perform logout with the URL /logout is requested with any HTTP method
#Override protected void configure(HttpSecurity http) throws Exception {
http.
logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout"));
}
}
You can also reference a good example on stack overflow using this same method here
When I had this issue I used this line
.logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout")).logoutSuccessUrl("/login");
Where
.logoutSuccessUrl("/login") was the page the user will be redirected to.
You could re-factor your code to something like this
#Override
protected void configure(HttpSecurity http) throws Exception { http
.authorizeRequests()
.antMatchers("/welcome").permitAll()
.antMatchers("/home", "/account/**", "/price/**").hasRole("ADMIN")
.antMatchers("/home", "/account/**", "/price/**").access("hasRole('ROLE_ADMIN')")
.anyRequest()
.authenticated()
.and()
.formLogin()
.loginPage("/welcome")
.defaultSuccessUrl("/home")
.and()
.logout()
.and() // This section is re-factored.
.logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/welcome").deleteCookies("JSESSIONID") //Or try .logoutSuccessUrl("/nradmin/welcome")
.invalidateHttpSession(true)
.permitAll()
.and()
.exceptionHandling()
.accessDeniedPage("/welcome")
.and()
.sessionManagement()
.sessio hinCreationPolicy(SessionCreationPolicy.IF_REQUIRED);
Update : This is a modified version. This is essentially what I use in my project except for this portion:
.and()
.exceptionHandling()
.accessDeniedPage("/welcome")
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);
So, I believe it should work; otherwise, I believe it may be a setup issue/configuration that resides somewhere else in your project. Please try the below example.
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/nradmin/welcome", "/home", "/account/**", "/price/**").hasRole("ADMIN")
.anyRequest().permitAll()
.and()
.formLogin()
.loginPage("/nradmin/welcome")
.permitAll()
.and()
.logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/nradmin/welcome").deleteCookies("JSESSIONID")
.invalidateHttpSession(true)
.permitAll()
.and()
.exceptionHandling()
.accessDeniedPage("/nradmin/welcome")
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);
}

Spring Security. Any request needs to be authorized and a special POST request needs an admin role. How to do this?

I want to secure my HATEOAS REST API build with Spring. All requests should need authorization and POST requests to "/rooms" should need the admin role. My WebSecurityConfigurerAdapter implementation code looks like this right now:
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
// Todo: Make sure that all resources need to be authenticated and POST rooms needs ADMIN role
.anyRequest().authenticated()
.antMatchers(HttpMethod.POST, "/api/v1/rooms").hasRole("ADMIN")
.and()
.httpBasic()
.and()
.csrf().disable();
}
Right now all resources only need authentication if I put the "anyRequest().authenticated()" line before the "antMatchers..." line, but then the needed "ADMIN" role doesn't work or get applied and vice versa.
How am I to get both things working at the same time?
Kind Regards,
Florian
Securityconfiguration.java
#Override
protected void configure(HttpSecurity http) throws Exception {
http.httpBasic().and().authorizeRequests().antMatchers("/public/**")
.permitAll().antMatchers("/sa/**").hasAuthority("sa")
.antMatchers("/admin/**").hasAuthority("admin")
.and().logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/index.html").and()
.addFilterAfter(new CsrfHeaderFilter(), CsrfFilter.class)
.csrf().disable();
}
And in the rest controller use..
#RequestMapping("/admin/adduser")
public void addUser(#RequestBody User user) {
authService.addUser(user);
}
The following code did it for me:
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers(HttpMethod.POST, "/api/v1/rooms").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.httpBasic()
.and()
.csrf().disable();
}
}
Thank you for the response Pankaj.

Match everything but some specific path with Java configuration - antMatchers

Base on this Answer, I'm trying to secure everything but the login page in my spring app.
So I'm using this Java configuration files for OAuth2
The extends for the ResourceServerConfigurerAdapter:
#Override
public void configure(final HttpSecurity http) throws Exception {
http
.requestMatchers()
.antMatchers("/**")
.and()
.authorizeRequests()
.anyRequest()
.authenticated()
.antMatchers("/login")
.permitAll()
The extends for OAuth2SsoConfigurerAdapter {
#Override
public void match(RequestMatchers matchers) {
matchers.antMatchers("/login");
}
#Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest()
.authenticated()
}
So, what I looking for is to have a http 401 for every request but for /login.
If a login request is perform the #EnableOAuth2Sso annotation would be used to redirect it to the OAuth2 server.
Update 1
After changing the order of the filter ResourceServerConfigurerAdapter, the /login request is not found.
http
.requestMatchers()
.antMatchers("/**")
.and()
.authorizeRequests()
.antMatchers("/login")
.permitAll()
.anyRequest()
.authenticated()
This request would be Unauthorized because any token is provided
~/ http 401 Unauthorized (good)
~/resource http 401 Unauthorized (good)
But the login page is not found:
~/login http 404 Not Found (bad)
The correct functionality should be a http 302 redirection to the OAuth2 server when the ~/login is hit.

Resources