I just created a new Spring Boot application with the following web security config (using spring-security-config:6.0.0):
#Configuration
#EnableWebSecurity
public class WebSecurityConfig {
#Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests((requests) -> requests
.requestMatchers("/", "/login", "/info/**").permitAll()
.anyRequest()
.authenticated()
)
.formLogin((form) -> form
.loginPage("/login")
.permitAll()
)
.logout(LogoutConfigurer::permitAll);
return http.build();
}
}
When trying to access any url I get redirected to /login with ERR_TOO_MANY_REDIRECTS. Something seems to be wrong with my SecurityConfig.
In previous versions I always used http.authorizeHttpRequests().antMatchers("/") instead of requestMatchers but it seems like they removed it.
Does requestMatchers() do the same thing or how can I configure url patterns that don't require login?
Related
When I launch my webapp I want spring to redirect to my login.jsp in order to authenticate before it goes to my home.jsp but when the app starts it immediately goes to my home.jsp. I created this SecurityFilterChain which I had thought would default to my login.jsp for authentication.
#Configuration
public class SecurityConfiguration {
#Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/login", "/register").permitAll()
.and()
.formLogin()
.loginPage("/login").permitAll();
return http.build();
}
}
If more information is needed please let me know.
Edit
As pointed out by jzheaux down below. The naming convention of the method doesn’t matter. The fix was adding the .anyRequest().authenticated() which makes sure any other page besides the ones I had specified above it require authentication before you’re able to go to them.
I found what was wrong. I was using filterChain rather than the securityFilterChain. I also modified the method a little bit as shown here
#Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests((requests) -> requests
.antMatchers("/login", "/register").permitAll()
.anyRequest().authenticated()
)
.formLogin((form) -> form
.loginPage("/login")
.loginProcessingUrl("/submit-login")
.permitAll()
)
.logout(LogoutConfigurer::permitAll);
return http.build();
}
Once making these changes the app defaulted to opening up my login.jsp for authentication before continuing on. Thank you all for the help.
I want to work with Spotify Web API, but I'm having trouble with Spring Security Configuration. Here are my security dependencies:
/* springBootVersion = '2.1.2.RELEASE' */
implementation "org.springframework.security:spring-security-oauth2-client"
implementation 'org.springframework.security:spring-security-oauth2-jose:5.1.6.RELEASE'
implementation "org.springframework.security.oauth.boot:spring-security-oauth2-autoconfigure:2.1.7.RELEASE"
And here's my security in my application.yml file:
spring:
security:
oauth2:
client:
registration:
spotify:
provider: spotify-provider
client-id: <client-id>
client-secret: <client-secret>
client-authentication-method: basic
authorization-grant-type: authorization_code
redirect-uri: http://localhost:8080/
scope: <comma delimited scopes>
provider:
spotify-provider:
authorization-uri: https://accounts.spotify.com/authorize
token-uri: https://accounts.spotify.com/api/token
user-info-uri: https://api.spotify.com/v1/me
My issue is that after I login and get redirected back to my application, it gets stuck on the URL http://localhost:8080/oauth2/authorization/spotify with the error
localhost redirected you too many times.
Here's what my java security configuration looks like:
#Configuration
public class SpotifySecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.oauth2Login();
}
}
The Redirect Loop was because the /oauth2/authorization/ endpoint was secured, thus it was triggering going back to the Web API for an access token.
I've updated my configuration to this:
#Configuration
public class SpotifySecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/home", "/login**","/callback/", "/webjars/**", "/error**", "/oauth2/authorization/**")
.permitAll()
.anyRequest()
.authenticated()
.and()
.oauth2Login();
}
}
The second issue was that the redirect-uri is the URI that the Web API will send the access token to Spring to be used to get the refresh token. I thought it was for a successful login. Spring already has an implementation for handling refresh tokens, but I did not know what endpoint it should use. For some reason, the redirect-uri cannot be blank, there is no default, I would get this error:
IllegalArgumentException: redirectUriTemplate cannot be empty
To use Spring's refresh token implementation I needed to set the redirect-uri to this:
redirect-uri: '{baseUrl}/login/oauth2/code/{registrationId}'
redirect-uri-template is an alias for redirect-uri (they're the same variable).
I found the redirect-uri in another stackoverflow post:
authorizationGrantType cannot be null in Spring Security 5 OAuth Client and Spring Boot 2.0
Try to add the #EnableOAuth2Sso annotation :
#Configuration
#EnableOAuth2Sso
public class SpotifySecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.oauth2Login();
}
}
I'm working with Spring Boot 1.4.2.RELEASE, Spring Security 4.1.3.RELEASE, and Java 8.
For the security configuration I have the following class:
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/assets/**", "/logout", "/login");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.sessionManagement() // 1
.sessionFixation() // 2
.migrateSession() // 3
.maximumSessions(1) // 4
.maxSessionsPreventsLogin(true).expiredUrl("/login").and() // 5
.invalidSessionUrl("/login") // 6
.and() // 7
.authorizeRequests()
.antMatchers("/app/**").authenticated()
.antMatchers("/about").permitAll()
.anyRequest().authenticated().and()
.formLogin()
.loginPage("/login").permitAll()
.loginProcessingUrl("/auth").permitAll()
.defaultSuccessUrl("/app/index", true)
.failureUrl("/login?error")
.usernameParameter("uid")
.passwordParameter("pwd").and()
.logout()
.permitAll()
.invalidateHttpSession(true)
.logoutUrl("/logout").permitAll()
.logoutSuccessUrl("/login").permitAll()
.clearAuthentication(true).and()
.exceptionHandling().and()
.csrf().disable()
.headers().frameOptions().disable()
.cacheControl().and();
}
}
When try access to "/about" (permit all everyone), redirects me to "/login". I try it a second time and now it allows me to access "/about".
I have changed the authorization order of requests in the configuration class but don't works. When I delete the lines of sessionManagement (1 to 7), everything works normally.
Do I need any extra configuration?
When you are testing this, did you clear your browser's cookie with regard to your testing site? The session management filter sets a jsessionid cookie, which gets sent back. Your browser has no idea that you reset your server, so thinks the cookie is just fine, and you send back an invalid session.
You may want to take a look at your session creation policies to see whether or not it suits your purpose.
In my Spring Boot application, I configure Spring Security as
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests()
.antMatchers("/css/**", "/js/**", "/images/**", "**/index.html").permitAll()
.antMatchers("/**.html").permitAll()
.antMatchers(HttpMethod.POST, "/login").permitAll()
.anyRequest().authenticated()
.and()
.addFilterBefore(new LoginFilter("/login"), BasicAuthenticationFilter.class)
.addFilterBefore(new TokenFilter(), BasicAuthenticationFilter.class);
}
}
I have index.html under resources/static/index.html. This stopped serving after I enabled security. What am I missing?
If I go back when I do not have any security, I get my HTML rendered on server.
try to change to /**/index.html. For Ant path matcher
? matches one character
* matches zero or more characters
** matches zero or more directories in a path
{spring:[a-z]+} matches the regexp [a-z]+ as a path variable named "spring"
I have created a Spring Boot app and I have my front-end app in the /resources/static folder.
For the routing, I am using Angular JS UI Router library.
I have defined a route, which I only want to be accessed by the admin and now I am trying to secure it using Spring Security.
Here is my WebSecurity Configuration class:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER").and()
.withUser("admin").password("password").roles("USER", "ADMIN");
}
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.authorizeRequests()
.antMatchers(HttpMethod.GET, "/#/admin").hasRole("ADMIN")
.and()
.formLogin()
.and()
.authorizeRequests()
.antMatchers(HttpMethod.POST, "/member", "/member/**").permitAll()
.antMatchers(
HttpMethod.GET,
"/",
"/*.html",
"/favicon.ico",
"/**/*.html",
"/**/*.css",
"/**/*.js",
"/**/**/*.css",
"/**/**/*.js",
"/**/**/*.html",
"/**/**/**/*.css",
"/**/**/**/*.js",
"/**/**/**/*.html",
"/**/**/**/**/*.css",
"/**/**/**/**/*.js"
).permitAll()
.antMatchers("/auth/**", "/member/**", "/account/**").permitAll()
.and()
.csrf().disable();
}
}
The route I am trying to secure can be accessed through http://localhost:8080/#/admin.
However, whenever I am accessing that route, no login is requested and the page can be viewed by anyone.
Is it there another approach I should follow?
The URL: http://localhost:8080/#/admin is mapped to / in your permitAll list instead of the /#/admin rule, since #/admin part is just URL fragment, and usually not the business of the server side.
You have to define an API between your frontend and backend. Usually in RESTful web services form, and serve at /api/* path. Secure the path, and let your frontend talk to your backend through those APIs only.
It is eaiser to fix your issue,
Update
.antMatchers(HttpMethod.GET, "/#/admin").hasRole("ADMIN")
To
.antMatchers(HttpMethod.GET, "/#/admin").hasRole("ADMIN").anyRequest().authenticated()
For every matchers, you always need with permitAll() or authenticated() for it.