A while ago I started working on a small SpringBoot application. Initially the plan was to use serverless as a tech stack - AWS Lambdas - so some aspects, such as security, hadn’t been addressed in the codebase, because it was supposed to be done using the mechanism already available in AWS. As a consequence when migrating the functionality from one technology to another security was a bit left behind. As the mobile client already had functionality built without security the priority was to get the most of the functionality up and running on the new tech stack. Test coverage was very good, but the project never went live due to a change of priorities.
At some point I had some time to get back to that project and I really wanted to add security to the application. The solution for securing those endpoints was JWT - Json Web Token, as this would provide a very simple way for mobile clients to comunicate with the server. Implemnting Spring Security is pretty straight forward, so I’m not going to focus to much on this subject.
In order to setup spring security you just need to include
spring-boot-starter-security among you dependencies and extend
WebSecurityConfigurerAdapter. Then overriding the method
configure(HttpSecurity http) will define how security will be configured for your application. Easy said and done. After having configured security, I went ahead and re-ran unit tests, because I wanted to to an additional refactor. It was at the that point that I discovered that all tests were failling with a 401 error code. The obvious reason was that I had implemented security and had not changed the way tests were run.
Possible solutions for this:
Change the setup method. Either the one annotated with
@Beforeor even better the one annotated with
@BeforeClasssuch that authentication is done only once before running all the tests. This should actually be pretty straight forward. Apart from actually changing the setup maethod to perform an additional call you would first need to make sure that the user you are performing authentication with exists inside the in-memory database you are using. If however you are using an external IAM system things could actually become a lot more complicated. Once you have added the necessary code for obtaining the token you would need to change all calls to your API to include the token. There is a bit of work involved, but it will actually insure that you are testing your endpoints exactly like they would behave in production.
Do we really need security when testing? Assuming that the spring security module has been properly tested and we implemented it according to best practices, it wouldn’t make too much sense to actually re-test it. So it would be safe to say that we can consider security as a fully functional component of our application. We should just focus on testing the business logic we wrote. It makes thus sense to de-activate it.
The way to de-activate would be to override the bean that we’ve used to configure security in the first place. Plain an simple what you are going to do is create a new class under you test folder that extends the same class as above. Inside the class overridding the
configure(HttpSecurity http) you would allow all requests.
http .authorizeRequests() .anyRequest() .permitAll();
Now, starting the application as should will actually yeld bean errors because the Spring context finds two beans annotated the same way and cannot decide which to use. Here is the small trick you would need to do. You are going to use Spring profiles. You would need to annotate your security configuration class that you have used for testing with
Make sure to annotate the main security configuration class with another profile such as
The last thing you need to do is inside the
application.properties of each location: source code and test add the profile that should be active using the property