Keycloak Authentication as a Backing Service for .NET Modular Monoliths Architecture
We are diving deep into how to leverage Keycloak as a backing service within a modular monolithic architecture.
We’ll explore how Keycloak can effectively manage identity and access in our application, making it more modular, scalable, and secure.
Why Keycloak?
Keycloak is an open-source Identity and Access Management (IAM) solution that provides robust features such as Single Sign-On (SSO), Identity Brokering, and Social Login. Instead of building authentication and authorization mechanisms from scratch, we can utilize Keycloak to handle these critical functionalities.
- Single Sign-On (SSO): Allows users to authenticate once and gain access to multiple applications without re-entering credentials.
- Identity Brokering and Social Login: Enables integration with external identity providers like Google, Facebook, and GitHub.
- User Federation: Connects Keycloak to existing user databases such as LDAP or Active Directory.
- Centralized Management: Offers a unified interface for managing users, roles, and permissions.
- Standard Protocols: Supports OAuth 2.0, OpenID Connect, and SAML 2.0, ensuring compatibility with various applications.
Keycloak as a Cloud-Native Backing Service
In our Modular Monolithic Architecture, we have different modules, such as Catalog, Basket, and Ordering, each responsible for specific functionalities. The Identity Module handles user authentication and authorization, which is critical for the security of the entire application.
Cloud-Native Backing Services
Keycloak serves as a cloud-native backing service in our architecture. This means it runs as a separate service, independent of our main application, and provides identity and access management functionalities.
By decoupling identity operations from the main application, we achieve:
- Better Modularity: Each module operates independently, making the architecture more modular.
- Scalability: The application can scale more efficiently as identity management is handled separately.
- Maintainability: Managing identity separately simplifies updates and maintenance without affecting the core application.
Moving Towards Microservices
As we transition to a microservices architecture, Keycloak can be the first microservice extracted from our monolithic application.
Extracting Identity Operations
By handling “User Identity” operations in a separate Keycloak container, we make our architecture more modular and easier to manage. This approach is crucial for scaling and maintaining our application over time. Here’s how it looks:
This image shows how Keycloak, as an identity provider, is decoupled from the main application, allowing us to manage it as an independent microservice.
Integrating Keycloak with Docker Compose
Now, let’s integrate Keycloak into our Docker environment. We will set it up as a backing service for identity management, ensuring it is part of our modular monolithic architecture.
Step 1: Docker Compose Configuration
To begin, we need to configure Keycloak in our docker-compose.yml
file. This file defines all the services required for our application, including databases, caches, and message brokers. Here’s the configuration:
version: '3.4'
services:
eshopdb:
image: postgres
distributedcache:
image: redis
seq:
image: datalust/seq:latest
messagebus:
image: rabbitmq:management
identity:
image: quay.io/keycloak/keycloak:24.0.3
volumes:
postgres_eshopdb:
- Keycloak Service: We added a new service named
identity
that uses the Keycloak imagequay.io/keycloak/keycloak:24.0.3
. This service will run Keycloak, providing identity and access management functionalities to our application.
Step 2: Override Configurations
Next, we define the specific configurations for the Keycloak service in the docker-compose.override.yml
file. This file allows us to set environment variables, restart policies, and port mappings, making the Keycloak service more flexible and configurable.
version: '3.4'
services:
eshopdb:
container_name: eshopdb
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
- POSTGRES_DB=EShopDb
restart: always
ports:
- "5432:5432"
volumes:
- postgres_eshopdb:/var/lib/postgresql/data/
distributedcache:
container_name: distributedcache
restart: always
ports:
- "6379:6379"
seq:
container_name: seq
environment:
- ACCEPT_EULA=Y
restart: always
ports:
- "5341:5341"
- "9091:80"
messagebus:
container_name: messagebus
hostname: ecommerce-mq
environment:
- RABBITMQ_DEFAULT_USER=guest
- RABBITMQ_DEFAULT_PASS=guest
restart: always
ports:
- "5672:5672"
- "15672:15672"
identity:
container_name: identity
environment:
- KEYCLOAK_ADMIN=admin
- KEYCLOAK_ADMIN_PASSWORD=admin
restart: always
ports:
- "9090:8080"
command:
- start-dev
Identity Configurations:
- container_name: Sets the container name to
identity
. - environment: Specifies environment variables for Keycloak, including the admin username and password.
- restart: Ensures the container always restarts to maintain availability.
- ports: Maps port 8080 inside the container to 9090 on the host, making the Keycloak admin console accessible via
http://localhost:9090
. - command: The
start-dev
command is used to start Keycloak in development mode, simplifying the setup process for development environments.
Summary
In this article, we covered the following key points:
- Keycloak as an Identity Provider: We explored how Keycloak serves as the identity provider for our application, integrated as a backing service in our modular monolithic architecture.
- Docker Compose Configuration: We added Keycloak to the
docker-compose.yml
file to run it as a service. - Override Configurations: We specified detailed configurations for the Keycloak service in the
docker-compose.override.yml
file, including environment variables, restart policies, and port mappings.
This is step-by-step development of reference Modular Monoltihs Architecture on .NET used ASP.NET Web API, Docker, PostgreSQL, Redis, RabbitMQ, Keycloak, Seq, MassTransit, Entity Framework Core, CQRS, MediatR, DDD, Vertical Slice Architecture and Outbox Pattern implementation with using latest features of .NET 8 and C# 12.