Empowering Businesses with Tech
Spring security using JWT
Spring Security is just a bunch of servlet filters that help us add authentication and authorization to our web application. It secures our application as it has many predefined methods which help in authenticating and authorizing any client who accesses your application. These methods can be overridden and customized as your own.
​
For implementing Spring Security you need to add a spring-boot-starter-security dependency. (And don’t forget to update maven).
This will enable security for our application. Now, as we can find that our swagger-UI is not opening the interface which we saw earlier. Neither our local web browser is running our application as both will ask for sign-in.
So, the default username is always “user” and the password will be provided in our console as logs of the java application. We can sign in and use your Apis.
Spring security using UserId and Password
1) We need to create a MyUserDetailService class that will implement and use methods of the “UserDetailService” interface. Here we will override a method named “loadUserByUsername” which will load the customer details to look up the username, password, and GrantedAuthorities for any user.
​
-
We will create and use a hard-coded user with a user name, password, and an empty ArrayList();
-
And this will be used for signing in.
​​
Note: We can also access users from the database without hardcoding users. But the username should be unique.
2) Now, we will create a security configuration that will extend “WebSecurityConfigureAdapter”. And we will override a default method that generates the default user and password as we saw above with the help of “AuthenticationManagerBuilder”. We will use our own created service “MyUserDetailService” for signing in to the security with help of our own created users.
​
-
So we need to create a user first with a username provided. And then create our Security configuration.
-
We used a method ‘passwordEncoder()’. This will encode our password as we would return. Here we have used “NoOpPasswordEncoder”. This is not recommended for any purpose unless you are just practicing. Because it does not encrypt the password.
-
Now we will run our application and sign in using the username and password of the user we created.
Spring security using JWT
​
JSON Web Tokens are standards for sharing security information between two parties.
JWT is secure as it uses encoded JSON which can be decoded and will have 3 parts -
a) Header - Contains the algorithm used and the type of token.
b) Payload - This section consists of data that are provided inside encoded JWT.
c) Verify Signature - To create the signature part you have to take the encoded header, the encoded payload, a secret, and the algorithm specified in the header, and sign that.
​
​
​We will use JWT to generate a token for a user and then authenticate the user based on the token provided.
Implementing JWT
1) First, we will add dependencies of JWT and “java.xml.bind”.
2) JWTUtil
​
-
First, we will create a “JwtUtil” class for using all utilities of JWT (generating the token, validating the token, setting expiration for a token, etc). And annotate it with @Component so Spring Boot can detect our class and inject dependencies.
-
We will define some methods here like -
-
generateToken: This will take “UserDetail” as a parameter and return a token.​
-
doGenerateToken: This will take a Map (created in the “generateToken” method) and a String as a parameter and return a token to the above method by creating a JWT token using “Jwts.builder”, set an expiration date for the token, and also set a signature for the token.
-
validateToken: This will take token and “UserDetail” as parameters and return a boolean.​
-
3) JWTFilter
​
We need to create a filter that will use any predefined web filter available from spring “OncePerRequestFilter”.
-
Our filter will intercept all the incoming requests and extract JWT from the header and validate the JWT and set up a security context telling that the current user is authenticated and should be allowed to use other APIs.
-
We will override an existing method “doFilterInternal()” which will take HttpServletRequest, HttpServletResponse, and a FilterChain as parameters and extract JWT from the header and validate the JWT, and set up security context.​
-
HTTP Headers -They are meta-data associated with the API request and response. In Jwt authorization you need to provide a header as “Authorization” and a key as Bearer <JWT token>.
4) Creating an endpoint to authenticate
Now we will try to get rid of the form-based default login that Spring security provides us. And will create an API to authenticate the user.
-
We need to create authentication requests and response DTOs that will take username and password as requests and return JWT as responses. And will annotate the classes with @NoArgsContructor and @AllArgsContructor, which are clear by name what they do.
-
After that, we need to make an API that will create a JWT token using the request as username and password and return “ResponseEntity” which will provide the status and JWT token.
-
We will use “AuthenticationManager” to authenticate the user. Once authenticated we will create a UserDetail with the help of our “loadByUsername” method of the “MyUserDetailService” we created earlier.
-
Then with the help of “UserDetail”, we will generate a token using the “generateToken” method of the “JwtUtil” class. And return a ResponseEntity with status as Ok.
5) But as we have created an API for signing in instead of a login form we will not be able to access even the “/authenticate” API.
​
-
So for using our authenticate API, we will alter some changes in “SecurityConfig” by overriding the “HttpSecurity” configure method. Here, we will allow and permit only “/authenticate” addresses to be open for all. Leaving that all addresses should be authenticated.
-
And we will set session management to stateless so that it will not create any sessions.
-
So, as sessions are not created here we will use our own created filter to be used before “UsernamePasswordAuthenticationFilter”.
6) Now everything is done and your application will run fine on Postman. But, it will not run on swagger. As we have set the “HttpSecurity” to access only “/authenticate”, the swagger URL is “/swagger-ui.html#/”.
​
-
So we will override a configuration method of “WebSecurity” which will ignore all the addresses related to swagger with the help of “.ignore.antMatchers(...)”.
-
Since we run Swagger on HTTP protocol, we need to override a configuration method of “HttpSecurity” which will ignore all the addresses related to swagger using “.antMatchers(...).permitAll”.
-
We also need to make AuthenticationManager a Bean, as in newer versions of Spring Authentication manager is not treated as Bean. Since we have autowired it, it should be a bean.
7) Now the last thing to do is to configure our swagger a little bit. Because we have allowed all swagger addresses. So, security and JWT will not be applied here.
​
-
We will add security contexts and security schemes in Docket and create an API key and security context. Now you are good to go.
Run your application and open your swagger and input the user’s username and password you created and you will be returned with a JWTtoken.
Then enter Bearer <JWT token> in the Authorize button on the top right. And you are ready to use other APIs.
Fig: Authenticating user by giving user details.
Fig: A JWT token returned as the user is authenticated.
Fig: Adding JWT token in the header to authorize the user.