How do i allow access certain request path to every user so that he/she can register user in spring security 6? - spring-boot

In spring security 5.7.5, I had the following security filter chain that allows unauthenticated users to easily register accounts.
Code in spring Security 5.7.5
#Bean
public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests(
authorize ->
authorize
.mvcMatchers("/user/**").permitAll()
.mvcMatchers("/**").authenticated()
).formLogin(Customizer.withDefaults());
return http.build();
But now, The previous way code is not working. How should I configure a filter chain that allows anyone to register accounts?
Present Code
#EnableWebSecurity
public class SecurityConfig {
#Bean
#Order(1)
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);
http.getConfigurer(OAuth2AuthorizationServerConfigurer.class)
.oidc(Customizer.withDefaults());
//when unauthenticated user tries to login the resource server
// redirect him/her to login page
http
.exceptionHandling(
exception ->
exception.authenticationEntryPoint(
new LoginUrlAuthenticationEntryPoint("/login")
)
);
return http.build();
}
#Bean
#Order(2)
public SecurityFilterChain appSecurityFilterChain(HttpSecurity http) throws Exception {
return http
.csrf().disable()
.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.disable()
.authorizeHttpRequests(
authorize ->
authorize
.requestMatchers("/user/registerUser",
"/user/getAllUser").permitAll()
.anyRequest().authenticated()
)
.formLogin(Customizer.withDefaults())
.build();
}
}
I'm getting 401 unauthorized in postman when i request for /user/registerUser and /user/getAllUser url. What i'm trying is, registering user account by unauthenticated users. I belive my security filter chain is sending me to /login page to authenticate which i don't want for register url.

Related

How to request authentication to all routes except welcome which has to be the login page in Spring Boot

I want to request authentication to all available routes except one "/welcome" which has to be the login page too!
I'm using Spring Boot Security and my SecurityFilterChain is coded like this:
#Configuration
public class AppConfig {
#Bean
SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeHttpRequests()
.requestMatchers("/welcome").permitAll()
.requestMatchers("/**").authenticated()
.and().formLogin().loginPage("/welcome")
.and().httpBasic();
return http.build();
}
#Bean
PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
I want the user to be redirected to the welcome url/page when not authenticated. And when authenticated to be redirected to the root "/". However with this configuration the server keeps telling me ERR_TOO_MANY_REDIRECTS
Where am I doing wrong?
How to allow public access only to the "/welcome" url and not the rest?

Spring Security 6 configuration with multiple security configs

I'm trying to setup my Spring Boot 3.0 / Spring Security 6 app with multiple security configs.
only /oauth/token should use/allow/enforce basic auth
all other endpoints will use/allow/enforce bearer auth
The issue I'm running into is that if I send a GET request to /test with the header Authorization: Basic xxx the basic auth filter is still picking it up.
This is what I have so far. The bearer filter isn't implemented yet, but for the sake of this question, let's assume all other endpoints should be wide open instead. How can I get them to bypass the basic auth filter if a user passes in basic auth header?
#Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf(CsrfConfigurer::disable)
.authorizeHttpRequests()
.requestMatchers("/oauth/token").authenticated()
.anyRequest().permitAll()
.and()
.httpBasic(Customizer.withDefaults());
return http.build();
}
Like this one:
private static final String[] RESOURCE_ARGS = new String[]{
"/test/**"
};
#Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests()
.requestMatchers(RESOURCE_ARGS).permitAll();
http
.csrf(CsrfConfigurer::disable)
.authorizeHttpRequests()
.requestMatchers("/oauth/token").authenticated()
.anyRequest().permitAll()
.and()
.httpBasic(Customizer.withDefaults());
....
}

SAML with Spring security anonymousUser

We have to implement SSO using SAML in SpringBoot. I have achieved to redirect the user to the identity provider login page and make the login. The problem is that after the login, when I try to get the user info with SecurityContextHolder.getContext().getAuthentication() I get anonymousUser, and not the logged user data.
Here is my SecurityConfig
#Override
protected void configure(final HttpSecurity http) throws Exception {
http
.csrf().and()
.authorizeRequests()
.antMatchers("/saml/**).permitAll()
.anyRequest().authenticated()
.and()
.apply(saml())
.userDetailsService(samlUserDetailsServiceImpl)
.serviceProvider()
.protocol("http")
.hostname("localhost:8080")
.basePath("/")
.keyStore()
.storeFilePath("classpath:metadata/samlKeystore.jks")
.keyPassword(keystorePass)
.keyname(keystoreAlias)
.and()
.and()
.identityProvider()
.metadataFilePath("classpath:metadata/idp.xml")
.discoveryEnabled(false)
.and()
.and();
And the implementation of SAMLUserDetailService
#Service
public class SamlUserServiceImpl implements SAMLUserDetailsService {
#Override
public Object loadUserBySAML(SAMLCredential credential) {
String userID = credential.getNameID().getValue();
GrantedAuthority userAuthority = new SimpleGrantedAuthority("ROLE_GESTOR");
return new User(userID, "DUMMY", Collections.singletonList(userAuthority));
}
I have debugged the code and in the SAMLUserDetailsService implementation I receive the user data after logging.
Also, is there a way to indicate the redirection url when the user has logged? Now it redirects to same url.
Thanks in advance

Why two formLogin configured in Spring Authorization Server Sample code

I'm checking latest Spring Authorization Server v0.2.0 and found two formLogin() configured on the provided sample authorizationserver.
One is AuthorizationServerConfig.java:
#Bean
#Order(Ordered.HIGHEST_PRECEDENCE)
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);
return http.formLogin(Customizer.withDefaults()).build();
}
Another one is DefaultSecurityConfig.java:
#Bean
SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeRequests(authorizeRequests ->
authorizeRequests.anyRequest().authenticated()
)
.formLogin(withDefaults());
return http.build();
}
My question is:
why there are two formLogin()s configured
If I wanted to customize formLogin() which one should I change?
The reason for the formLogin() configuration in AuthorizationServerConfig is purely a "convenience configuration", as it will setup the LoginUrlAuthenticationEntryPoint and perform the redirect to /login when the current request is not authenticated.
For example, when the client is redirected to /oauth2/authorize and the user is not authenticated, the user will be redirected to /login, which will match on the SecurityFilterChain defined by DefaultSecurityConfig NOT AuthorizationServerConfig.
Basically, the formLogin() in AuthorizationServerConfig serves the sole purpose of performing the redirect to /login, which is ultimately matched on the DefaultSecurityConfig SecurityFilterChain.

Spring Security OAuth - how to disable login page?

I want to secure my application with Spring Security, using OAuth 2. However, I don't want the server to redirect incoming unauthorized requests, but instead to respond with HTTP 401. Is it possible?
Example: this code redirects requests to a default login page.
application.properties
spring.security.oauth2.client.registration.google.client-id=...
spring.security.oauth2.client.registration.google.client-secret=...
AuthConfig.java
#Configuration
public class AuthConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/secured/**").authenticated()
.anyRequest().permitAll()
.and()
.oauth2Login();
// https://stackoverflow.com/questions/31714585/spring-security-disable-login-page-redirect
// deos not work
// .and()
// .formLogin().successHandler((request, response, authentication) -> {});
}
}
You need to create new authentication entry point and set it in configuration.
#Configuration
public class AuthConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.exceptionHandling()
.authenticationEntryPoint(new AuthenticationEntryPoint())
.and()
.authorizeRequests()
.antMatchers("/secured/**").authenticated()
.anyRequest().permitAll()
.and()
.oauth2Login();
}
}
public class AuthenticationEntryPoint extends LoginUrlAuthenticationEntryPoint {
public AuthenticationEntryPoint() {
super("");
}
#Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
response.sendError(401, "Unauthorized");
}
}
You need to set oauth2Login.loginPage in your HttpSecurity config and create a controller mapping to return whatever you want. Here's a simple example.
So in your security config
http
.authorizeRequests()
.antMatchers("/noauth").permitAll()
.oauth2Login()
.loginPage("/noauth")
In a controller
#GetMapping("/noauth")
public ResponseEntity<?> noAuth() {
Map<String, String> body = new HashMap<>();
body.put("message", "unauthorized");
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(body);
}
You can pass a map or pojo to the body method.
I would like to expand on Petr's answer by explaining that apparently for the time being first of all, the default login page is shown when there are more than one OAuth2 configured providers. I would expect that Spring Boot would have a smart trick to bypass this page easily and choose the right provider automatically, basing e.g. on the existence of the provider's client ID in the original request. I found out the hard way that this is not the case. So the way to do this is.. this not very apparent trick of providing a custom handler for failures - that will REDIRECT the user to the correct OAuth2 endpoint for each provider, based on the original HTTP request URL. I tried this and it works and I spent a whole day trying all manners of other solutions - my original scenario was to pass additional parameters to OAuth2 scheme in order to be able to get them back on successful authentication - they used to do this appending Base64 encoded information to the "state" URL request parameter, but Spring Security does not allow this at the moment. So the only alternative was to call a Spring Security-protected URL with those parameters already there, so when the successful authentication happens, this URL is accessed again automatically with those parameters intact.
Related: Multiple Login endpoints Spring Security OAuth2

Resources