Spring Cloud Gateway with KeyCloak and OAuth2

In this article I will show how to configure a KeyCloak server. And I will use it in a Spring Cloud and Spring Boot architecture as an authorization server where a Spring Cloud Gateway will try to authenticate.

Content

  • Keycloak
  • Authorization Server
  • Resources Server
  • Client Server

You can also find all the details in the following video.

The code used in the article can be found in this repository.

Keycloak

Keycloak is a tendency for identity and access management. Today, I will show how to configure it as an Authorization Server in front of a Spring Cloud Gateway client.

First of all, Keycloak is considered as a single sign-on system. This means that multiple clients can delegate the end user authentication to Keycloak.

Let’s say I am trying to enter a protected building where each door gives a personalized experience of leisure. But each door is locked and only opens upon the presentation of a key card. I can choose whatever a personalized leisure room I want to enter. It’s like registering on some different websites.

The keycard represents Keycloak. If the door is able to read the keycard, it means that the door is connected to the central server of Keycloak as a trusted client. I need, by myself, to register on the central server as a regular user, to also be known by Keycloak.

Finally, when trying to enter a room, a message will be displayed on the door to confirm that’s me, what’s behind the door, and which personal data will be used. If I accept, the room will be able to access some of my personal data to give me a personalized leisure experience. The room, the client, never asked me about my identity. The form on the screen comes from the central server from Keycloak. The client delegated the authentication to Keycloak.

Let’s represent this in the real world. I’m still the end user. The doors are the websites which will use some of my personal data to give me a personalized experience. And the key card is my credentials of my account in Keycloak.

I’ve created a user account in Keycloak. This will be my master account, the only account needed for all the websites. Each website must be also registered with Keycloak as trusted clients. A secured ID and secret will be used to trust and authenticate the communication from each client.

Finally, the data requested by the websites will be stored in third parties applications. This data is protected behind Keycloak. If any website wants to access my personal data located on those third applications, Keycloak must trust the website, certify I’m the one which tries to access the data, and validate which data will be accessed. Those are called the resource servers.

Okay, all of this is based on the already known OAuth2 protocol and OpenID Connect.

Authorization Server

version: '3'

services:
  db:
    image: postgres:13.5
    environment:
      POSTGRES_HOST_AUTH_METHOD: trust
      POSTGRES_USER: my_admin
      POSTGRES_PASSWORD: my_password
      POSTGRES_DB: keycloak_db
    ports:
      - 5432:5432
  kc:
    image: quay.io/keycloak/keycloak:legacy
    environment:
      DB_VENDOR: POSTGRES
      DB_ADDR: db
      DB_DATABASE: keycloak_db
      DB_USER: my_admin
      DB_SCHEMA: public
      DB_PASSWORD: my_password
      KEYCLOAK_HOSTNAME: backend-keycloak-auth
      KEYCLOAK_USER: kc_admin
      KEYCLOAK_PASSWORD: kc_password
    ports:
      - 8080:8080
    depends_on:
      - db

Let’s start by creating my Keycloak server. I will use a Docker-Compose system. On the first image, I have the database where Keycloak can save all its data and configuration. And on the second image, I have Keycloak itself.

At lines 8 and 9 are the credentials to connect to the database. And at line 10 is the name of the database. And now, from line 13, is the image for the Keycloak instance. First, I have the same information to connect to the database (at lines 18 to 21). Then, at line 22 I indicate the hostname I want to access the Keycloak instance. I had to add the same host name to the /etc/hosts file too with the localhost address. And finally, at lines 23 and 24, I’ve added the credentials to connect to the Keycloak administration console.

When starting Keycloak, the first thing I can see is the Realm. The Realm is like a tenant. It’s like a group of clients. It’s like the building where we’re located all the doors to the leisure rooms. I will create my own Realm to avoid using the master one.

Now that I’ve created my Realm, I need to get the URL all the clients will need to call, to delegate the Authentication.

I will create now my personal account, my user account.

At each user creation, I can indicate some actions such as: completing the profile information, resetting the password, or to verify the email.

Before going to the client creation, I first need to create the scopes needed by the client to access my resources server.

Let’s go now with my client.

Those are the callback URLs that must be trust by Keycloak after the authentication is successful.

Here I can choose which login form will be displayed when the authentication is delegated to Keycloak.

And finally, I indicate which scopes are necessary for this client.

Let’s get now the client security information and go to my client server.

Resources Server

Ok, my Keycloak server is ready. I have now a Sprint Boot application as a resource server and a Spring Cloud Gateway application as a client server. My Spring Cloud Gateway needs to access the resource server, but my resource server is protected behind Keycloak. So I must configure my resource server to validate the authentication tokens against Keycloak. And configure my Spring Cloud Gateway to delegate the authentication to Keycloak.

server:
  port: 8082

spring:
  application.name: backend-resources
  # the current backend is configured to be used as a resource server
  # then, I must indicate the URI of the backend-auth to be used and which token to be used
  security:
    oauth2:
      resourceserver:
        jwt:
          issuer-uri: http://backend-keycloak-auth:8080/auth/realms/my_realm

In the last line I have the endpoint I’ve copied from the Realm settings. This way, the resource server knows how to validate an authentication token. Let’s go now with the Spring Gateway.

Client Server

server:
  port: 8083

spring:
  application.name: backend-gateway-client
  cloud:
    gateway:
      routes:
        - id: resources
          uri: http://backend-resources:8082/messages
          predicates:
            Path=/messages/**
          filters:
            TokenRelay=
  security:
    oauth2:
      client:
        registration:
          gateway:
            provider: my-provider
            client-id: my_client
            client-secret: xxx
            authorization-grant-type: authorization_code
            redirect-uri: "http://backend-gateway-client:8083/login/oauth2/code/{registrationId}"
            scope: openid, message.read
        provider:
          my-provider:
            issuer-uri: http://backend-keycloak-auth:8080/auth/realms/my_realm

At lines 21 and 22 are the clientID and client-secret I’ve copied from my created client. And at line 28 is again the endpoint of my Realm.

After the logging is successful, I can see the active sessions of the user in Keycloak. I can also see the sessions created by my client.

The length of the sessions, the way they are created and more can be configured in the settings.

Conclusion

  • I’ve created a Keycloak instance with a connected database.
  • I’ve created a Realm which will group all my clients and users.
  • I’ve created a single user as an end user which will be used to logging into the client website.
  • I’ve created the Scopes needed by my resource server.
  • I’ve created my client and obtained the ID and secret.
  • I’ve indicated to my client which scopes and authorization flows are necessary.
  • Then I’ve added the Keycloak URL to my resource server and client server.
  • And I’ve also copied the client-ID and client-secret to my client server.

References

Repository

My New ebook, How to Master Git With 20 Commands, is available now.

One response to “Spring Cloud Gateway with KeyCloak and OAuth2”

  1. […] here, it’s the standard protocol for a backend authentication. I’ve already written an article about […]

    Like

Leave a comment

A WordPress.com Website.