Spring Security Basic Auth Password Rotation Issue - spring

Experts,,
I have a spring boot 2.5.5 application(embedded tomcat) where I have to configure the basic auth.
This is the class I have that does the work for me
#Component
#EnableWebSecurity
public class ApplicationSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.httpBasic();
}
}
The issue is I just need to enter the user/password once in the browser and it works for any subsequent request. Furthermore, I don't need to supply the new username/password after the server restarts which is driving me crazy - the app still works and I can access my APIs/pages.
Even if i assume the browser is somehow saving the username and password it should not work once the server is restarted as the password gets changed - isnt it ?
Update II:
Following the advice from M. Deinum I made the session stateless and it worked. I then went on to implement Basic Auth with InMemoryUserDetailsManager and added the below code and we are back to the same issue again. The credentials seem to be again stored in session and I need not pass them for the subsequent request.
#Autowired
public ApplicationSecurityConfig(PasswordEncoder passwordEncoder) {
this.passwordEncoder = passwordEncoder;
}
#Override
#Bean
protected UserDetailsService userDetailsService() {
UserDetails user = User
.builder()
.username("admin")
.password(passwordEncoder.encode("admin"))
.roles("ADMINISTRATOR")
.build();
return new InMemoryUserDetailsManager(user);
}

This is how I would expect it to work with your current configuration.
When successfully authenticated with basic authentication the browser will send the username/password for all other subsequent requests. So this is as expected.
Another thing is that, by default, Spring Security will use the HTTP Session to store the user information. A session-cookie is also sent with each request so that the session state can be restored for each request.
This session state is, by default for your servlet container, saved to disc when you stop the server, when you restart and the session is still valid (not timed out) it will still have the authentication.
You can fix this by making Spring Security not use a session (set the session mode to stateless).
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
The drawback of this is that it will re-authenticate each request (which takes some time and thus impacts your performance slightly). But it should give an error after restart now, as you changed the password.

Related

SpringBoot works on the web but doesn't work in the postman?

I'm trying to build to build a really basic user/role CRUD with spring security.
I created 2 types of accounts: admin and user.
After I go to this URL: http://localhost:8080/api/v1/employees first I get login and after that I get the result
The problem start when I try to connect via postman. I can't get past the login.
I can't get past the login no matter what. I tried other controller but the same thing happens.
Am I doing something wrong? Am I missing a step?
To make a call in Postman, you need to pass a proper authorization (token header/cookie) when calling an endpoint. In your current case, Postman either shows you a login page which is that HTML you see, or an error page because unauthorized
I had this problem yesterday, it's most likely the same thing.
I disabled csrf in the class that extends WebSecurityConfigurerAdapter to get it to work. If you're moving into production, you should probably leave it enabled.
My WebSecurityConfig class:
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/").permitAll();
}
}
I don't fully understand how the csrf protection so there might be issues if you try to log in from a browser. Uncomment out the .csrf().disable() when you want to run in from a browser

Keep session id in case of presence of special parameter in request. Spring Security

Does anybody know if there any way to configure Spring Security in the way that it doesn't change session id if there is some parameter in the request.
For example:
somesite.com/home.jsp?password=encrypted- change session id after
authentication
somesite.com/home.jsp?password=encrypted& keepsessionid - don't
change session id after authentication
I was thinking about filter chain, maybe removing conditionally SessionManagementFilter, but not sure if this is a proper way, and even if this will be working
For someone with the same question. I found the answer. Different session management strategy can be achieved by using multiple http security configuration (inner classes of main security classes). The special case http security configurer should be adjusted to some special request
#Configuration
#Order(1)
public class SpecialCaseSessionHandlingConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.requestMatcher(request -> Check1(request))
.authorizeRequests()
.anyRequest().authenticated();
}
}

My heroku app is requesting a password that I did not put there

I'm new to the process of sending an application to production and I'm using Heroku free plan to test. Today I went to check my app and the API I made using Spring boot is not working and is requesting a login that I didn't do. My app address is https://erik-financial-api.herokuapp.com and when you go there it redirects you to the address https://erik-financial-api.herokuapp.com/login with the following:
I did not make this page and none of the passwords (from my app or from my Heroku account) work on it. This was supposed to be just a REST API for another front-end app. Does anyone know why is this happening?
The code for this project can be found on my GitHub on https://github.com/esscheffer/financial-api
Edit: this seems to be a default spring security login page. I have searched for solutions, but none worked so far. What I have tried:
Add
override fun configure(security: HttpSecurity) {
security.httpBasic().disable()
.formLogin().disable()
}
to my WebSecurityConfigurerAdapter class.
Add http.httpBasic().disable().formLogin().disable() to the configure of my ResourceServerConfigurerAdapter class.
Add (exclude = [SecurityAutoConfiguration::class]) to the #SpringBootApplication sanitation on my application class.
The first 2 tries didn't remove the login page and the last one broke the app, returning 404 for all pages. Note that this only happens when I deploy my application to Heroku. When running locally I don't have this login page or any other problem.
Add a new configuration class com.scheffer.erik.financial.api.config.SecurityConfig, where in the configure method you can disable the HTTP Basic authentication as well as login form based authentication, like below:
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity security) throws Exception {
security
.httpBasic().disable()
.formLogin().disable();
}
}
Do it like this...permit all requests for the home page...I hope it will work for you.
#Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable().
authorizeRequests()
.antMatchers("/").permitAll() //OR .antMatchers("/**").permitAll()
.anyRequest().authenticated();
}

Authentication of background tasks using Spring Boot and Spring Security

I have a background task (running with Project Reactor, but I don't think it is relevant) that I need to run in with an authenticated user to get through some #PreAuthorize annotated methods.
I'm doing something like this:
Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(login, password));
SecurityContextHolder.getContext().setAuthentication(authentication);
But when I trace into the authenticationManager call, I find that it is using Spring-Boot's default InMemoryUserDetailsService, rather than my custom authentication configuration. This happens regardless of whether I run the authentication in a web request thread, or in the background thread.
I don't know if it is relevant, but I am running this code in an integration test, with these annotations (among others):
#SpringApplicationConfiguration(classes=MyAppConfiguration.class)
#WebAppConfiguration
#IntegrationTest({"server.port:0"})
In addition to this problem, my test makes an authenticated web request to my server, and that authenticates just fine. So I know at least the web portion of my system is using the correct authenication configuration.
Here is my authentication configuration:
#EnableWebMvcSecurity
#EnableGlobalMethodSecurity(jsr250Enabled=true, prePostEnabled=true)
public abstract class BaseSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
public LocalUserDetailsService localUserDetailsService;
#Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(localUserDetailsService);
}
#Override
public void configure(HttpSecurity http) throws Exception {
http.csrf().disable().httpBasic()
.and()
.authorizeRequests()
.antMatchers( "/admin/**" ).hasRole( "ADMIN" )
}
It is hard to tell without your test implementatiton but it matters that you are running it in integration test
Maybe you are forgetting to add `FilterChainProxy to your mockMvc
like this mvc = MockMvcBuilders.webAppContextSetup(context)
.addFilter(springSecurityFilterChain).build();
instance of filterChainPrioxy can be #Autowired into your test class, of course this answer may not make sense, depends of your implementation of test class
---after your comment
this line :
SecurityContextHolder.getContext().setAuthentication(authentication);
assigns security constrains to current thread and does not impact threads running in background, unless your strategy is global and it is not default

how to implement a authentication with spring boot security?

i am using spring boot. i want to post a username and password params to login, and if login success then return a token. after, i will use the token to judge login status. here is my security configure code. but i don't konw where to write the login authentication logic code.
SecurityConfig.java
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest()
.fullyAuthenticated()
.and()
.formLogin()
.loginPage("/user/unlogin")
.permitAll();
}
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/user/login")
.antMatchers("/user/logout")
.antMatchers("/user/register");
}
}
==========================
thank you !
There's always more than one way to do something with Spring. There is a happy path (probably) with Spring Boot, and you seem to have started on it. Note though, if you want Boot to provide some default behaviour, then don't use #EnableWebSecurity (as advised in the user guide). The web-secure sample has an example you can follow.
If you use formLogin() the default login URL is /login (not /user/login), so you should be able to post the username and password to that endpoint to authenticate. Don't add /login to the unsecured paths using web.ignoring() or Spring Security will never process it. When you post to /login you get back a JSESSIONID cookie. That's your authentication token, and it expires when the session expires in the server (30min by default, but easily configurable). Include it in future requests for secure resources - some HTTP clients will even do that for you (like a browser does).

Resources