Friday, May 18, 2018

Integrate Keycloak with Spring Boot


Security, I know this is so boring. But this is must. Years ago we have to expend much more time to implement the security of our enterprise applications, basically I'm talking about Web application security. But nowadays there are some Identity management tools that can be used to make easier our lives.

What is an Identity management tool ?

Simply it can be used as a security provider. We can delegate our security to a third party. It is just like hiring a security person or hiring a bodyguard. 

What is Keycloak ?

This is one of the best tools that can be used as an authentication management tool. Actually it is an identity provider. You can very easily integrate it to your Spring Boot applications and if you want you can integrate it with Spring Security also.

Advantages of Keycloak ?
  • It is light weight and fast.
  • Single sign on
  • It uses standard protocols such as OAuth 2.0, OpenID, SAML 2.0...etc.
  • Can be managed easily. 
  • Very easy to use with Keycloak adapters.
  • Very easy to enable social logins.

Here I'm not going to explain more details about Security concerns. I just wanted to explain the integration of Keycloak with Spring Boot.

First of all lets create a simple web application using Spring Boot. Go through following link to get started with Spring Boot if you are new to Spring Boot.

http://www.javafoundation.xyz/2017/06/spring-boot-hello-world-project.html#.W77OhWgzZnK

Here I'm going to create a simple web application to demonstrate this. 

ReservationController.java

package com.app.api;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;

@Controller
public class ReservationController {

    @GetMapping("/")
    public String home(){
        return "index";
    }

    @GetMapping("/reservation")
    public String getReservations(){
        return "reservations";
    }

    @GetMapping("/logout")
    public String logout(HttpServletRequest request) throws ServletException {
        request.logout();
        return "index";
    }
}


index.html

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Home</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>

    <h1>Home page</h1>
    <a href="/reservation">My Reservations</a>
</body>
</html>


reservations.html

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Reservations</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>

    <h2>Reservations page</h2>

    <a href="/logout">Logout</a>

</body>
</html>


You can download the full project from here.

https://github.com/raviyasas/keycloak-api-parent.git

I changed the default server port to 8090 in application.properties file. Just go to following links and check your application is working or not. 

http://localhost:8090/
http://localhost:8090/reservation

How to use Keycloak server
  • Download Keycloak server on https://www.keycloak.org/downloads.html then download the Standalone server distribution zip file.


  • Unzip it in your machine.
  • Go to bin folder. If you are on Windows OS just you can run standalone.bat file or if you are using a Linux distribution, you may use standalone.sh file to start the server. 
  • Normally it will run on port 8080. But you can change it as your wish, go to standalone\configuration\standalone.xml and change the port.
  • Once you run the server, go to http://localhost:8080/auth/

You will be able to see as follows.


This is to create an admin user. You can give any username and password you like. Once you create an admin user, you will be redirected to following page. 


You can see the red square "Administration Console". Just click it and then you will be redirected to following page which asks your admin credentials for the admin you've already created.



Once you are logged, then you can see below page.


Then you have to create a Realm. Just point your mouse to left side and then you will be able to see a button like below image.


Then you can create a realm by giving a realm name. 


Once you create a realm you will be able to see following page.



Then you need to create a client for you application. Click on Client in the left menu.


Then you can give any name for Client ID, I'm using it as "reservations". Once you created a client, scroll down and then you will be able to see "Valid redirect URIs".


It is the entry point to your application after you logged in to it. You may use the port which your Spring Boot application is running. My application is running on port 8090.

Then you have to add new Role. Go to Roles in the menu and click on Add Role.




Once you click, you will be able to see like this.


Add role name, I use it as "user". We need to use this role in our Spring Boot application. Once you save your role, Click again on Roles in menu. Then go to Default Roles.


Then you need to add your role to Default Roles. Select your role and click Add selected.

Now you can create a new user. Click on Users in the menu.


Then click on Add users and give an username and click save. I used it as "client".


Once you saved, just go to Credentials tab in your user and reset your password. Turn off temporary tab for the password. 

Now everything is done on Keycloak configuration side. Ready to go with Spring Boot app.

Configure Spring Boot application

It is actually simple application. What you need to do is, add Keycloak dependencies to your pom.xml and add configurations to application.properties file. 

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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>

 <groupId>com.app</groupId>
 <artifactId>api</artifactId>
 <version>0.0.1-SNAPSHOT</version>
 <packaging>jar</packaging>

 <name>api</name>
 <description>Demo project for Spring Boot</description>

 <parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>1.5.14.BUILD-SNAPSHOT</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>
  <keycloak.version>3.4.2.Final</keycloak.version>
 </properties>

 <dependencies>
  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-thymeleaf</artifactId>
  </dependency>
  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
  </dependency>
  <dependency>
   <groupId>org.keycloak</groupId>
   <artifactId>keycloak-spring-boot-starter</artifactId>
  </dependency>

  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-test</artifactId>
   <scope>test</scope>
  </dependency>
 </dependencies>

 <dependencyManagement>
  <dependencies>
   <dependency>
    <groupId>org.keycloak.bom</groupId>
    <artifactId>keycloak-adapter-bom</artifactId>
    <version>${keycloak.version}</version>
    <type>pom</type>
    <scope>import</scope>
   </dependency>
  </dependencies>
 </dependencyManagement>

 <build>
  <plugins>
   <plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
   </plugin>
  </plugins>
 </build>

 <repositories>
  <repository>
   <id>spring-snapshots</id>
   <name>Spring Snapshots</name>
   <url>https://repo.spring.io/snapshot</url>
   <snapshots>
    <enabled>true</enabled>
   </snapshots>
  </repository>
  <repository>
   <id>spring-milestones</id>
   <name>Spring Milestones</name>
   <url>https://repo.spring.io/milestone</url>
   <snapshots>
    <enabled>false</enabled>
   </snapshots>
  </repository>
 </repositories>

 <pluginRepositories>
  <pluginRepository>
   <id>spring-snapshots</id>
   <name>Spring Snapshots</name>
   <url>https://repo.spring.io/snapshot</url>
   <snapshots>
    <enabled>true</enabled>
   </snapshots>
  </pluginRepository>
  <pluginRepository>
   <id>spring-milestones</id>
   <name>Spring Milestones</name>
   <url>https://repo.spring.io/milestone</url>
   <snapshots>
    <enabled>false</enabled>
   </snapshots>
  </pluginRepository>
 </pluginRepositories>


</project>


application.properties

#server port of Spring Boot application is running
server.port=8090

#specify the url that keycloak server is running
keycloak.auth-server-url=http://localhost:8080/auth

#realm name which you used when you configured keycloak
keycloak.realm=api
keycloak.public-client=true
#client name you created
keycloak.resource=reservations

#created user, when you configured keycloak
keycloak.security-constraints[0].auth-roles[0]=user
#url pattern needs to be secured
keycloak.security-constraints[0].security-collections[0].patterns[0]=/reservation/*


This is a simple example of Spring Boot and Keycloak integration. You will be able to see more details, if you can go to Realm settings and then Login tab. Then you can very easily add functionalities for User registration, Remember me, Forgot password, Verify email...etc. You can download the full Spring Boot project from below link.

https://github.com/raviyasas/SpringBoot-Keycloak-demo.git