Spring Security Basics: Implementing Authentication and Authorization-PART 1
Published: 2024-06-06 23:35:00

##  Create the base application
Before proceeding to the implementation of authentication and authorization , let's create a simple application to serve as a foundation. The application will have the following API end points.

1. `GET /api/hello`
    
2. `GET /api/protected`
    
3. `GET /api/admin`
    

Also a database software is required. Here the setup uses **PostgreSQL** database. You are free to choose yours.


>Don't forget to create a database named <code>spring_access_db</code> in your favorite database tool.



Let's go through the following steps to build the foundation.

1. Create the project
    
2. Implement the API end points
    
3. Create user and role entities
    
4. Create user and role repositories
    
5. Configure database connectivity
    
6. Populate database with sample users
    
7. Run the application
    
8. Verify users and roles are created by querying the database
    
9. Try accessing the API end points
    

### Create the project

To create the project go to [https://start.spring.io/](https://start.spring.io/) and create the sample project with the following dependencies.

* **Spring Web**
    
* **Spring Data JPA**
    
* **PostgreSQL Driver**
    

> If you are using <strong><em>IntelliJ IDEA Ultimate</em></strong> or <strong><em>Visual Studio Code</em></strong> you can create the project within the IDE.


>Create project with IntelliJ IDEA Ultimate : <a target="_blank" rel="noopener noreferrer nofollow" href="https://www.jetbrains.com/help/idea/your-first-spring-application.html" style="pointer-events: none">Click here for doc</a>

>Create project with Visual Studio Code: <a target="_blank" rel="noopener noreferrer nofollow" href="https://code.visualstudio.com/docs/java/java-spring-boot" style="pointer-events: none">Click here for doc

Here I used the Spring initializer and opened the project in IntelliJ IDEA (Community Edition)



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1547uvcjawkv17k5kpsm.png)

1. Add the dependencies
    
2. Fill up the project metadata
    
3. Generate the Zip file and extract it.
    
4. Then open it in your IDE.
    

### Implement the API end points

Create a class named **ApiController** and implement the APIs there.

* **ApiController.java**
    
    ```java
    package com.gintophilip.springauth.controller;
    
    import org.springframework.http.ResponseEntity;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    @RequestMapping("/api")
    public class ApiController {
        @GetMapping("/hello")
        public ResponseEntity<String> hello() {
            return ResponseEntity.ok("Hello");
        }
    
        @GetMapping("/protected")
        public ResponseEntity<String> protectedResource() {
            String message = """
                    This is a protected resource <br>
                    You are seeing this because you are an authenticated user
                    """;
            return ResponseEntity.ok(message);
        }
    
        @GetMapping("/admin")
        public ResponseEntity<String> admin() {
            String message = "Hello Admin";
            return ResponseEntity.ok(message);
        }
    }
    ```
    

### Create user and role entities

Create two classes for modeling the user and role entities.

**ApplicationUser.java**

```java
package com.gintophilip.springauth.entities;

import jakarta.persistence.*;

@Entity
public class ApplicationUser {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String firstName;
    private String lastName;
    @Column(unique = true)
    private String email;
    private String password;
    @ManyToOne
    @JoinTable(name = "user_roles")
    private Roles role;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Roles getRole() {
        return role;
    }

    public void setRole(Roles role) {
        this.role = role;
    }
}
```

**Roles.java**

```java
package com.gintophilip.springauth.entities;

import jakarta.persistence.*;

@Entity
public class Roles {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    @Column(unique = true)
    private String roleName;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getRoleName() {
        return roleName;
    }

    public void setRoleName(String roleName) {
        this.roleName = roleName;
    }
}
```

### Create user and role repositories

**UserRepository.java**

```java
package com.gintophilip.springauth.repository;

import com.gintophilip.springauth.entities.ApplicationUser;
import org.springframework.data.jpa.repository.JpaRepository;

public interface UserRepository  extends JpaRepository<ApplicationUser,Long> {

    ApplicationUser findByEmail(String email);
}
```

**RoleRepository.java**

```java
package com.gintophilip.springauth.repository;

import com.gintophilip.springauth.entities.Roles;
import org.springframework.data.jpa.repository.JpaRepository;

public interface RoleRepository extends JpaRepository<Roles,Long> {

}
```

### Configure database connectivity

Let's configure the connection to the database named `spring_access_db` with the following settings:

username: **postgres**

password: **12345**

For configuring the database connectivity update the **application.properties** file as follows.

```plaintext
spring.datasource.url=jdbc:postgresql://localhost:5432/spring_access_db
spring.datasource.username=postgres
spring.datasource.password=12345
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect
spring.jpa.hibernate.ddl-auto = update
```
>If you are using a different database, please ensure that the connection URL is updated to correspond with your specific database. also the hibernate dialect

### Populate database with sample users

Let's Create a class which implements the `CommandLineRunner` interface. The method `run` will be executed once the application is ready.

**DatabaseUtilityRunner.java**

```java
package com.gintophilip.springauth;

import com.gintophilip.springauth.entities.ApplicationUser;
import com.gintophilip.springauth.entities.Roles;
import com.gintophilip.springauth.repository.RoleRepository;
import com.gintophilip.springauth.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

@Component
public class DataBaseUtilityRunner implements CommandLineRunner {
    @Autowired
    UserRepository usersRepository;
    @Autowired
    RoleRepository rolesRepository;
    @Override
    public void run(String... args) throws Exception {
        try {
            Roles userRole = new Roles();
            userRole.setRoleName("USER");
            Roles adminRole = new Roles();
            adminRole.setRoleName("ADMIN");
            rolesRepository.save(userRole);
            rolesRepository.save(adminRole);
            ApplicationUser user1 = new ApplicationUser();
            user1.setFirstName("John");
            user1.setEmail("john@test.com");
            user1.setPassword("123456");
            user1.setRole(userRole);

            ApplicationUser adminUser = new ApplicationUser();
            adminUser.setFirstName("sam");
            adminUser.setEmail("sam@test.com");
            adminUser.setPassword("12345");

            adminUser.setRole(adminRole);
            usersRepository.save(user1);
            usersRepository.save(adminUser);
        }catch (Exception exception){
         
        }

    }
}
```

### Verify users and roles are created by querying the database

As a result of the previous step three tables will be created with the provided data in the database `spring_access_db`;

Here I use the psql CLI client to view and query the database.

**List of tables**

```bash
spring_access_db-# \dt
              List of relations
 Schema |       Name       | Type  |  Owner   
--------+------------------+-------+----------
 public | application_user | table | postgres
 public | roles            | table | postgres
 public | user_roles       | table | postgres
(3 rows)
```

**Table: application\_user**

**Query**: `select * from application_user;`

```bash
spring_access_db=# select * from application_user;
 id |     email     | first_name | last_name | password 
----+---------------+------------+-----------+----------
  1 | john@test.com | John       |           | 123456
  2 | sam@test.com  | sam        |           | 12345
(2 rows)
```

In this example, the password is stored in clear text. In a real-world scenario, it is essential to store passwords in an encrypted form rather than as plain text. We'll do this later.

**Table: roles**

**Query:**`select * from roles;`

```bash
spring_access_db=# select * from roles;
 id  | role_name 
-----+-----------
 802 | USER
 803 | ADMIN
(2 rows)
```

**Table: user\_roles**

**Query:**`select * from user_roles;`

```bash
spring_access_db=# select * from user_roles;
 role_id | id 
---------+----
     802 |  1
     803 |  2
(2 rows)
```

### Run the application

Now run the application. Once it is up and running, open the browser and try to access the API endpoints.

1. [http://localhost:8080/api/hello](http://localhost:8080/api/hello)
    
2. [http://localhost:8080/api/protected](http://localhost:8080/api/protected)
    
3. [http://localhost:8080/api/admin](http://localhost:8080/api/admin)
    

You will be able to access all the APIs without any restrictions. This completes the setup of base application.

In the comings steps we'll see how to protect these end points by integrating authentication and authorization mechanisms using Spring Security.

---