Spring security : configure JWT with formLogin - spring

I am trying to configure JWT filter with formLogin authentication .
(My server serve UI clients (thats why i need formLogin ) and i am exposing also Rest End Point (to be authenticated by JWT ) .
currently my JWT is working , but it seems that my Roles (anyRole) -- isnt working .
here is my configure method :
post login -> if I am trying to reach /kuku path - I get 302 and login page again .
if i am removing the addFilterBefore -> my roles is working fine .
protected void configure(HttpSecurity http) throws Exception {
http.
authorizeRequests()
.antMatchers("/login").permitAll()
.antMatchers("/").hasRole("ADMIN")
.antMatchers("/kuku/**").hasRole("ADMIN")
.anyRequest()
.authenticated()
.and()
.formLogin().defaultSuccessUrl("/inital.html", true)
;
http.addFilterBefore(new JwtFilter(), UsernamePasswordAuthenticationFilter.class);
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
String userName = "Admin"; // currently due to Vault IMPL - this input is hardcoded .
String password ="Admin"
auth.inMemoryAuthentication()
.withUser(userName).password(passwordEncoder().encode(password))
.roles("ADMIN");
}

Try adding csrf().disable() to your configure(http) method. This worked in my case where I have similar configuration as yours. Although, I suggest searching for whether or not this is secure, because this disables built-in csrf protection.

Related

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

Spring security antMatcher not working as expected

I have my custom controller "/my-endpoint" and spring app with the following configuration:
#Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/my-endpoint", "/health")
.permitAll()
.antMatchers(DENY_RESOURCE_PATTERNS)
.denyAll()
.anyRequest()
.authenticated()
}
It seems that for a unanimous user it working fine. But if I already authorized (using oauth2) and my session(or token) is expired -> spring trying to redirect me to the login page.
I don't want this, I want to allow any user to connect to "/my-endpoint" endpoint.
What I forgot to configure?
The interesting thing, that built-in endpoint "/health" working as expected, even if session is expired.
you can use configure(WebSecurity web). It will bypass the Spring Security Filters and will allow any user to access the endpoint. see HttpSecurity vs WebSecurity
#Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers(HttpMethod.yourMethod, "/health")
.antMatchers(HttpMethod.yourMethod, "/my-endpoint");
}

How can I get roles or groups from Azure SAML 2.0 Application in Spring Boot

I have a spring boot application where I need to limit access for specific endpoints. So far I can authenticate against Azure using SAML 2.0.
This is the main configuration of the authentication in Spring
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.exceptionHandling()
.authenticationEntryPoint(samlEntryPoint());
http
.csrf()
.disable();
http
.addFilterBefore(metadataGeneratorFilter(), ChannelProcessingFilter.class)
.addFilterAfter(samlFilter(), BasicAuthenticationFilter.class);
http
.authorizeRequests()
.antMatchers("/error").permitAll()
.antMatchers("/saml/**").permitAll()
.anyRequest().authenticated();
http
.logout()
.logoutSuccessUrl("/");
}
in Azure I have added the roles to the claim values as shown in the image below
Azure Claims
My target is to be able evantaully to do something like the following:
#GetMapping("/")
#PreAuthorize("hasRole('User')")
public String getSample(Principal principal) {
log.info("Get Request");
return "Hello";
}
Next step would be to implement your own SAMLUserDetailsService that would return the corresponding UserDetail instance with the rights Authorities granted to the user.
You would have to retrieve the list of Azure role from the SAMLCredential (something like credential.getAtttributeAsString(<your_attribute_name>) then you would have to map theses values with the list of authorities defined in your application.

Spring Security Authentication Success With Wrong Password

My WebSecurity Config is like below;
#EnableWebSecurity
#Configuration
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated().and().httpBasic();
}
#Override
protected void configure(AuthenticationManagerBuilder builder) throws Exception {
builder.inMemoryAuthentication().withUser("hellouser")
.password("hellopass").roles("USER");
}
}
When i give wrong username, Authentication fails as expected. But, if i get success in authentication once, all other requests after that with wrong password but correct username gets authenticated successfully....
Is it getting cached somewhere?
Can i disable this feature?
Isn't it suppose to give authentication failure with wrong password?
NOTE: I am learning spring-security. I dont have any html pages in this app and testing from PostMan.
use http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); in the configure method.
#Override
protected void configure(HttpSecurity http) throws Exception {
http
//HTTP Basic authentication
.httpBasic()
.and()
....
.csrf().disable()
.formLogin().disable();
//to check password in each request
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
I was able to access the URL from below configuration using basic auth from Postman even with wrong credential, which was happening because once you provide the right credentials the credentials get stored in session and even if you repeats the same request the same session will be used to access the URL.
http
.httpBasic()
.and()
.authorizeRequests()
.antMatchers("/secure/admin/**").hasRole("ADMIN")
.antMatchers("/api/**","/secure/getUserByName/**").hasAnyRole("USER","ADMIN")
.anyRequest().fullyAuthenticated();
Solution:
http
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
Just add the above code. So this configuration assures that only a single instance of a user is authenticated at a time. And if the same user tries to access the URL then it's previous session is terminated and then the user has to provide login credentials again for which new session is created.

How to capture Spring Security authentication token and save it in a database

We are using a two-pronged approach to user authentication where we are using an in-memory authentication token store in clustered environment and saving the token in a shared database as well. Now I am able to get token using the in-memory store and authenticate users. Everything is working as expected.
I am looking for the following things :
Capture the token and save it in the database? How to achieve this with Spring Security (this should happen after successful authentication)?
If server restarts then I should still be able to validate the token from database.(if user name password is correct.)
#Component
public class CustomAuthSuccessHandler implements AuthenticationSuccessHandler {
#Override
public void onAuthenticationSuccess(HttpServletRequest request,
HttpServletResponse response, Authentication authentication)
throws IOException, ServletException {
System.out.println(request);
System.out.println(response);
}
}
Following are my HTTP settings:
#Override
public void configure(HttpSecurity http) throws Exception {
http.exceptionHandling()
.authenticationEntryPoint(customAuthenticationEntryPoint)
.and()
.logout()
.logoutUrl("/oauth/logout")
.logoutSuccessHandler(customLogoutSuccessHandler)
.and()
.csrf()
.requireCsrfProtectionMatcher(
new AntPathRequestMatcher("/oauth/authorize"))
.disable().headers().frameOptions().disable()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and().authorizeRequests().antMatchers("/hello/")
.permitAll().antMatchers("/secure/**").authenticated();
}
PS : It looks like adding an interceptor can help, however I am not sure how do I to get token from response. Any suggestions?

Resources