Spring Boot Security mechanisms and OAuth2 with JWT

Last updated on May 30 2022
Amarjit Malik

Table of Contents

Spring Boot Security mechanisms and OAuth2 with JWT

In this blog , you will learn in detail about Spring Boot Security mechanisms and OAuth2 with JWT.

Authorization Server

Authorization Server is a supreme architectural component for Web API Security. The Authorization Server acts a centralization authorization point that allows your apps and HTTP endpoints to identify the features of your application.

Resource Server

Resource Server is an application that provides the access token to the clients to access the Resource Server HTTP Endpoints. It is collection of libraries which contains the HTTP Endpoints, static resources, and Dynamic web pages.

OAuth2

OAuth2 is an authorization framework that enables the application Web Security to access the resources from the client. To build an OAuth2 application, we need to focus on the Grant Type (Authorization code), Client ID and Client secret.

 

JWT Token

JWT Token is a JSON Web Token, used to represent the claims secured between two parties. You can learn more about the JWT token at www.jwt.io/.

Now, we are going to build an OAuth2 application that enables the use of Authorization Server, Resource Server with the help of a JWT Token.

You can use the following steps to implement the Spring Boot Security with JWT token by accessing the database.

First, we need to add the following dependencies in our build configuration file.

Maven users can add the following dependencies in your pom.xml file.

<dependency>   <groupId>org.springframework.boot</groupId>   <artifactId>spring-boot-starter-jdbc</artifactId></dependency> <dependency>   <groupId>org.springframework.boot</groupId>   <artifactId>spring-boot-starter-security</artifactId></dependency> <dependency>   <groupId>org.springframework.boot</groupId>   <artifactId>spring-boot-starter-web</artifactId></dependency> <dependency>   <groupId>org.springframework.security.oauth</groupId>   <artifactId>spring-security-oauth2</artifactId></dependency> <dependency>   <groupId>org.springframework.security</groupId>   <artifactId>spring-security-jwt</artifactId></dependency> <dependency>   <groupId>com.h2database</groupId>   <artifactId>h2</artifactId></dependency> <dependency>   <groupId>org.springframework.boot</groupId>   <artifactId>spring-boot-starter-test</artifactId>   <scope>test</scope></dependency> <dependency>   <groupId>org.springframework.security</groupId>   <artifactId>spring-security-test</artifactId>   <scope>test</scope></dependency>

Gradle users can add the following dependencies in the build.gradle file.

compile(‘org.springframework.boot:spring-boot-starter-security’)compile(‘org.springframework.boot:spring-boot-starter-web’)testCompile(‘org.springframework.boot:spring-boot-starter-test’)testCompile(‘org.springframework.security:spring-security-test’) compile(“org.springframework.security.oauth:spring-security-oauth2”)compile(‘org.springframework.security:spring-security-jwt’)compile(“org.springframework.boot:spring-boot-starter-jdbc”)compile(“com.h2database:h2:1.4.191”)

where,

  • Spring Boot Starter Security − Implements the Spring Security
  • Spring Security OAuth2 − Implements the OAUTH2 structure to enable the Authorization Server and Resource Server.
  • Spring Security JWT − Generates the JWT Token for Web security
  • Spring Boot Starter JDBC − Accesses the database to ensure the user is available or not.
  • Spring Boot Starter Web − Writes HTTP endpoints.
  • H2 Database − Stores the user information for authentication and authorization.

The complete build configuration file is given below.

<?xml version = “1.0” encoding = “UTF-8”?><project xmlns = “http://maven.apache.org/POM/4.0.0”    xmlns:xsi = “http://www.w3.org/2001/XMLSchema-instance”   xsi:schemaLocation = “http://maven.apache.org/POM/4.0.0    http://maven.apache.org/xsd/maven-4.0.0.xsd”>      <modelVersion>4.0.0</modelVersion>   <groupId>com.tecklearn</groupId>   <artifactId>websecurityapp</artifactId>   <version>0.0.1-SNAPSHOT</version>   <packaging>jar</packaging>   <name>websecurityapp</name>   <description>Demo project for Spring Boot</description>    <parent>      <groupId>org.springframework.boot</groupId>      <artifactId>spring-boot-starter-parent</artifactId>      <version>1.5.9.RELEASE</version>      <relativePath /> <!– lookup parent from repository –>   </parent>    <properties>      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>      <java.version>1.8</java.version>   </properties>    <dependencies>      <dependency>         <groupId>org.springframework.boot</groupId>         <artifactId>spring-boot-starter-jdbc</artifactId>      </dependency>            <dependency>         <groupId>org.springframework.boot</groupId>         <artifactId>spring-boot-starter-security</artifactId>      </dependency>            <dependency>         <groupId>org.springframework.boot</groupId>         <artifactId>spring-boot-starter-web</artifactId>      </dependency>            <dependency>         <groupId>org.springframework.security.oauth</groupId>         <artifactId>spring-security-oauth2</artifactId>      </dependency>            <dependency>         <groupId>org.springframework.security</groupId>         <artifactId>spring-security-jwt</artifactId>      </dependency>            <dependency>         <groupId>com.h2database</groupId>         <artifactId>h2</artifactId>      </dependency>            <dependency>         <groupId>org.springframework.boot</groupId>         <artifactId>spring-boot-starter-test</artifactId>         <scope>test</scope>      </dependency>            <dependency>         <groupId>org.springframework.security</groupId>         <artifactId>spring-security-test</artifactId>         <scope>test</scope>      </dependency>   </dependencies>    <build>      <plugins>         <plugin>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-maven-plugin</artifactId>         </plugin>      </plugins>   </build>   </project>

Gradle – build.gradle

buildscript {   ext {      springBootVersion = ‘1.5.9.RELEASE’   }   repositories {      mavenCentral()   }   dependencies {      classpath(“org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}”)   }}apply plugin: ‘java’apply plugin: ‘eclipse’apply plugin: ‘org.springframework.boot’ group = ‘com.tecklearn’version = ‘0.0.1-SNAPSHOT’sourceCompatibility = 1.8 repositories {   mavenCentral()} dependencies {   compile(‘org.springframework.boot:spring-boot-starter-security’)   compile(‘org.springframework.boot:spring-boot-starter-web’)   testCompile(‘org.springframework.boot:spring-boot-starter-test’)   testCompile(‘org.springframework.security:spring-security-test’)   compile(“org.springframework.security.oauth:spring-security-oauth2”)   compile(‘org.springframework.security:spring-security-jwt’)   compile(“org.springframework.boot:spring-boot-starter-jdbc”)   compile(“com.h2database:h2:1.4.191”)  }

Now, in the main Spring Boot application, add the @EnableAuthorizationServer and @EnableResourceServer annotation to act as an Auth server and Resource Server in the same application.

Also, you can use the following code to write a simple HTTP endpoint to access the API with Spring Security by using JWT Token.

package com.tecklearn.websecurityapp; import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController; @SpringBootApplication@EnableAuthorizationServer@EnableResourceServer@RestControllerpublic class WebsecurityappApplication {   public static void main(String[] args) {      SpringApplication.run(WebsecurityappApplication.class, args);   }   @RequestMapping(value = “/products”)   public String getProductName() {      return “Honey”;      }}

Use the following code to define the POJO class to store the User information for authentication.

package com.tecklearn.websecurityapp; import java.util.ArrayList;import java.util.Collection;import org.springframework.security.core.GrantedAuthority; public class UserEntity {   private String username;   private String password;   private Collection<GrantedAuthority> grantedAuthoritiesList = new ArrayList<>();      public String getPassword() {      return password;   }   public void setPassword(String password) {      this.password = password;   }   public Collection<GrantedAuthority> getGrantedAuthoritiesList() {      return grantedAuthoritiesList;   }   public void setGrantedAuthoritiesList(Collection<GrantedAuthority> grantedAuthoritiesList) {      this.grantedAuthoritiesList = grantedAuthoritiesList;   }   public String getUsername() {      return username;   }   public void setUsername(String username) {      this.username = username;   }}

Now, use the following code and define the CustomUser class that extends the org.springframework.security.core.userdetails.User class for Spring Boot authentication.

package com.tecklearn.websecurityapp; import org.springframework.security.core.userdetails.User; public class CustomUser extends User {   private static final long serialVersionUID = 1L;   public CustomUser(UserEntity user) {      super(user.getUsername(), user.getPassword(), user.getGrantedAuthoritiesList());   }}

You can create the @Repository class to read the User information from the database and send it to the Custom user service and also add the granted authority “ROLE_SYSTEMADMIN”.

package com.tecklearn.websecurityapp; import java.sql.ResultSet;import java.util.ArrayList;import java.util.Collection;import java.util.List; import org.springframework.beans.factory.annotation.Autowired;import org.springframework.jdbc.core.JdbcTemplate;import org.springframework.security.core.GrantedAuthority;import org.springframework.security.core.authority.SimpleGrantedAuthority;import org.springframework.stereotype.Repository; @Repositorypublic class OAuthDao {   @Autowired   private JdbcTemplate jdbcTemplate;    public UserEntity getUserDetails(String username) {      Collection<GrantedAuthority> grantedAuthoritiesList = new ArrayList<>();      String userSQLQuery = “SELECT * FROM USERS WHERE USERNAME=?”;      List<UserEntity> list = jdbcTemplate.query(userSQLQuery, new String[] { username },         (ResultSet rs, int rowNum) -> {                  UserEntity user = new UserEntity();         user.setUsername(username);         user.setPassword(rs.getString(“PASSWORD”));         return user;      });      if (list.size() > 0) {         GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(“ROLE_SYSTEMADMIN”);         grantedAuthoritiesList.add(grantedAuthority);         list.get(0).setGrantedAuthoritiesList(grantedAuthoritiesList);         return list.get(0);      }      return null;   }}

You can create a Custom User detail service class that extends the org.springframework.security.core.userdetails.UserDetailsService to call the DAO repository class as shown.

package com.tecklearn.websecurityapp; import org.springframework.beans.factory.annotation.Autowired;import org.springframework.security.core.userdetails.UserDetailsService;import org.springframework.security.core.userdetails.UsernameNotFoundException;import org.springframework.stereotype.Service; @Servicepublic class CustomDetailsService implements UserDetailsService {   @Autowired   OAuthDao oauthDao;    @Override   public CustomUser loadUserByUsername(final String username) throws UsernameNotFoundException {      UserEntity userEntity = null;      try {         userEntity = oauthDao.getUserDetails(username);         CustomUser customUser = new CustomUser(userEntity);         return customUser;      } catch (Exception e) {         e.printStackTrace();         throw new UsernameNotFoundException(“User ” + username + ” was not found in the database”);      }   }}

Next, create a @configuration class to enable the Web Security, defining the Password encoder (BCryptPasswordEncoder), and defining the AuthenticationManager bean. The Security configuration class should extend WebSecurityConfigurerAdapter class.

package com.tecklearn.websecurityapp; import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationManager;import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;import org.springframework.security.config.annotation.web.builders.HttpSecurity;import org.springframework.security.config.annotation.web.builders.WebSecurity;import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;import org.springframework.security.config.http.SessionCreationPolicy;import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;import org.springframework.security.crypto.password.PasswordEncoder; @Configuration@EnableWebSecurity@EnableGlobalMethodSecurity(prePostEnabled = true)public class SecurityConfiguration extends WebSecurityConfigurerAdapter {   @Autowired   private CustomDetailsService customDetailsService;    @Bean   public PasswordEncoder encoder() {      return new BCryptPasswordEncoder();   }   @Override   @Autowired   protected void configure(AuthenticationManagerBuilder auth) throws Exception {      auth.userDetailsService(customDetailsService).passwordEncoder(encoder());   }   @Override   protected void configure(HttpSecurity http) throws Exception {      http.authorizeRequests().anyRequest().authenticated().and().sessionManagement()         .sessionCreationPolicy(SessionCreationPolicy.NEVER);   }   @Override   public void configure(WebSecurity web) throws Exception {      web.ignoring();   }   @Override   @Bean   public AuthenticationManager authenticationManagerBean() throws Exception {      return super.authenticationManagerBean();   }}

Now, define the OAuth2 Configuration class to add the Client ID, Client Secret, Define the JwtAccessTokenConverter, Private key and Public key for token signer key and verifier key, and configure the ClientDetailsServiceConfigurer for the Token validity with scopes.

package com.tecklearn.websecurityapp; import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationManager;import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;import org.springframework.security.oauth2.provider.token.store.JwtTokenStore; @Configurationpublic class OAuth2Config extends AuthorizationServerConfigurerAdapter {   private String clientid = “tecklearn”;   private String clientSecret = “my-secret-key”;   private String privateKey = “private key”;   private String publicKey = “public key”;    @Autowired   @Qualifier(“authenticationManagerBean”)   private AuthenticationManager authenticationManager;      @Bean   public JwtAccessTokenConverter tokenEnhancer() {      JwtAccessTokenConverter converter = new JwtAccessTokenConverter();      converter.setSigningKey(privateKey);      converter.setVerifierKey(publicKey);      return converter;   }   @Bean   public JwtTokenStore tokenStore() {      return new JwtTokenStore(tokenEnhancer());   }   @Override   public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {      endpoints.authenticationManager(authenticationManager).tokenStore(tokenStore())      .accessTokenConverter(tokenEnhancer());   }   @Override   public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {      security.tokenKeyAccess(“permitAll()”).checkTokenAccess(“isAuthenticated()”);   }   @Override   public void configure(ClientDetailsServiceConfigurer clients) throws Exception {      clients.inMemory().withClient(clientid).secret(clientSecret).scopes(“read”, “write”)         .authorizedGrantTypes(“password”, “refresh_token”).accessTokenValiditySeconds(20000)         .refreshTokenValiditySeconds(20000);    }}

Now, create a Private key and public key by using openssl.

You can use the following commands for generating private key.

openssl genrsa -out jwt.pem 2048openssl rsa -in jwt.pem

You can use For public key generation use the below commands.

openssl rsa -in jwt.pem -pubout

For the version of Spring Boot latter than 1.5 release, add the below property in your application.properties file to define OAuth2 Resource filter order.

security.oauth2.resource.filter-order=3

YAML file users can add the below property in YAML file.

security:   oauth2:      resource:         filter-order: 3

Now, create schema.sql and data.sql file under the classpath resources src/main/resources/directory to connect the application to H2 database.

The schema.sql file is as shown −

CREATE TABLE USERS (ID INT PRIMARY KEY, USERNAME VARCHAR(45), PASSWORD VARCHAR(60));

The data.sql file is as shown −

INSERT INTO USERS (ID, USERNAME,PASSWORD) VALUES (   1, ‘tecklearn@gmail.com’,’$2a$08$fL7u5xcvsZl78su29x1ti.dxI.9rYO8t0q5wk2ROJ.1cdR53bmaVG’); INSERT INTO USERS (ID, USERNAME,PASSWORD) VALUES (   2, ‘myemail@gmail.com’,’$2a$08$fL7u5xcvsZl78su29x1ti.dxI.9rYO8t0q5wk2ROJ.1cdR53bmaVG’);

Note − Password should be stored in the format of Bcrypt Encoder in the database table.

You can create an executable JAR file, and run the Spring Boot application by using the following Maven or Gradle commands.

For Maven, you can use the command given below −

mvn clean install

After “BUILD SUCCESS”, you can find the JAR file under the target directory.

For Gradle, you can use the command as shown −

gradle clean build

After “BUILD SUCCESSFUL”, you can find the JAR file under the build/libs directory.

Now, run the JAR file by using the command shown here −

java –jar <JARFILE>

The application is started on the Tomcat port 8080.

Page 13 Image 1
appstarted

Now hit the POST method URL via POSTMAN to get the OAUTH2 token.

http://localhost:8080/oauth/token

Now, add the Request Headers as follows −

  • Authorization − Basic Auth with your Client Id and Client secret.
  • Content Type − application/x-www-form-urlencoded
Page 13 Image 2
requestheader

Now, add the Request Parameters as follows −

  • grant_type = password
  • username = your username
  • password = your password
Page 14 Image 3
request parameter

Now, hit the API and get the access_token as shown −

Page 14 Image 4
access_token

Now, Hit the Resource Server API with Bearer access token in Request Header as shown.

Page 14 Image 5
resource

Then you can see the output as shown below −

Page 15 Image 6
output

So, this brings us to the end of blog. This Tecklearn ‘Spring Boot Security mechanisms and OAuth2 with JWT’ blog helps you with commonly asked questions if you are looking out for a job in Java Programming. If you wish to learn Spring Boot and build a career Java Programming domain, then check out our interactive, Java and JEE Training, that comes with 24*7 support to guide you throughout your learning period. Please find the link for course details:

https://www.tecklearn.com/course/java-and-jee-training/

Java and JEE Training

About the Course

Java and JEE Certification Training is designed by professionals as per the industrial requirements and demands. This training encompasses comprehensive knowledge on basic and advanced concepts of core Java & J2EE along with popular frameworks like Hibernate, Spring & SOA. In this course, you will gain expertise in concepts like Java Array, Java OOPs, Java Function, Java Loops, Java Collections, Java Thread, Java Servlet, and Web Services using industry use-cases and this will help you to become a certified Java expert.

Why Should you take Java and JEE Training?

  • Java developers are in great demand in the job market. With average pay going between $90,000/- to $120,000/- depending on your experience and the employers.
  • Used by more than 10 Million developers worldwide to develop applications for 15 Billion devices.
  • Java is one of the most popular programming languages in the software world. Rated #1 in TIOBE Popular programming languages index (15th Consecutive Year)

What you will Learn in this Course?

Introduction to Java

  • Java Fundamentals
  • Introduction to Java Basics
  • Features of Java
  • Various components of Java language
  • Benefits of Java over other programming languages
  • Key Benefits of Java

Installation and IDE’s for Java Programming Language

  • Installation of Java
  • Setting up of Eclipse IDE
  • Components of Java Program
  • Editors and IDEs used for Java Programming
  • Writing a Simple Java Program

Data Handling and Functions

  • Data types, Operations, Compilation process, Class files, Loops, Conditions
  • Using Loop Constructs
  • Arrays- Single Dimensional and Multi-Dimensional
  • Functions
  • Functions with Arguments

OOPS in Java: Concept of Object Orientation

  • Object Oriented Programming in Java
  • Implement classes and objects in Java
  • Create Class Constructors
  • Overload Constructors
  • Inheritance
  • Inherit Classes and create sub-classes
  • Implement abstract classes and methods
  • Use static keyword
  • Implement Interfaces and use it

Polymorphism, Packages and String Handling

  • Concept of Static and Run time Polymorphism
  • Function Overloading
  • String Handling –String Class
  • Java Packages

Exception Handling and Multi-Threading

  • Exception handling
  • Various Types of Exception Handling
  • Introduction to multi-threading in Java
  • Extending the thread class
  • Synchronizing the thread

File Handling in Java

  • Input Output Streams
  • io Package
  • File Handling in Java

Java Collections

  • Wrapper Classes and Inner Classes: Integer, Character, Boolean, Float etc
  • Applet Programs: How to write UI programs with Applet, Java.lang, Java.io, Java.util
  • Collections: ArrayList, Vector, HashSet, TreeSet, HashMap, HashTable

Java Database Connectivity (JDBC)

  • Introduction to SQL: Connect, Insert, Update, Delete, Select
  • Introduction to JDBC and Architecture of JDBC
  • Insert/Update/Delete/Select Operations using JDBC
  • Batch Processing Transaction
  • Management: Commit and Rollback

Java Enterprise Edition – Servlets

  • Introduction to J2EE
  • Client Server architecture
  • URL, Port Number, Request, Response
  • Need for servlets
  • Servlet fundamentals
  • Setting up a web project in Eclipse
  • Configuring and running the web app with servlets
  • GET and POST request in web application with demo
  • Servlet lifecycle
  • Servlets Continued
  • Session tracking and filter
  • Forward and include Servlet request dispatchers

Java Server Pages (JSP)

  • Fundamentals of Java Server Page
  • Writing a code using JSP
  • The architecture of JSP
  • JSP Continued
  • JSP elements: Scriptlets, expressions, declaration
  • JSP standard actions
  • JSP directives
  • Introduction to JavaBeans
  • ServletConfig and ServletContext
  • Servlet Chaining
  • Cookies Management
  • Session Management

Hibernate

  • Introduction to Hibernate
  • Introduction to ORM
  • ORM features
  • Hibernate as an ORM framework
  • Hibernate features
  • Setting up a project with Hibernate framework
  • Basic APIs needed to do CRUD operations with Hibernate
  • Hibernate Architecture

POJO (Plain Old Java Object)

  • POJO (Plain Old Java Object)
  • Persistent Objects
  • Lifecycle of Persistent Object

Spring

  • Introduction to Spring
  • Spring Fundamentals
  • Advanced Spring

Got a question for us? Please mention it in the comments section and we will get back to you.

 

 

 

0 responses on "Spring Boot Security mechanisms and OAuth2 with JWT"

Leave a Message

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