Spring Boot, Elastic Beanstalk error, no issue from the IDE - spring

I'm currently using continuous integration in order to automatically set up and configure the servers. Unfortunately I'm running into issues when the Elastic Beanstalk Tomcat 8 initializes. I get the following error only when running from AWS, it runs fine in my ide:
Caused by: java.lang.NullPointerException: null
at org.springframework.security.config.annotation.web.builders.HttpSecurity.addFilterBefore(HttpSecurity.java:1112) ~[spring-security-config-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at uk.co.thinkinnovate.security.WebSecurityConfig.configure(WebSecurityConfig.java:41) ~[WebSecurityConfig.class:na]
at org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter.getHttp(WebSecurityConfigurerAdapter.java:199) ~[spring-security
And the block of code with the issue:
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf()
.disable()
.addFilterBefore(tokenProcessingFilter(),
BasicAuthenticationFilter.class)
.addFilterBefore(new SimpleCORSFilter(),
AuthenticationTokenProcessingFilter.class)
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and().exceptionHandling();
}
#Bean
public AuthenticationTokenProcessingFilter tokenProcessingFilter() {
System.out.println("Getting token processing filter.");
System.out.println(this.tokenBasedRememberMeService);
return this.tokenBasedRememberMeService;
}
Why is the TomCat version not autowiring the tokenBasedRememberMeService but my Spring Boot application is?
Thanks guys.
Edit:
Just a weird note: "Getting token processing filter" only calls in the AWS app and is null whereas in the IDE and Spring Boot it does not appear.
I feel I'm missing some key concept here.

This issue was so simple!
Make sure your application class extends SpringBootServletInitializer implements InitializingBean

Related

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

Spring Boot 2.0.2 Spring Security how to disable custom Form Login for two endpoints

EDIT:
After several days of trying various Security configuration changes, I punted and put .permitAll() on every endpoint which should authorize/authenticate any request. But even then, although I could freely "browse" any page without authenticating, my device clients were still unable to submit PUT requests to their normal application endpoint.
So now the question is, why can the remote clients successfully submit PUT requests to my app running on the 1.5.4 Spring Boot version but not when "the same app" is running at Spring Boot 2.0.2?
I get a successful "health check" response ("up and running as usual...") when I hit the same "device" endpoint with a GET request from my browser. But the client devices just get ERR_CONNECTION_REFUSED (or similar) when they try to PUT.
/EDIT
This question is related to one I asked about Web Socket migration a couple of days ago, but the web socket part turned out to be a red herring.
The real issue I'm facing is related to Spring Security in SB 2.0.2.
springBootVersion = '2.0.2.RELEASE'
springVersion = '5.0.13.RELEASE'
springSecurityVersion = '5.2.1.RELEASE'
Everything was working the way we needed at SB 1.5.4, but at 2.0.2 I can't seem to restore the necessary behavior. What I need is my custom Form Login applied to all endpoints except /input and /input/auth
This is the only configurer adapter we were using at 1.5.4 (with ACCESS OVERRIDE)
#Configuration
#EnableWebSecurity
//#Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
#Order(1)// highest priority
class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
SimpleAuthenticationManager sam;
#Override
protected void configure(HttpSecurity http) throws Exception {
// false means go to original destination page after login success
boolean alwaysRedirectToSuccessUrl = false;
http.headers().cacheControl().disable();
http.headers().frameOptions().sameOrigin();
http.csrf().ignoringAntMatchers("/input/auth/**");// ignoring WebSocket endpoints (secured by other means)
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.ALWAYS);
http.authorizeRequests()
.antMatchers('/widgetInfo/**', '/stats', '/errorCodes').hasAuthority('USER').anyRequest().fullyAuthenticated()
http.formLogin()
.loginPage('/widgetInfo/login')
.loginProcessingUrl("/widgetInfo/fooInfo")
.defaultSuccessUrl("/widgetInfo/fooInfo", alwaysRedirectToSuccessUrl)
.failureUrl("/widgetInfo/login?status=LOGIN_FAILURE").permitAll()
}
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers('/webjars/**', '/static/**', '/css/**', '/js/**', '/input/**');
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.parentAuthenticationManager(sam)
}
}
The above configuration works in 2.0.2, except that it is not allowing free access to the /input endpoints. After chasing the red herring for a couple of days, and realizing my misunderstanding, I tried adding another much more lenient configurer adapter as more-or-less described at the bottom of this page
#Configuration
#EnableWebSecurity
#Order(11)// lowest priority
class LenientWebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().ignoringAntMatchers("/input/auth/**");// ignoring WebSocket endpoints (secured by other means)
http.authorizeRequests().antMatchers('/input', 'input/auth', '/input/**').permitAll()
}
}
But it's not working, the /input endpoint is not yet freely accessible. What is the issue?
If I swap the #Order, then nothing goes through my custom Form Login.
Answering here just to close loop for future users who might land here.
The problem turned out to be that Spring Boot 1.5.4 would accept "HTTP1.1" requests, but Spring Boot 2.0.2 will not.
Our app sits behind an F5 device that rejects inbound requests if/when the application "healthcheck" requests fail. This is the "healthcheck" request that was working at 1.5.4
GET /myGateway/input HTTP/1.1\r\n
But at 2.0.2, that request was failing. At 2.0.2 the healthcheck request needs to be
GET /myGateway/input \r\n
Therefore, "Spring Security" configuration issues were also a red herring.
EDIT: Apparently, this is/was a known issue with 2.0.x that was fixed in Spring Boot 2.2.x (summer 2019)

Setting session timeout in spring boot application using google App Engine

I have a spring boot application which is being deployed in google app engine.
I have a requirement of setting session time out on condition basis.
I tried attaching a successHandler in spring security configuration as
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.ALWAYS)
.and()
.successHandler(successHandler())
}
And here is the success handler
private AuthenticationSuccessHandler successHandler() {
return (httpServletRequest, httpServletResponse, authentication) -> {
httpServletRequest.getSession().setMaxInactiveInterval(10);
};
}
I figured out that google app engine uses jetty server (jetty 9 actually) and
it frequently keeps storing the created sessions in memcache and datastore.
some how app engine does not honor the session time out set by calling
httpServletRequest.getSession().setMaxInactiveInterval(10);

How to reload the Configure method of WebSecurityConfigurerAdapter when the application is up and running

I am using spring boot and in spring security we are using "WebSecurityConfigurerAdapter" and using the method
#Override
protected void configure(HttpSecurity http) throws Exception {
AuthenticationFilter authenticationFilter = new AuthenticationFilter(authenticationManager(), tokenService(), externalServiceAuthenticator());
http.addFilterBefore(authenticationFilter, BasicAuthenticationFilter.class)
.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and().authorizeRequests().antMatchers(externalServiceCaller.getPrivateEndPoints())
.hasAnyAuthority(externalServiceCaller.getAllAuthorities()).anyRequest().authenticated()
.and().authorizeRequests().anyRequest().anonymous()
.and().exceptionHandling().authenticationEntryPoint(unauthorizedEntryPoint())
.and().exceptionHandling().authenticationEntryPoint(forbiddenEntryPoint());
}
This is working fine for existing role and user but when we are adding more users and role at run time (After the application start) then spring security is not able to recognize new role and new user . Is there any way to call the above method again when the application is up and running.
Reload configure(HttpSecurity http) is impossible in runtime, because it's some kind of builder and it's creates some part of the spring security chain when the application is starting - if you'd like to reload the method you have to replace the spring security chain during runtime - it's not so easy and recommended way.
If you need add some user during runtime - implement custom AuthentificationProvider

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

Resources