Jakub Bajorek

DevOps

Mar 07, 2021 in Development

Open ID: connecting Keycloak and RabbitMQ [Part 1]

Looking for help with Keycloak and RabbitMQ or trying to understand why and how to use them together? I’m happy to bring you the answers with my mini-series of articles on connecting these two open-source applications together! We’re going to start with a small overview. In the end of each article you’ll find a link to another part of the series. 

Here we go!

1. Overview

Nowadays, when microservice architecture is very popular and one client uses multiple applications at once, companies use central service to provide common authentication and authorization. Its main purpose is to authorize access to different resources while giving credentials only once, alongside with further passwordless authentication. If we decide to implement such pattern, in the end we will have:

- Database which stores all users’ credentials and access rules to all our services

- Management by graphic interface

- Management by API

- Possibility to perform authentication and authorization using one of protocols

If our system contains many services, there is often needed to provide reliable and fast communication between them. Software called message brokers is often used as an alternative to most common way of exposing service’s API. It allows all connected services to exchange messages according to configured rules in secure way using specific protocol. From this article perspective important feature is that such software often has its authentication and authorization mechanisms built in.

Main goal of this article would be to show a way to connect two applications:

- Keycloak – popular open-source identity management and access management software

- RabbitMQ – message broker

We would like to use Keycloak server as authentication and authorization method instead of internal RabbitMQ auth backend.

2. RabbitMQ

Let’s assume, that we have RabbitMQ instance running at keycloak-rabbit:5672. To access it we will use default AMQP protocol. 

Create file definitions.json. It will be loaded by our message broker at the start and populate instance with described objects, so it’s kind of start state for it. As for password_hash field, please refer to RabbitMQ documentation how to generate correct value. This will create user admin, vhost keycloak_test and allow access this user to defined vhost.

//================================================
definitions.json
//================================================

{
   "rabbit_version" : "3.7.8",
   "policies" : [],
   "parameters" : [],
   "topic_permissions" : [],
   "global_parameters" : [
      {
         "name" : "cluster_name",
         "value" : "keycloak-rabbit"
      }
   ],
   "users" : [
{"name":"admin","password_hash":"…","hashing_algorithm":"rabbit_password_hashing_sha256","tags":"administrator"}
   ],
   "permissions" : [
    {
      "user": "admin",
      "vhost": "keycloak_test",
      "configure": ".*",
      "write": ".*",
      "read": ".*"
    }
   ],
   "vhosts" : [
      {
         "name" : "keycloak_test"
      }
   ],
   "bindings" : [],
   "queues": [],
   "exchanges" : []
}

//================================================

Edit main configuration file of message broker rabbitmq.conf. We should tell RabbitMQ to load our definitions and also configure rabbitmq-auth-backend-http plugin (https://github.com/rabbitmq/rabbitmq-auth-backend-http). It allows us to switch default internal authentication and authorization backend for one based on external http API calls. When external client will try to access RabbitMQ, broker will make request to selected endpoint and according to received response it will allow or deny access. Let’s say that our external service will be located at keycloak-proxy:3000. To not disable possibility to access instance with internal credentials we set new plugin as second auth backend.

//================================================

rabbitmq.conf

//================================================

loopback_users.guest = false

listeners.tcp.default = 5672

default_pass = …

default_user = admin

default_vhost = keycloak_test

management.load_definitions = /srv/definitions.json

auth_backends.1 = http

auth_backends.2 = internal

auth_http.http_method = post

auth_http.user_path = http://keycloak-proxy:3000/user

auth_http.vhost_path = http://keycloak-proxy:3000/vhost

auth_http.resource_path = http://keycloak-proxy:3000/resource

auth_http.topic_path = http://keycloak-proxy:3000/topic

//================================================

Although rabbitmq-auth-backend-http plugin is added to RabbitMQ installation by default, we must turn it on in the command line manually.

Rabbitmq-plugins enable –offline rabbitmq_auth_backend_http

At this point our RabbitMQ instance will try to authenticate and authorize each access to resource by sending requests to defined endpoints:

POST http://keycloak-proxy:3000/user

POST http://keycloak-proxy:3000/vhost

POST http://keycloak-proxy:3000/resource

POST http://keycloak-proxy:3000/topic

In response it expects plain string with status 200:

- allow

- deny

- allow <tag> - only in case of user endpoint, when selected user have tag attached.

Part two of the series 

I'm already working on the next parts of the series so stay tuned - they're coming soon!

Do you need more information about this topic?

Schedule a call with our developers

Let's talk!

Back to top