Skip to content

devops-vishalacharya/springboot-keycloak

Repository files navigation

Keycloak Spring Boot Authentication System

A production-ready authentication system using Keycloak as the identity provider and Spring Boot with OAuth2 resource server configuration.

Features

  • JWT Authentication - Secure token-based authentication
  • Role-based Authorization - USER and ADMIN role management
  • Password Reset - Admin-managed password reset functionality
  • CORS Support - Cross-origin resource sharing enabled
  • Health Monitoring - Spring Boot Actuator endpoints
  • Docker Deployment - Containerized with Docker Compose

Quick Start

Prerequisites

  • Docker and Docker Compose
  • Java 21+ (for local development)
  • Maven 3.6+ (for local development)

1. Environment Setup

# Copy environment template
cp .env.working .env

# Edit environment variables if needed
nano .env

2. Start Services

# Start all services
docker-compose up -d

# Check service status
docker-compose ps

3. Run Tests

# Execute test suite
./test.sh

API Endpoints

Public Endpoints

  • GET /api/public - Public access endpoint

Authentication Required

  • GET /api/authenticated - Basic authentication check
  • GET /api/logout - Logout with Keycloak redirect

Role-based Endpoints

  • GET /api/user - Requires USER role
  • GET /api/admin - Requires ADMIN role

Password Management

  • POST /api/password/reset - Admin password reset
  • POST /api/password/change - User password change

Health Monitoring

  • GET /actuator/health - Application health status

Authentication Flow

  1. Get Access Token
curl -X POST http://localhost:8081/realms/springboot-realm/protocol/openid-connect/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=password&client_id=springboot-backend&client_secret=my-client-secret&username=user&password=password"
  1. Use Token in Requests
curl -H "Authorization: Bearer YOUR_TOKEN" http://localhost:8080/api/user

Configuration

Environment Variables

KEYCLOAK_ADMIN=admin
KEYCLOAK_ADMIN_PASSWORD=admin123
KEYCLOAK_ADMIN_USERNAME=admin
POSTGRES_DB=keycloak
POSTGRES_USER=keycloak
POSTGRES_PASSWORD=keycloak123

Default Users

  • Admin: admin / admin123 (ADMIN role)
  • User: user / password (USER role)

Development

Local Development

# Build application
mvn clean package -DskipTests

# Run locally (requires Keycloak running)
java -jar target/keycloak-springboot-app-0.0.1-SNAPSHOT.jar

Docker Build

# Rebuild application container
docker-compose build app --no-cache
docker-compose up -d app

Architecture

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   Frontend      │    │  Spring Boot    │    │   Keycloak      │
│   Application   │◄──►│   Resource      │◄──►│   Identity      │
│                 │    │   Server        │    │   Provider      │
└─────────────────┘    └─────────────────┘    └─────────────────┘
                                │                        │
                                ▼                        ▼
                       ┌─────────────────┐    ┌─────────────────┐
                       │   Application   │    │   PostgreSQL    │
                       │   Database      │    │   Database      │
                       └─────────────────┘    └─────────────────┘

Security Features

  • JWT Token Validation - All protected endpoints validate JWT tokens
  • Role-based Access Control - Method-level security with @PreAuthorize
  • CORS Configuration - Secure cross-origin requests
  • Password Encryption - Bcrypt password hashing
  • Session Management - Stateless JWT-based sessions

Troubleshooting

Common Issues

  1. Service Not Starting
# Check logs
docker-compose logs app
docker-compose logs keycloak
  1. Authentication Failures
# Verify Keycloak is running
curl http://localhost:8081/realms/springboot-realm/.well-known/openid_configuration
  1. Token Issues
# Check token validity
curl -H "Authorization: Bearer YOUR_TOKEN" http://localhost:8080/api/authenticated

Reset Environment

# Stop and remove all containers
docker-compose down -v

# Restart fresh
docker-compose up -d

Testing with curl

1. Test Public Endpoint

curl http://localhost:8080/api/public

2. Get User Access Token

curl -X POST http://localhost:8081/realms/springboot-realm/protocol/openid-connect/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=password&client_id=springboot-backend&client_secret=my-client-secret&username=user&password=password"

3. Get Admin Access Token

curl -X POST http://localhost:8081/realms/springboot-realm/protocol/openid-connect/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=password&client_id=springboot-backend&client_secret=my-client-secret&username=admin&password=password"

4. Test Authenticated Endpoint

# Set your token first
TOKEN="your_access_token_here"

curl -H "Authorization: Bearer $TOKEN" http://localhost:8080/api/authenticated

5. Test User Role Endpoint

curl -H "Authorization: Bearer $TOKEN" http://localhost:8080/api/user

6. Test Admin Role Endpoint

# Use admin token
ADMIN_TOKEN="your_admin_token_here"

curl -H "Authorization: Bearer $ADMIN_TOKEN" http://localhost:8080/api/admin

7. Test Health Endpoint

curl http://localhost:8080/actuator/health

8. Test Password Reset (Admin only)

curl -X POST http://localhost:8080/api/password/reset \
  -H "Authorization: Bearer $ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"username": "user", "newPassword": "newpassword123"}'

9. Test Password Change (User)

curl -X POST http://localhost:8080/api/password/change \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"currentPassword": "password", "newPassword": "newpassword123"}'

10. Test Token Refresh

# Use refresh token from login response
curl -X POST http://localhost:8081/realms/springboot-realm/protocol/openid-connect/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=refresh_token&client_id=springboot-backend&client_secret=my-client-secret&refresh_token=your_refresh_token_here"

11. Test Logout

curl http://localhost:8080/api/logout

Complete Test Script

#!/bin/bash

echo "=== Testing Keycloak Spring Boot API ==="

# Test public endpoint
echo "1. Testing public endpoint..."
curl -s http://localhost:8080/api/public | jq .

# Get user token
echo "2. Getting user token..."
USER_RESPONSE=$(curl -s -X POST http://localhost:8081/realms/springboot-realm/protocol/openid-connect/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=password&client_id=springboot-backend&client_secret=my-client-secret&username=user&password=password")

USER_TOKEN=$(echo $USER_RESPONSE | jq -r .access_token)

# Test authenticated endpoint
echo "3. Testing authenticated endpoint..."
curl -s -H "Authorization: Bearer $USER_TOKEN" http://localhost:8080/api/authenticated | jq .

# Test user role endpoint
echo "4. Testing user role endpoint..."
curl -s -H "Authorization: Bearer $USER_TOKEN" http://localhost:8080/api/user | jq .

# Get admin token
echo "5. Getting admin token..."
ADMIN_RESPONSE=$(curl -s -X POST http://localhost:8081/realms/springboot-realm/protocol/openid-connect/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=password&client_id=springboot-backend&client_secret=my-client-secret&username=admin&password=password")

ADMIN_TOKEN=$(echo $ADMIN_RESPONSE | jq -r .access_token)

# Test admin role endpoint
echo "6. Testing admin role endpoint..."
curl -s -H "Authorization: Bearer $ADMIN_TOKEN" http://localhost:8080/api/admin | jq .

# Test health endpoint
echo "7. Testing health endpoint..."
curl -s http://localhost:8080/actuator/health | jq .

echo "=== All tests completed ==="

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published