A comprehensive, easy-to-install Spring Boot security library that integrates seamlessly with Keycloak for authentication and authorization.
- β User Registration & Authentication - Complete user management with Keycloak
- β JWT Token Security - Stateless JWT-based authentication
- β Role & Group Management - Assign and manage user roles and groups
- β Password Reset - Built-in password reset functionality
- β User Profile Management - Update user profiles and information
- β Token Refresh - Automatic token refresh support
- β Easy Configuration - Simple setup with environment variables
- β RESTful API - Clean REST endpoints for all operations
- Java 21 or higher
- Maven 3.6 or higher
- Docker and Docker Compose (recommended for easy setup)
- OR Keycloak server (version 26.0.2 or compatible) if running manually
- Spring Boot 3.4.0 or higher
Note: This setup is configured for development - HTTP is enabled and SSL is not required. For production, you should configure HTTPS and proper SSL settings.
The easiest way to get started is using Docker Compose, which sets up Keycloak, PostgreSQL, and the Spring Boot application automatically.
git clone https://github.com/your-username/springboot-keycloak-security.git
cd springboot-keycloak-securitydocker-compose up -dThis will:
- Start PostgreSQL database for Keycloak
- Start Keycloak server (realm import is optional - see below)
- Build and start the Spring Boot application
Wait about 30-60 seconds for all services to start up completely.
You have two options:
Option A: Use the Provided Realm (Optional)
If you want to use the pre-configured realm from realm-export.json:
- Set environment variable to enable import:
echo "KEYCLOAK_IMPORT_REALM=true" >> .env
- Restart Keycloak:
docker-compose restart keycloak
- Wait for import to complete (~30 seconds)
- Note: The imported realm has SSL disabled, but you may still need to disable SSL for the master realm to access the admin console (see step 4)
Option B: Create Your Own Realm (Recommended for First Time)
- Wait for Keycloak to start (~30-60 seconds)
- Access the admin console:
- If you get "HTTPS required" error, use: http://localhost:8080/admin/master/console/
- Otherwise: http://localhost:8080 β Click Administration Console
- Login with:
- Username:
admin - Password:
admin(or your configuredKEYCLOAK_ADMIN_PASSWORD)
- Username:
- Click Create Realm button
- Enter realm name (e.g.,
my-realm) - Click Create
- Go to Realm Settings β Security tab
- Set Require SSL to
none(for development) - Click Save
- Create a client:
- Go to Clients β Create Client
- Client ID:
user-management-service(or your preferred name) - Client Protocol:
openid-connect - Enable Client authentication (confidential client)
- Enable Service accounts roles (for admin operations)
- Set Valid redirect URIs:
http://localhost:8083/* - Click Save
- Go to Credentials tab and copy the Secret
On first startup, the master realm requires SSL. To disable it for development:
Option 1: Via Admin Console (Recommended)
- Wait for Keycloak to fully start (about 30-60 seconds)
- Access the admin console directly: http://localhost:8080/admin/master/console/
- (This direct URL bypasses the SSL redirect)
- Login with:
- Username:
admin - Password:
admin(or your configuredKEYCLOAK_ADMIN_PASSWORD)
- Username:
- Go to Realm Settings (left sidebar) β Security tab
- Set Require SSL dropdown to
none - Click Save
Option 2: Via Script (After first login) After you've logged in once and disabled SSL manually, you can use the script for future setups:
./init-master-realm.shNote: After disabling SSL, you can access the admin console normally at http://localhost:8080
-
Create/update your
.envfile with your Keycloak configuration:cat > .env << EOF KEYCLOAK_REALM=my-realm KEYCLOAK_SERVER_URL=http://keycloak:8080 KEYCLOAK_CLIENT_ID=user-management-service KEYCLOAK_CLIENT_SECRET=your-client-secret-here KEYCLOAK_ADMIN_USERNAME=admin KEYCLOAK_ADMIN_PASSWORD=admin KEYCLOAK_ADMIN_CLIENT_ID=admin-cli SERVER_PORT=8083 EOF
Replace
your-client-secret-herewith the secret from your client (see step 3) -
Restart the Spring Boot app:
docker-compose restart springboot-app
Note: The Spring Boot app will start without the secret, but you need it for full functionality. You can also create the .env file before starting services if you prefer.
- Keycloak Admin Console: http://localhost:8080 (admin/admin)
- Spring Boot API: http://localhost:8083
- Keycloak Health: http://localhost:8080/health/ready
docker-compose downTo remove volumes (database data):
docker-compose down -v<dependency>
<groupId>io.teyoh</groupId>
<artifactId>springboot-keycloak-security</artifactId>
<version>1.0.0</version>
</dependency>- Install and start Keycloak server (version 26.0.2)
- Access Keycloak Admin Console (typically http://localhost:8080)
- Import the realm from
src/main/resources/realm-export.json:- Go to Realm Settings β Import
- Select the
realm-export.jsonfile - Click Import
- Get the client secret:
- Navigate to Clients β user-management-service β Credentials
- Copy the Secret value
export KEYCLOAK_REALM=my-realm
export KEYCLOAK_SERVER_URL=http://localhost:8080
export KEYCLOAK_CLIENT_ID=user-management-service
export KEYCLOAK_CLIENT_SECRET=your-client-secret-here
export KEYCLOAK_ADMIN_USERNAME=admin
export KEYCLOAK_ADMIN_PASSWORD=admin
export KEYCLOAK_ADMIN_CLIENT_ID=admin-cli
export SERVER_PORT=8083Or create a .env file with these variables.
mvn spring-boot:runPOST /auth/login- User loginPOST /auth/logout- User logoutPOST /auth/refresh-token- Refresh access tokenPOST /auth/reset-password-request- Request password resetPOST /auth/reset-password- Reset password with token
GET /auth/users/me- Get current user profileGET /auth/users/{userId}- Get user by IDPUT /auth/users/{userId}- Update user profilePOST /auth/users/{userId}/roles- Assign role to user
The project includes a pre-configured realm export (src/main/resources/realm-export.json) that contains:
- Realm:
my-realm - Client:
user-management-service(configured with service account) - Default roles and settings
With Docker Compose: The realm is automatically imported on first startup.
Manual Import:
- Log into Keycloak Admin Console
- Select the master realm (or create a new one)
- Click Import in the realm selector dropdown
- Select
src/main/resources/realm-export.json - Click Import
After importing the realm:
- Navigate to Clients β user-management-service
- Go to the Credentials tab
- Copy the Secret value
- Update your
.envfile or environment variables withKEYCLOAK_CLIENT_SECRET
Note: The realm export has a masked secret (**********), so you must get the actual secret from Keycloak after import.
If you want to create your own client instead:
- Go to Clients β Create Client
- Set Client ID:
your-client-id - Set Client Protocol:
openid-connect - Enable Client authentication (confidential client)
- Enable Service accounts roles (for admin operations)
- Set Valid redirect URIs:
http://localhost:8083/* - Save and note the Client secret
- Update
KEYCLOAK_CLIENT_IDin your configuration
@Autowired
private UserService userService;
UserRegistrationRequest request = new UserRegistrationRequest(
"john.doe@example.com",
"password123",
"John",
"Doe"
);
UserResponse user = userService.registerUser(request);LoginRequest loginRequest = new LoginRequest(
"john.doe@example.com",
"password123"
);
LoginResponse response = userService.login(loginRequest);
String accessToken = response.accessToken();
String refreshToken = response.refreshToken();UserResponse currentUser = userService.getMe();userService.assignRoleToUser(userId, "ADMIN");spring:
application:
name: keycloak-security-service
keycloak:
realm: ${KEYCLOAK_REALM:my-realm}
auth:
server:
url: ${KEYCLOAK_SERVER_URL:http://localhost:8080}
resource: ${KEYCLOAK_CLIENT_ID:springboot-security-client}
credentials:
secret: ${KEYCLOAK_CLIENT_SECRET:}
admin:
username: ${KEYCLOAK_ADMIN_USERNAME:admin}
password: ${KEYCLOAK_ADMIN_PASSWORD:admin}
client-id: ${KEYCLOAK_ADMIN_CLIENT_ID:admin-cli}
server:
port: ${SERVER_PORT:8083}The library automatically configures:
- JWT token validation
- Role extraction from Keycloak tokens
- Public endpoint access (login, logout, password reset)
- Protected endpoint authentication
- JWT Token Validation - All tokens are validated against Keycloak
- Role-Based Access Control - Roles from Keycloak are mapped to Spring Security authorities
- Stateless Sessions - No server-side session storage
- CSRF Protection Disabled - Suitable for API-only applications
- Password Reset - Secure password reset flow
public record LoginRequest(
String username,
String password
) {}public record LoginResponse(
String accessToken,
String refreshToken,
String tokenType,
Long expiresIn
) {}public record UserResponse(
String id,
String username,
String email,
String firstName,
String lastName,
List<String> roles,
List<String> groups
) {}# Run all tests
mvn test
# Run with specific profile
mvn test -PtestSee the Quick Start section above for the easiest setup.
Build and run the application container:
docker build -t springboot-keycloak-security .
docker run -p 8083:8083 \
-e KEYCLOAK_SERVER_URL=http://localhost:8080 \
-e KEYCLOAK_REALM=my-realm \
-e KEYCLOAK_CLIENT_ID=user-management-service \
-e KEYCLOAK_CLIENT_SECRET=your-secret \
springboot-keycloak-securityNote: When running standalone, ensure Keycloak is accessible at the configured URL.
Problem: Application can't connect to Keycloak
Solutions:
- Verify Keycloak is running:
curl http://localhost:8080/health/ready - Check
KEYCLOAK_SERVER_URLin your environment variables - For Docker Compose, ensure services are on the same network
- Check Keycloak logs:
docker-compose logs keycloak
Problem: Authentication fails with "Invalid client credentials"
Solutions:
- Verify the client secret matches what's in Keycloak
- Get the secret from: Keycloak Admin β Clients β [Your Client] β Credentials
- Ensure
KEYCLOAK_CLIENT_IDmatches the client ID in Keycloak - Restart the application after updating the secret
Problem: "Realm not found" errors
Solutions:
- Verify the realm exists in Keycloak
- Check
KEYCLOAK_REALMmatches the actual realm name - Import the realm from
realm-export.jsonif using the provided setup
Problem: Port already in use
Solutions:
- Change
SERVER_PORTin.envfor the Spring Boot app - Change
KEYCLOAK_PORTin.envfor Keycloak - Stop other services using those ports
Problem: Keycloak can't connect to PostgreSQL
Solutions:
- Ensure PostgreSQL container is healthy:
docker-compose ps - Check PostgreSQL logs:
docker-compose logs postgres - Verify database credentials in
.envmatch docker-compose.yml
This project is open source and available under the MIT License.
Contributions are welcome! Please read our Contributing Guidelines for details on:
- Code style and standards
- Development setup
- Testing requirements
- Pull request process
- Commit message conventions
Quick checklist:
- β All code follows Java best practices
- β Comprehensive JavaDoc is included
- β Unit tests are provided
- β Code is properly formatted
- β Documentation is updated
- Setup Guide - Detailed step-by-step setup instructions
- Contributing Guidelines - How to contribute to this project
- LICENSE - MIT License details
.env.example- Environment variable template (create.envfrom this)
- Keycloak Documentation
- Spring Security Documentation
- Keycloak Admin Client
- Docker Compose Documentation
For issues and questions:
- Open an issue on the repository
- Check existing documentation and troubleshooting section
- Review example configurations in
.env.example - Check Contributing Guidelines for development help
Made with β€οΈ by Teyoh