Comprehensive guide for testing Keycloak Email Authenticator locally using Docker or Podman.
✅ Docker OR Podman installed
✅ Java 21 installed
✅ Maven installed
✅ Port 8080 available
Note: All commands work with both Docker and Podman. Simply replace
podmanwithdockeror vice versa.
# 1. Build the JAR
cd /path/to/keycloak-2fa-email-authenticator
export JAVA_HOME=$(/usr/libexec/java_home -v 21)
mvn clean package
# 2. Build image (Docker or Podman)
docker build -t keycloak-email-auth:latest .
# OR
podman build -t keycloak-email-auth:latest .
# 3. Run container
docker run -d \
--name keycloak-test \
-p 8080:8080 \
-e KEYCLOAK_ADMIN=admin \
-e KEYCLOAK_ADMIN_PASSWORD=admin \
keycloak-email-auth:latest \
start-dev
# OR
podman run -d \
--name keycloak-test \
-p 8080:8080 \
-e KEYCLOAK_ADMIN=admin \
-e KEYCLOAK_ADMIN_PASSWORD=admin \
keycloak-email-auth:latest \
start-dev
# 4. View logs
docker logs -f keycloak-test
# OR
podman logs -f keycloak-test
# 5. Access
# http://localhost:8080/admin
# Username: admin, Password: admincd /path/to/keycloak-2fa-email-authenticator
# Build with Java 21
export JAVA_HOME=$(/usr/libexec/java_home -v 21)
mvn clean packageExpected output: target/keycloak-2fa-email-authenticator-v26.0.0-SNAPSHOT.jar
Docker Compose:
docker-compose up --buildPodman Compose:
podman-compose up --buildAlternative (use Docker CLI with Compose):
docker compose up --buildOpen in browser: http://localhost:8080
- Username: admin
- Password: admin
Docker:
cd /path/to/keycloak-2fa-email-authenticator
docker build -t keycloak-email-auth:latest .Podman:
cd /path/to/keycloak-2fa-email-authenticator
podman build -t keycloak-email-auth:latest .This will:
- Build JAR with Maven
- Copy JAR to Keycloak 26.0.0 image
- Integrate provider into Keycloak
Docker:
docker run -d \
--name keycloak-test \
-p 8080:8080 \
-e KEYCLOAK_ADMIN=admin \
-e KEYCLOAK_ADMIN_PASSWORD=admin \
keycloak-email-auth:latest \
start-devPodman:
podman run -d \
--name keycloak-test \
-p 8080:8080 \
-e KEYCLOAK_ADMIN=admin \
-e KEYCLOAK_ADMIN_PASSWORD=admin \
keycloak-email-auth:latest \
start-devDocker:
docker logs -f keycloak-testPodman:
podman logs -f keycloak-testSuccessful startup message:
Keycloak 26.0.0 on JVM (powered by Quarkus)
Running the server in development mode. DO NOT use this configuration in production.
- Username:
admin - Password:
admin
To create new realm:
- Click dropdown in top-left → "Create Realm"
- Realm name:
test - Click "Create"
IMPORTANT: SMTP settings required for email sending!
Realm Settings → Email:
- From: noreply@example.com
- Host: smtp.gmail.com (for Gmail)
- Port: 587
- Enable StarTLS: ON
- Username: your-email@gmail.com
- Password: your-app-password
For Gmail:
- Create "App Password": https://myaccount.google.com/apppasswords
- 2FA must be enabled
Users → Add User:
- Username:
testuser - Email:
your-email@gmail.com(real email!) - Email Verified: ON
- Click "Create"
Credentials → Set Password:
- Password:
test123 - Temporary: OFF
Authentication → Flows:
- Select "Browser" flow
- Click "Copy" → Name: "Browser with Email OTP"
- Click "OK"
In "Browser with Email OTP" flow:
- Select "Browser with Email OTP Forms" row
- Click "Add step"
- Select "Email OTP" (our provider!)
- Click "Add"
On "Email OTP" row:
- Requirement: REQUIRED (or CONDITIONAL)
Bindings tab:
- Browser Flow: Select "Browser with Email OTP"
- Click "Save"
Click ⚙️ (Settings) icon on "Email OTP" row:
- Code length: 6
- Time-to-live: 300 (5 minutes)
- Simulation mode: false (for real emails)
- Resend cooldown: 30 (seconds)
- Logout (if logged in)
- Go to login: http://localhost:8080/realms/test/account
- Username:
testuser, Password:test123 - ✅ Code will be sent to email
- Enter code
- ✅ Login successful
- Login, wait for code
- Wait 5+ minutes
- Enter expired code
- ❌ Should see "Code expired" error
- Login, receive email
- Click "Resend code" link
- Try again within 30 seconds → cooldown message
- After 30 seconds → new code sent
- Login
- Enter wrong code
- ❌ Should see "Invalid code" error
To test without sending emails:
In flow settings:
- Simulation mode: true
View code in container logs:
podman logs -f keycloak-test | grep "SIMULATION MODE"Output:
***** SIMULATION MODE ***** Email code send to test@example.com for user testuser is: 123456
Change language on login page:
- 🇹🇷 Türkçe
- 🇬🇧 English
- 🇩🇪 Deutsch
- 🇫🇷 Français
- 🇮🇹 Italiano
- 🇪🇸 Español
- 🇷🇺 Русский
- 🇸🇦 العربية
- 🇩🇰 Dansk
- 🇦🇿 Azərbaycan
- 🇹🇼 中文 (繁體)
# Check container status
podman ps -a
# Check logs
podman logs keycloak-test
# Stop and remove
podman stop keycloak-test
podman rm keycloak-testCheck inside container:
podman exec -it keycloak-test ls -la /opt/keycloak/providers/Expected:
keycloak-2fa-email-authenticator-v26.0.0-SNAPSHOT.jar
-
Test SMTP settings:
- Realm Settings → Email → "Test connection"
-
Enable simulation mode:
- Flow settings → Simulation mode: true
- Watch logs:
podman logs -f keycloak-test
-
For Gmail:
- Use App Password (not regular password)
- 2FA must be enabled
# Use different port
podman run -d \
-p 8081:8080 \
...Access at: http://localhost:8081
All commands work with both docker and podman. Examples show both.
docker stop keycloak-test
# OR
podman stop keycloak-testdocker start keycloak-test
# OR
podman start keycloak-testdocker stop keycloak-test && docker rm keycloak-test
# OR
podman stop keycloak-test && podman rm keycloak-testdocker rmi keycloak-email-auth:latest
# OR
podman rmi keycloak-email-auth:latest# 1. Rebuild JAR
mvn clean package
# 2. Rebuild image
docker build -t keycloak-email-auth:latest .
# OR
podman build -t keycloak-email-auth:latest .
# 3. Recreate container
docker stop keycloak-test && docker rm keycloak-test
docker run -d --name keycloak-test \
-p 8080:8080 \
-e KEYCLOAK_ADMIN=admin \
-e KEYCLOAK_ADMIN_PASSWORD=admin \
keycloak-email-auth:latest start-devWARNING:
start-devshould NOT be used in production!
podman run -d \
--name keycloak-prod \
-p 8443:8443 \
-e KC_HOSTNAME=keycloak.example.com \
-e KC_HTTPS_CERTIFICATE_FILE=/path/to/cert.pem \
-e KC_HTTPS_CERTIFICATE_KEY_FILE=/path/to/key.pem \
-e KC_DB=postgres \
-e KC_DB_URL=jdbc:postgresql://db/keycloak \
-e KC_DB_USERNAME=keycloak \
-e KC_DB_PASSWORD=password \
keycloak-email-auth:latest \
start- Keycloak Documentation: https://www.keycloak.org/docs/latest/
- Podman Documentation: https://docs.podman.io/
- Project README: README.md
- Keycloak SPI Guide: https://www.keycloak.org/docs/latest/server_development/
If you encounter issues:
- Check container logs
- Review Keycloak Admin Console error messages
- Open GitHub Issue: https://github.com/mesutpiskin/keycloak-2fa-email-authenticator/issues