A production-grade microservices architecture demonstrating enterprise-level security protocols (mTLS, TLS, RBAC, CBAC) with optimized inter-service communication using RSocket and Protocol Buffers. This project proves that comprehensive security measures can be implemented without sacrificing performance or introducing unacceptable latency.
- Architecture Overview
- Key Features
- Technology Stack
- Prerequisites
- Quick Start
- API Documentation
- Security Model
- Project Structure
- Database Schema
The platform consists of four microservices communicating over mTLS-secured RSocket connections:
- Single HTTPS entry point for all client requests
- Validates access tokens and session IDs via Auth Service
- Routes authenticated requests to appropriate services
- Manages HTTP cookies (access token, session ID, refresh token)
- Central authentication and authorization authority
- Issues and validates JWT tokens (access, refresh, service)
- Implements Role-Based Access Control (RBAC)
- Manages guest user flows
- Binds refresh tokens to devices using
Client-CityandUser-Agentheader - Sends suspicious events to Monitoring Service
- Domain-specific business logic for user management
- Creates and stores user profile details and addresses
- Demonstrates Claim Based Access Control(CBAC) in service-to-service authorization using service tokens
- Validates location data against predefined cities/countries
- Sends suspicious events to Monitoring Service
- Receives fire-and-forget events from other services
- Logs suspicious activities to PostgreSQL
- Non-blocking event ingestion to avoid performance impact
- Mutual TLS (mTLS): All inter-service communication uses client certificate authentication
- TLS 1.3: External HTTPS connections to API Gateway
- JWT Authentication: RS512-signed tokens with separate keys for access, refresh, and service tokens
- Session Management: Redis-backed sessions with access token + session ID binding
- RBAC: Role-based authorization (roles: GUEST_USER, USER)
- CBAC: Claim-based authorization using service tokens with service and destination claims
- Refresh Token Security: Device-bound refresh tokens with city and device based validation
- Suspicious Event Monitoring: Automated logging of security events (failed logins, token theft attempts, etc.)
- RSocket Protocol: Binary, reactive communication with backpressure support
- Protocol Buffers: Efficient serialization (smaller payload than JSON)
- Non-blocking I/O: Fully reactive Spring WebFlux stack
- Connection Reuse: Persistent RSocket connections between services
- Fire-and-Forget: Monitoring events don't block request processing
| Component | Technology | Version |
|---|---|---|
| Runtime | Java | 25 |
| Framework | Spring Boot | 4.0.3 |
| Build Tool | Maven | 3.9.12 |
| Communication | Spring RSocket | - |
| Serialization | Protocol Buffers | 4.28.2 |
| Database | PostgreSQL | 18-alpine |
| Database | Redis | 8.2.4-alpine3.22 |
| Containerization | Docker & Docker Compose | - |
| Security | OpenSSL, Java Keytool | - |
Before running this project, ensure you have the following installed:
- Docker (version 20.10+)
- Docker Compose (version 2.0+)
- Git (for cloning the repository)
- OpenSSL (for certificate generation via setup.sh)
- Java (JDK 17+ or later, required for keytool)
- curl or Postman (for API testing)
Note: Maven, PostgreSQL, and Redis do not need to be installed locally because they run inside Docker containers.
git clone https://github.com/Rungrukuk/Reactive-Microservices-Platform.git
cd Reactive-Microservices-PlatformThe setup.sh script generates all required TLS certificates, JWT keys, and environment variables:
chmod +x setup.sh
./setup.shWhat this does:
- Creates a Certificate Authority (CA)
- Generates signed certificates for all services (redis, auth, user, api-gateway, monitoring)
- Creates PKCS12 keystores and a shared truststore
- Generates RSA-4096 key pairs for JWT signing (access, refresh, service tokens)
- Writes a
.envfile with all credentials and base64-encoded keys
docker compose up --buildFirst startup will take 3-5 minutes as Docker:
- Builds images for 4 Spring Boot services
- Pulls PostgreSQL and Redis images
- Initializes 4 databases with schemas and seed data
- Waits for health checks to pass
You'll see:
✓ postgres Healthy
✓ redis Healthy
✓ monitoring-service Started
✓ auth-service Started
✓ user-service Started
✓ api-gateway Started
docker compose psAll services should show status Up or healthy.
The API Gateway is now accessible at https://localhost:8443. See API Documentation for examples.
All requests must include the Client-City header (simulates IP geolocation by the frontend). Except https://localhost:8443/createUserDetails endpoint cookies can be discarded for all other endpoints as authentication service will generate new guest user and check if guest user has enough permission for the original request.
https://localhost:8443
Note: The API uses a self-signed certificate. In curl, use the
-kflag to skip verification. In Postman, disable "SSL certificate verification" in Settings.
Creates a new guest user session.
Endpoint: GET /
Headers:
Client-City: Bakucurl Example:
curl -k https://localhost:8443/ \
--header 'Client-City: Baku' \
-c cookies.txt -vResponse:
{
"userStatus": "AUTHORIZED_GUEST_USER"
}Sets Cookies:
accessToken- JWT access token (24h expiry)sessionId- Session identifierrefreshToken- Not set for guest users
Registers a new user account and upgrades from guest to authenticated user.
Endpoint: POST /register
Headers:
Content-Type: application/json
Client-City: BakuRequest Body:
{
"email": "user@example.com",
"password": "SecurePass123!",
"rePassword": "SecurePass123!"
}curl Example:
curl -k https://localhost:8443/register \
--header 'Content-Type: application/json' \
--header 'Client-City: Baku' \
-c cookies.txt -b cookies.txt \
-d '{
"email": "user@example.com",
"password": "SecurePass123!",
"rePassword": "SecurePass123!"
}'Response (Success):
{
"userStatus": "AUTHORIZED_USER",
"message": "User created successfully",
"status": "OK"
}Sets Cookies:
accessToken- New JWT for authenticated usersessionId- New session IDrefreshToken- Long-lived refresh token (7 days)
Validation Rules:
- Email must be valid format
- Password must be at least 8 characters, must include at least 1 lower-case, 1 upper-case, 1 special character, and 1 number
- Password and rePassword must match
- Email must be unique
Authenticates an existing user.
Endpoint: POST /login
Headers:
Content-Type: application/json
Client-City: BakuRequest Body:
{
"email": "user@example.com",
"password": "SecurePass123!"
}curl Example:
curl -k https://localhost:8443/login \
--header 'Content-Type: application/json' \
--header 'Client-City: Baku' \
-c cookies.txt -b cookies.txt \
-d '{
"email": "user@example.com",
"password": "SecurePass123!"
}'Response (Success):
{
"userStatus": "AUTHORIZED_USER",
"message": "Logged in successfully",
"status": "OK"
}Response (Failure):
{
"userStatus": "AUTHORIZED_GUEST_USER",
"message": "Email or password is incorrect",
"status": "BAD_REQUEST"
}Sets Cookies:
- Same as registration (new tokens and session)
Saves user profile and address information. Requires authentication (must login or register first).
Endpoint: POST /user-details
Headers:
Content-Type: application/json
Client-City: BakuRequest Body:
{
"email": "user@example.com",
"name": "John",
"surname": "Doe",
"phoneNumber": "+994501234567",
"country": "AZE",
"state": "",
"city": "Baku",
"postalCode": "AZ1000",
"addressLine1": "123 Main Street",
"addressLine2": "Apt 4B",
"isDefault": "true"
}curl Example:
curl -k https://localhost:8443/user-details \
--header 'Content-Type: application/json' \
--header 'Client-City: Baku' \
-b cookies.txt \
-d '{
"email": "user@example.com",
"name": "John",
"surname": "Doe",
"phoneNumber": "+994501234567",
"country": "AZE",
"state": "",
"city": "Baku",
"postalCode": "AZ1000",
"addressLine1": "123 Main Street",
"addressLine2": "Apt 4B",
"isDefault": "true"
}'Response (Success):
{
"userStatus": "AUTHORIZED_USER",
"message": "User details created successfully",
"status": "OK"
}Response (Unauthorized):
{
"userStatus": "UNAUTHORIZED_GUEST_USER"
}Available Locations:
| Country | ISO3 | Cities | Postal Codes |
|---|---|---|---|
| Azerbaijan | AZE | Baku, Khirdalan, Ganja | AZ1000, AZ1001, AZ0101, AZ2000 |
| Turkey | TUR | Istanbul | TR34000, TR34010 |
Complete workflow for a new user:
# 1. Create guest session
curl -k https://localhost:8443/ \
--header 'Client-City: Baku' \
-c cookies.txt
# 2. Register new account
curl -k https://localhost:8443/register \
--header 'Content-Type: application/json' \
--header 'Client-City: Baku' \
-c cookies.txt -b cookies.txt \
-d '{"email":"test@test.com","password":"Pass123!","rePassword":"Pass123!"}'
# 3. Create user details
curl -k https://localhost:8443/user-details \
--header 'Content-Type: application/json' \
--header 'Client-City: Baku' \
-b cookies.txt \
-d '{"email":"test@test.com","name":"Test","surname":"User","phoneNumber":"+994501234567","country":"AZE","city":"Baku","postalCode":"AZ1000","addressLine1":"Street 1"}'┌──────┐ ┌─────────────┐ ┌──────────────┐ ┌────────────────┐
│Client│ │ API Gateway │ │ Auth Service │ │ Domain Service │
└──┬───┘ └──────┬──────┘ └──────┬───────┘ └───────┬────────┘
│ │ │ │
│ 1. HTTPS Request │ │ │
│ + accessToken cookie │ │ │
│ + sessionId cookie │ │ │
│ + Client-City header │ │ │
│──────────────────────────────>│ │ │
│ │ │ │
│ │ 2. Validate Token + Session │ │
│ │ (RSocket mTLS) │ │
│ │───────────────────────────────>│ │
│ │ │ │
│ │ 3. AuthResponse │ │
│ │ + serviceToken │ │
│ │<───────────────────────────────│ │
│ │ │
│ │ 4. Forward to Service │
│ │ (RSocket mTLS) │
│ │─────────────────────────────────────────────────────>│
│ │ Response │
│ 5. Response + Set-Cookie │<─────────────────────────────────────────────────────│
│<──────────────────────────────│
| Token Type | Lifetime | Purpose | Storage |
|---|---|---|---|
| Access Token | 24 hours | Authenticates user to API Gateway | HTTP-only cookie |
| Session ID | 24 hours | Binds to access token in Redis | HTTP-only cookie |
| Refresh Token | 7 days | Rotates access token when expired | HTTP-only cookie |
| Service Token | 5 minutes | Authorizes inter-service calls | Generated on-the-fly |
Service tokens are short-lived JWT tokens created by Auth Service and sent to downstream services. They contain:
{
"sub": "user-uuid",
"role": "USER",
"services": ["USER_SERVICE"],
"destinations": ["CREATE_USER_DETAILS"],
"iat": 1234567890,
"exp": 1234568190
}The target service validates the service token to ensure the request is authorized for that specific operation.
Refresh tokens are bound to a device using:
userId- The authenticated useruserAgent- Browser/client identifierclientCity- Geographic location from IP address
If any of these change, the refresh token is invalidated and the user must re-authenticate. This prevents stolen refresh tokens from being used on different devices or locations.
| Role | Permissions |
|---|---|
| GUEST_USER | Can access /, /register, /login |
| USER | Can access /, /user-details |
Permissions are stored in PostgreSQL and checked by Auth Service before issuing service tokens.
All services authenticate to each other using X.509 certificates:
- Each service has a private key and certificate signed by a common CA
- Services present their certificate during connection
- Peer certificates are validated against the truststore containing the CA certificate
- Connections fail if certificate validation fails (
client-auth: need)
This prevents unauthorized services from joining the network.
Microservices-Platform/
├── api_gateway/
│ ├── .mvn/
│ ├── src/
│ │ ├── main/
│ │ │ ├── java/platform/api_gateway/
│ │ │ │ ├── config/
│ │ │ │ ├── controller/
│ │ │ │ ├── security/
│ │ │ │ ├── service/
│ │ │ │ ├── util/
│ │ │ │ └── ApiGatewayApplication.java
│ │ │ ├── proto/
│ │ │ └── resources/
│ │ └── test/
│ ├── .gitignore
│ ├── Dockerfile
│ ├── mvnw
│ ├── mvnw.cmd
│ └── pom.xml
│
├── auth_service/
│ ├── .mvn/
│ ├── src/
│ │ ├── main/
│ │ │ ├── java/platform/auth_service/
│ │ │ │ ├── config/
│ │ │ │ ├── controller/
│ │ │ │ ├── domain/
│ │ │ │ ├── dto/
│ │ │ │ ├── repository/
│ │ │ │ ├── security/
│ │ │ │ ├── service/
│ │ │ │ ├── util/
│ │ │ │ └── AuthServiceApplication.java
│ │ │ ├── proto/
│ │ │ └── resources/
│ │ └── test/
│ ├── .gitignore
│ ├── Dockerfile
│ ├── mvnw
│ ├── mvnw.cmd
│ └── pom.xml
│
├── monitoring_service/
│ ├── .mvn/
│ ├── src/
│ │ ├── main/
│ │ │ ├── java/platform/monitoring_service/
│ │ │ │ ├── config/
│ │ │ │ ├── controller/
│ │ │ │ ├── domain/
│ │ │ │ ├── repository/
│ │ │ │ ├── service/
│ │ │ │ ├── util/
│ │ │ │ └── MonitoringServiceApplication.java
│ │ │ ├── proto/
│ │ │ └── resources/
│ │ └── test/
│ ├── .gitignore
│ ├── Dockerfile
│ ├── mvnw
│ ├── mvnw.cmd
│ └── pom.xml
│
├── user_service/
│ ├── .mvn/
│ ├── src/
│ │ ├── main/
│ │ │ ├── java/platform/user_service/
│ │ │ │ ├── config/
│ │ │ │ ├── controller/
│ │ │ │ ├── domain/
│ │ │ │ ├── dto/
│ │ │ │ ├── repository/
│ │ │ │ ├── service/
│ │ │ │ ├── util/
│ │ │ │ └── UserServiceApplication.java
│ │ │ ├── proto/
│ │ │ └── resources/
│ │ └── test/
│ ├── .gitignore
│ ├── Dockerfile
│ ├── mvnw
│ ├── mvnw.cmd
│ └── pom.xml
│
├── docker/
│ ├── postgres/
│ │ ├── 01-init-auth.sql
│ │ ├── 02-init-user.sql
│ │ ├── 03-init-location.sql
│ │ └── 04-init-log.sql
│ └── redis/
│ └── redis.conf
├── images/
│ └── Microservices.png
│
├── .gitignore
├── LICENSE.txt
├── docker-compose.yml
├── Readme.md
└── setup.sh
The project uses 4 PostgreSQL databases:
Stores authentication and authorization data.
Tables:
users- User accounts (email, hashed password, role)roles- Available roles (GUEST_USER, USER)permissions- Granular permissions (service + destination pairs)role_permissions- Many-to-many mapping of roles to permissionsrefresh_tokens- Refresh tokens bound to user + device + location
Stores user profile and address data.
Tables:
users- User profiles (name, surname, phone)addresses- Physical addressesuser_addresses- Links users to addresses (supports multiple addresses)
Reference data for locations (read-only seed data).
Tables:
countries- Country list with ISO codesstates- States/provinces per countrycities- Cities per statepostal_codes- Valid postal codes per city
Stores security monitoring events.
Tables:
monitoring_events- Suspicious activities logged by services- Indexed by: event_type, service_name, user_id, timestamp
This is an academic research project. For questions or suggestions, please open an issue.
MIT License
Built with Spring Boot, RSocket, Protocol Buffers, PostgreSQL, and Redis.
