The provided content is a comprehensive tutorial on securing a "StarVote" Spring Boot application using Keycloak or Okta as an Identity Provider (IdP), which includes adding security dependencies, creating login pages, updating UI components, and configuring Web Security settings.
Abstract
The article "Building a Single Spring Boot App with Keycloak or Okta as IdP: Adding Security" offers a step-by-step guide on how to secure the StarVote application, a Spring Boot application, using either Keycloak or Okta as an Identity Provider. It begins by outlining the necessary steps to add security features, including the addition of specific dependencies such as spring-boot-starter-oauth2-client and spring-boot-starter-oauth2-resource-server in the pom.xml file. The tutorial then instructs on creating a login.html page and modifying existing UI components like header.html and stars-list.html to integrate security features. It also covers the implementation of security configurations through the WebSecurityConfig class, which involves setting up security filter chains, OAuth2 login configurations, and JWT token validation. The article acknowledges potential startup failures and promises to address these issues in subsequent articles, which will delve into enabling Keycloak or Okta as the IdP. The tutorial series aims to provide a thorough understanding of implementing a secure single Spring Boot application.
Opinions
The author emphasizes the importance of securing applications and provides clear instructions on integrating OAuth2 security with Spring Boot.
The tutorial is designed to be accessible to developers familiar with Spring Boot, Thymeleaf, and Spring Security, with the expectation that readers will follow along and implement the security measures
Spring Boot | Star Vote
Building a Single Spring Boot App with Keycloak or Okta as IdP: Adding Security
A step-by-step guide on how to secure the StarVote application
This article is part of a series that explores the implementation of a Single Spring Boot application called StarVote. The application will use Keycloak or Okta as Identity Provider.
In the introductory article, we outline the sections we will cover:
Here’s a sneak peek of how the StarVote application will be at the end!
In this particular article, we will explore the necessary steps to secure the application. This includes adding the required dependencies, making UI modifications, and configuring the Web Security settings.
The spring-boot-starter-oauth2-client dependency provides the necessary components to enable OAuth 2.0 client functionality in the Spring Boot application;
The spring-boot-starter-oauth2-resource-server dependency allows the Spring Boot application to act as an OAuth 2.0 resource server, validating and processing incoming requests from OAuth 2.0 clients;
The thymeleaf-extras-springsecurity6 dependency is an extension for Thymeleaf that integrates with Spring Security version 6, providing additional features and utilities for secure web application development.
Implementing Security
Create the login.html
In the resources/templates folder, create the login.html file with the following content:
<!DOCTYPE html><htmllang="en"xmlns:th="http://www.thymeleaf.org"><head><metacharset="UTF-8"><title>StarVote</title><linkrel="stylesheet"href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.5.0/semantic.min.css"></head><divth:insert="~{header :: header}"></div><body><divclass="ui center aligned basic segment"><h2class="ui center aligned icon header"><iclass="circular users icon"></i>
Sign in
</h2><divclass="ui compact labeled icon menu"><aclass="item"><iclass="openid alternate icon"></i>
OpenID
</a></div></div><scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.0/jquery.min.js"></script><scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.5.0/semantic.min.js"></script></body></html>
The login.html page features an <a> tag for the Identity Provider that users can use to log in to the StarVote application. In the upcoming tutorials, we will provide the URL links to be included in the href attribute of the <a> tags.
Update the header.html
Let’s apply the following changes (highlighted in bold) to the header.html file.
<!DOCTYPE html><htmllang="en"xmlns:th="http://www.thymeleaf.org"xmlns:sec="http://www.thymeleaf.org/extras/spring-security"><body><header><divclass="ui massive menu"><divclass="item"><iclass="video camera icon"></i>
StarVote
</div><aclass="item"th:href="@{/}">
Home
</a><aclass="item"th:href="@{/add-stars}"sec:authorize="hasRole('STAR-VOTE-ADMIN')">
Add Star
</a><aclass="item"th:href="@{/stars-list}"sec:authorize="hasAnyRole('STAR-VOTE-ADMIN','STAR-VOTE-USER')">
Star's List
</a><aclass="item"th:href="@{/stars-rank}">
Star's Rank
</a><divclass="right menu"><aclass="ui item"th:href="@{/login}"sec:authorize="!isAuthenticated()">
Login
</a><aclass="ui item"sec:authentication="name"sec:authorize="isAuthenticated()"></a><aclass="ui item"th:href="@{/logout}"sec:authorize="isAuthenticated()">
Logout
</a></div></div><divclass="ui divider"></div></header></body></html>
The xmlns:sec="http://www.thymeleaf.org/extras/spring-security" XML namespace declaration has been added to enable the usage of Thymeleaf-Spring Security tags;
The sec:authorize="hasRole('STAR-VOTE-ADMIN')" attribute is added to the "Add Star" menu item, allowing only individuals with the role STAR-VOTE-ADMIN to see and access this link;
The sec:authorize="hasAnyRole('STAR-VOTE-ADMIN','STAR-VOTE-USER')" attribute is added to the "Star's List" menu item, allowing individuals with either the role STAR-VOTE-ADMIN or STAR-VOTE-USER to see and access this link;
Inside the right-aligned portion of the menu, a new <a> tag has been added to display the authenticated user's name. It uses the sec:authentication=”name” as the text value to display the name of the authenticated user.
Update the stars-list.html
Let’s go to the stars-list.html file and apply the following changes (highlighted in bold).
<!DOCTYPE html><htmllang="en"xmlns:th="http://www.thymeleaf.org"xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
...
<main>
...
<divclass="ui container"><divclass="ui basic segment"><divclass="ui five stackable doubling centered cards"><divclass="card"th:each="star:${stars}">
...
<divclass="extra content"><divclass="ui large circular black label">
Votes
<divclass="detail"th:text="${star.votes}">214</div></div><aclass="ui right floated primary basic blue button"th:href="@{/vote-stars/{id}(id = ${star.id})}"sec:authorize="hasRole('STAR-VOTE-USER')">Vote</a></div></div></div></div></div></main>
...
</body></html>
Added the Thymeleaf-Spring Security XML namespace declaration, xmlns:sec="http://www.thymeleaf.org/extras/spring-security";
Added the sec:authorize="hasRole(‘STAR-VOTE-USER’)" attribute to the <a> tag for voting, specifying that only users with the role STAR-VOTE-USER can see and interact with the "Vote" button.
Update the StarUIController class
Open StarUIController class and add the following method:
Here’s an overview of the WebSecurityConfig class:
Annotated with @Configuration and @EnableWebSecurity, indicating that this class is a configuration class for web security;
Defines two constants: STAR_VOTE_ADMIN and STAR_VOTE_USER, representing the role names used in the application.
The @Value annotation is used to retrieve the value of a configuration property named jwt.auth.converter.principal-attribute. This value is assigned to the variable principalAttribute in the class. If the property is not defined, the variable will be assigned a default value of "sub".
Contains a securityFilterChain method, which configures the security filter chain for the application using the provided HttpSecurity object. This method defines various security rules and configurations, such as authorization rules for different endpoints, login configuration, JWT token validation, logout configuration, and disabling CSRF protection.
Defines a oAuth2UserService bean, which configures the OAuth2 user service used for loading user information from the OIDC provider. It overrides the default behavior of OidcUserService to customize the user details returned.
Provides a jwtAbstractAuthenticationTokenConverter method, which returns a converter that converts a JWT token to an AbstractAuthenticationToken. This converter extracts the granted authorities from the JWT and combines them with the resource roles obtained from the JWT to create the authentication token.
Contains helper methods, such as extractRoles and getPrincipalClaimName, which are used to extract information from the JWT token. The implementation of the extractRoles method will be covered in the upcoming articles, as it is specific to how Keycloak and Okta construct the JWT token payload.
StarVote application fails to start!
If you attempt to start the StarVote application after implementing the changes outlined in this article, you may encounter an exception, as shown below:
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of method setFilterChains in org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration required a bean of type'org.springframework.security.oauth2.client.registration.ClientRegistrationRepository' that could not be found.
Action:
Consider defining a bean of type'org.springframework.security.oauth2.client.registration.ClientRegistrationRepository'in your configuration.
Don’t panic! We will solve it in the next articles.
Up Next
We will delve into enabling Keycloak as the Identity Provider for the StarVote application.