Skip to main content

Spring Security - An Introduction

Building an application without security is like building a house without doors
– Unknown

When I was in my college days, all I used to care about was creating an application that would bring a change. My thought process was limited to the development of the UI + Backend + Database. I even created a website that would register users, retrieve logged-in users, and book bikes and cars for them. It was a great portal to book and track your bookings after logging in. But all this changed when I came across this subject in my third year based on networking.
What changed in my perspective was the following :
  1. I came to know that the data will travel from one router to another before reaching the actual server. For example - let's say the server is in the USA, and I send a request from India. It will pass through a lot of networking devices before reaching the actual recipient.
  2. This means that there might be a scenario, where someone intercepts this data in the middle, gets the username and password, and use it to impersonate that user.
  3. I may send an encrypted text, but if it's intercepted, still the hacker can impersonate me or the user trying to log in by sending that encrypted text to the server and getting the data from it.

Take a moment to think about it. Is encryption enough? Can't he just use the encrypted text instead? The hacker anyways does not care what password you put in as long as he can get what he desires.
This is just one example, you can think of a lot more along these lines.
So now the question is -
What can we do to remediate this?

Spring Security To The Rescue !!!!!

Spring Security is a powerful and highly customizable authentication and access-control framework.
What it would basically do is provide you with methods and ways to authenticate as well as authorize the user. I will talk about Authorization in a little while, right now let's concentrate on the authentication part.
If you understood the above challenges correctly, you might think -
HOW?? will spring security do it? Is it going to provide a security guard on each networking device from where your data passes? Hmm.... nice thought, but you know security guards can be drugged sometimes forcefully but majorly voluntarily.
The answer is NO!. This won't be a practical solution. But what we can do is check for any disruption in the data sent from client to server. Basically saying checking if the data sent for authentication from the client to the server was actually sent by the client.
What I am basically trying to say is: If I send a request from India from my computer, or we can call it a client, We can send something to the server which would tell the server that we sent it.
By now I am sure you might have understood the challenges we face. I am still going to point them down just in case we forget what we are talking about. The questions our server will ask are the following :
  1. Is the request sent to me from the actual user?
  2. Is the request sent to me not tampered with?

The Real Question is HOW?





There are many ways to do this in the context of spring security. I will cover each way in terms of authentication and we will see how each can be utilized in your applications.

Spring Security Using JPA

If you are unfamiliar with JPA, you can go to this link and have a quick look - 
https://www.tutorialspoint.com/jpa/jpa_introduction.htm#

In basic terms, a JPA is a layer between your application and database, using which you can write code in the application language such as java and interact with the database.
For example, if we want to get a user by its username from the database, we would use JPA inbuilt methods like findUserByUsername() and get the username.

I would not go into much detail on JPA as this blog is more inclined toward security.

FLOW :

The flow of this application is simple. 
  1. User enters credentials and hits submit in the User Interface Form.
  2. Data reaches the server and passes through the spring security filters.
  3. We will create a class for the authentication of this data through JPA, which we will see in a while.
  4. Spring security will authenticate this user with the database using JPA and if the user is authenticated, it will save the user in its context, and then for example, if a user visits any other part of the application, the server can check if the user is an authenticated user or not using this context.
Implementation :
Create a project using this link. In dependencies, add the following dependencies



Once this project is ready, download it and unzip it and import it as a maven project into your IDE. I will be using eclipse for this one.


Let us first create a controller class with some APIs.

Code For Controller


This controller has three endpoints, which would return three different HTML when they are called by the User Interface. If you know how to create a rest API, this would look pretty simple. If not, you should take a look at how we can write a simple API using java and spring boot.


But now, We would only want an authenticated user to be able to access these API Endpoints.
For this, We will create a security configuration class, where all the magic of spring security will happen.



What are we doing here?

Before I explain that, there is something really notable we must know - 
The Authentication part where we compare the user details which came from UI with what we already have in our databases will always be done by spring security, what we can change is the way, in which the information is retrieved from our database or any third-party service for comparison.
In our case, we are creating a user details service and auto-wiring it to this class.

Then, we tell spring security that whatever data comes from the UI or the consumer's end, we want you to check that data through our custom-made userDetailsService.

Setup JPA and Custom UserDetails class

Now, We will set up our JPA. For this, I am using MySQL as a database.
We will create a database using the command 
<create database spring security>  in MySQL.
Do it however it suits you.
Then, we will go to the application.properties file, presented under the resources folder of our project, and type in some configurations that our application will use to connect to the database.


After this, the application will know where and how to connect to our database.

Next, we create a repository using the inbuilt JPARepository class, which provides us with methods such as getUserByUsername, etc which will then be automatically converted to actual SQL queries by the JPA.



As we can see, this Interface extends JPARepository and also takes in a generic. This generic first parameter is the class, on which this repository will perform operations such as getUserByUsername(). Then the second parameter is the type of key being used in the class/table. We see the first parameter is User. But who defined this User class?

This will also be defined by us as an entity class. I will not go into JPA in detail but the entity class is mapped to a table in MySQL in simple language.
Our User.java class will look like this : 


In the repository above, we have also defined our own method : 
Optional<User> findByUserName(String userName);

We did this to so that when we send a userName to this method, we are returned with an Optional of type User. Why we did it, will be explained when we write our UserDetailsService.


What is UserDetailsService?
This is the service, which will tell spring security, how the data is to be retrieved. You might think that this data implementation may differ from person to person. For example, some people might want to send just user name and password, while others may send a username, password, phone number, etc. 

You are right, spring security does have a standard class for this very reason.

Its name is - UserDetails which is present in org.springframework.security.core.userdetails package.

The class would look something like this : 



What the hell is this code???
Ok Ok, Calm down. It's pretty simple.
We annotate this class with a @service annotation to let the spring container know of its presence.
We then implement the UserDetailsService Interface. This interface does two things for us :
  1. It will help our custom class to be autowired to the previous configuration class.
  2. It will add a method called loadUserByUsername.
The loadUserByUsername(String userName) takes a parameter called username, which is supplied by spring to this method from the data which the user sent from the actual user interface. Now in the next line, we use the JPA repository to fetch us the data using findByUserName(userName). 
If the user is found, it returns a User class type of optional which we then convert according to our custom class which is MyUserDetails using its constructor.

Why did we convert to MyUserDetails?
We did this because as we talked about above there should be a generalized class present, this generalization is required so that the data which is retrieved is in the same pattern as required by spring security to read and evaluate it with the data user sent. This class MyUserDetails will implement UserDetails Interface. Take some time to understand it through the code or else code it yourself for better understanding.


Notice what we are trying to achieve here is to convert or map the User object we retrieved from our database to the UserDetails object required as spring can only read objects of UserDetails class.

Great! Once this is done you can start your spring boot either through IDE or you can visit the internet to check how to run the spring boot application in your desired platform.

Once you are there, you will be presented with a form, provided by spring security to enter your username and password. Note whatever we enter here should be present in the User table of our database for spring security to compare. Once this is done, you will see that you can easily access the URL:  localhost
 You can also put in a debugger in your respective IDE to see how all this works.






Comments

Popular posts from this blog

My Quarantine "Efforts"

A true relationship is two imperfect people refusing to give up on each other. – Them This blog is on relationships and of course a bit of coding, otherwise it would be stupid to put it here anyways. My girlfriend and I have been having some issues lately regarding the term "Efforts". Now when I put it in front of any of my friends, They have the same reply "Efforts" and when asked what efforts are? … Nothing. I get a supposedly deep answer - Efforts come from within. What does that even mean?. So I tried some stuff to get a response from her. Well for some context we came in relationship on 28 february,2020 and guess when the lockdown started in India. Don't guess, you may as well google it. It was not even a month before the lockdown began and we flew back home. She lives more than 1500km from my state. But you know sometime you just meet the right person and you just know. We knew we had to fight this as we had so much left to say to each ot...

Developing an app with react native and firebase - firestore - Part 1

Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live. –John F. Woods Let's face it, we are two years into work from home, quarantined from the outside and this makes me wonder that how lucky I am as an engineer to be able to have so many domains open for me to work on, with which I could eventually make money, help others. In other words, it gives me the power to bring a change. I just can't think of a problem where technology cannot help. As soon as I find a problem in minutes my mind starts to work on how it can be solved technically. I think this development is what our college provides us with, to open our technical aspects. Today, I will be talking about react-native and firestore, making app development a little painless and fast. If we are looking to solve a simple everyday problem and want an app to do it for us, an app that is not very complex - react native is the way to go. So,...

What The Hell Is gRPC?

Time is the longest distance between two places. ― Tennessee Williams  If you are a software engineer and you work on websites or any other software which is in high demand by your consumer, but you see that some parts of your application say the products page gets higher demand than any other services you provide at some point of time or let's say you want to loosely couple your application for your application to be developed more easily and flexibly.  These are a few use cases, there are many more. We are seeing a trend in the industry getting more aligned toward following microservices patterns while building the application. The When, Why, Where, and How parts of microservices can be easily found on the internet.  Here I want to talk more about some new technologies which have become an integral part when we talk about microservices. So this blog would be more fruitful for people who know the  When, Why, Where, and How  parts. Today, I will talk a...