Securing a Spring Boot REST API with Okta

In this section, we will learn how to secure a Spring Boot REST API with Okta.


What is Okta?

Okta is primarily cloud-based identity and access management software that enables secure authentication, Single Sign-On (SSO), Active Directory (AD) and LDAP integration, the centralized deprovisioning of users, multifactor authentication (MFA), mobile identity management, and flexible policies for organization security and control.

Okta’s basis is based on the notion of Identity as a Service (IDaaS), which provides enterprises with a comprehensive solution for identity and access management. More Info - click here


Why Do We Use Okta?

1. Increased Security

It provides a strong and secure authentication architecture that protects enterprises against illegal access and data breaches.


2. Better User Experience

Users can access all applications with only one set of credentials thanks to Okta's single sign-on (SSO) capabilities, which make for a faster and more effective user experience.


3. Productivity

Okta boosts productivity by making application access faster and easier.


4. Scalability and Flexibility

Okta solutions are scalable to meet the growing demands of modern technology landscapes, adaptable to different environments.


5. Governance and Compliance

Okta ensures adherence to regulatory requirements and compliance standards, instilling trust among customers and partners.


6. Cost savings

Okta reduces the need for IT specialists and streamlines user account management, saving enterprises time and money.


7. Enhanced collaboration

Okta's API access control tools let developers build safe and smooth interfaces between apps, facilitating communication and information sharing between teams.

More Info - click here


Let's go through a simple example,

1. Register to Okta

Go to okta signup page using https://developer.okta.com/signup/ link, We will be taken to a page like the below image,

Then click on the "Sign up free for Developer Edition" button. We will be taken to a page like the below image,

We can register by entering our personal information and click on "Sign up" button or We can register by clicking "Continue with GitHub" or "Continue with Google". I am using my Google account to register to Okta.

Okta will work as authorization server and for our API it will give us access token. Only when we have the access token we will be able to access the secured API's in our application.


2. Create an application in Okta

Next we need to create an application in Okta. 

Navigate to "Applications" on the left panel and select the "application" option from the dropdown list and then click on "Create App Integration" like below image.

After clicking "Create App Integration" button, we will see a popup like below image, 

Then choose "API Services" and the click on "Next" button. We will be taken to a page like the below image,

Here we have to give the name of our application and then click on "Save" button. We will be taken to a page like the below image,

Remember to have "Client ID" and "Client Secret" safely with us for the future purpose.

Next, navigate to "Security" on the left panel and select the "API" option from the dropdown list. 

Remember to have Authorization Server URL "Issuer URI" with us for the future purpose. This is created by Okta by default for us.


3. Create Custom Scope

Scopes are identifiers used to specify what access privileges are being requested.

Click on edit button, We will be taken to a page like the below image,

Click on "Add Scope" button, we will see a popup like below image, 

Remember to have custom scope "knowledgefactory" with us for the future purpose.


4. Creating spring boot application

First, open the Spring initializr https://start.spring.io/ 

Then, Provide the Group and Artifact name. We have provided Group name com.knf.dev.demo and Artifact spring-boot-okta-secure-rest-api. Here I selected the Maven project - language Java 17 - Spring Boot 3.1.5 , Okta, and Spring Web.

Then, click on the Generate button. When we click on the Generate button, it starts packing the project in a .zip(spring-boot-okta-secure-rest-api) file and downloads the project. Then, Extract the Zip file.

Then, import the project on your favourite IDE.


Final Project Directory


Complete pom.xml

<?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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.knf.dev.demo</groupId>
<artifactId>spring-boot-okta-secure-rest-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-boot-okta-secure-rest-api</name>
<description>Demo project for Spring Boot and Okta</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.okta.spring</groupId>
<artifactId>okta-spring-boot-starter</artifactId>
<version>3.0.5</version>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-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>


application.yaml 

okta:
oauth2:
issuer: https://<your-domain>/oauth2/default

Specify our issuer uri in application.yaml file.


Create Security Configuration

package com.knf.dev.demo.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http
.authorizeHttpRequests((requests) -> requests
.requestMatchers("/public").permitAll()
.anyRequest().authenticated())
.oauth2ResourceServer((oauth2) -> oauth2
.jwt(Customizer.withDefaults())
)
.build();
}
}

@Configuration annotation indicating that an object is a source of bean definitions. @Configuration classes declare beans through @Bean -annotated methods.

The @EnableWebSecurity helps to configure the Spring security-related beans, here SecurityFilterChain. SecurityFilterChain is used by FilterChainProxy to determine which Spring Security Filter instances should be invoked for the current request. More Info - click here

The requestMatchers() facilitate all the ways of restricting requests that were supported by the removed methods. Here's an example that permits access to the /public endpoint without authentication.

permitAll() method is used to configure access rules for specific endpoints or resources, allowing unrestricted access to them without requiring authentication or authorization. So, here '/public' endpoint has access to any request. But, '/protected' end point is secured. We need access token to access it.


Create DemoController.java 

package com.knf.dev.demo.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class DemoController {

@GetMapping("/public")
public String publicMsg(){

return "Public...";
}

@GetMapping("/protected")
public String protectedMsg(){

return "Protected...";
}
}


SpringBootOktaSecureRestApiApplication.java 

package com.knf.dev.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringBootOktaSecureRestApiApplication {

public static void main(String[] args) {
SpringApplication.run(SpringBootOktaSecureRestApiApplication.class, args);
}

}


5. Verify our system is working as expected


Run the Spring Boot application - mvn spring-boot:run


OR 


Run this Spring boot application from 

  • IntelliJ IDEA IDE by right click - Run 'Application.main()' 
  • Eclipse/STS - You can right click the project or the Application.java file and run as java application or Spring boot application.


Get the access token 

URL to hit to get the access token

https://<your-domain>/oauth2/default/v1/token

For Authorization specify, [Username = Client ID and Password = Client Secret]

On request body specify,[grant_type client_credentials and scope knowledgefactory] like below images.


We can use this access token as a Bearer Token to hit the secured endpoint, 



Remove the token and hit the endpoint again, we will get Status: 401 Unauthorized 

Source code - click here!

Popular posts from this blog

Learn Java 8 streams with an example - print odd/even numbers from Array and List

Java Stream API - How to convert List of objects to another List of objects using Java streams?

Registration and Login with Spring Boot + Spring Security + Thymeleaf

Java, Spring Boot Mini Project - Library Management System - Download

ReactJS, Spring Boot JWT Authentication Example

Spring Boot + Mockito simple application with 100% code coverage

Top 5 Java ORM tools - 2024

Java - Blowfish Encryption and decryption Example

Spring boot video streaming example-HTML5

Google Cloud Storage + Spring Boot - File Upload, Download, and Delete