Customizing Spring Security

In this post I want to explain how Spring Security can be customized since it seems to be difficult to find any solid documentation around this available on internet. I am going to use a custom API Key based authentication example to demonstrate how Spring Security can be configured for your needs.

I am going to create three things to get this done.

  1. A Token to hold the principal and the credentials
  2. A Filter to create the aforementioned Token from the request, authenticate that using the AuthenticationManager and place the Authentication in the SecurityContextHolder.
  3. An Authentication Provider to be used by the AuthenticationManager to authenticate the Token.

I will begin by creating a Spring Boot Project using Spring Initializr. I will need two dependencies here; Web and Security.

Once I have the project running on my favorite IDE, I am going to create two packages called config and security. I will use the former to keep my Security Configuration file and the latter to keep the Token, Filter and the Authentication Provider. You really don’t have to stick to this package structure. You can do whatever you want with your package structure as long as that makes sense to you and the folks writing the code.

Next Steps

Create the Custom Authentication Token

The Custom Authentication Token will hold the apiKey.

Create the Custom Authentication Provider which supports ApiKeyAuthenticationToken to authenticate the Custom Token we just created

I will first add the my API Key to application.properties.

The Custom Authentication Provider will check if the API Key is valid. If it is not, the Authentication Provider will throw an Exception. In a Production Application you may create a Custom Exception which will be handled gracefully with the correct HTTP response code.

Create the Filter which creates the Token and asks the Authentication Manager to authenticate that Token

Update the Security Configuration

The Security Configuration class that extends WebSecurityConfigurerAdapter annotated with @EnableWebSecurity.

Section 1 disables Basic Authentication( which is enabled by default), CSRF and Cookies( you will not see the JSESSIONID now) for all requests.

Section 2 permits all traffic to public endpoints.

Section 3 adds our custom filter for all protected endpoints.

I will use the code snippet below to configure Authentication Manager to use the Custom Authentication Provider.

Write the Controllers

I will now create another package for controllers called controller and write two GET methods there.

Testing

The public endpoint will respond without any API Keys.

The protected endpoint will give an access denied error if the API Key is not sent in the Headers.

The protected endpoint will throw an error with the message “Invalid API Key”. Note that the HTTP Error code is 500. That needs to be handled with an Exception Handler.

The protected endpoint will respond if the correct API Key is sent.

The Source Code is available here.

Photo Credits

unsplash-logoAlisa Anton

You may also like

Leave a Reply

Your email address will not be published. Required fields are marked *