A professional Keycloak Authentication Provider implementation for two-factor authentication (2FA) using One-Time Passwords (OTP) delivered via email. Supports multiple email providers (Keycloak SMTP, SendGrid, AWS SES, Mailgun).
- Overview
- Features
- Prerequisites
- Deployment
- Configuration
- Local Testing
- Development
- Resources
- Localization
- Contributing
- License
This Keycloak extension enables email-based two-factor authentication by sending a verification code (OTP) to the user's registered email address during login. The authenticator integrates seamlessly with Keycloak's authentication flow system.
Key Capabilities:
- Send OTP codes via multiple email providers (Keycloak SMTP, SendGrid, AWS SES, Mailgun)
- Flexible provider selection with automatic fallback support
- Customizable email templates
- Conditional authentication support
- Integration with Keycloak's authentication flow builder
- โ Email-based OTP authentication
- โ Multiple email provider support (Keycloak SMTP, SendGrid, AWS SES)
- โ Automatic fallback to Keycloak SMTP if primary provider fails
- โ SendGrid integration with API key authentication
- โ AWS SES integration with IAM credentials and regional support
- โ Customizable email templates
- โ Conditional authentication flows
- โ Multi-stage Docker build support
- โ Compatible with Keycloak 26.x
- โ Easy integration with existing authentication flows
* Mailgun support coming soon
git clone https://github.com/mesutpiskin/keycloak-2fa-email-authenticator.git
cd keycloak-2fa-email-authenticatorCheck your Java and Maven versions:
java -version # Should show Java 21+
mvn -version # Should show Maven 3.9+mvn clean packageThis creates target/keycloak-2fa-email-authenticator-v26.0.0-SNAPSHOT.jar.
Note: If tests fail due to Java version compatibility, use:
mvn clean package -DskipTests
For Standard Keycloak Installation:
cp target/keycloak-2fa-email-authenticator-*.jar <KEYCLOAK_HOME>/providers/For Dockerized Keycloak:
cp target/keycloak-2fa-email-authenticator-*.jar /opt/keycloak/providers/<KEYCLOAK_HOME>/bin/kc.sh buildThis project includes a multi-stage Dockerfile for streamlined containerized deployment.
Using Docker:
docker build -t keycloak-2fa-email:latest .Using Podman:
podman build --tls-verify=false -t keycloak-2fa-email:latest .Note: The
--tls-verify=falseflag may be needed with Podman if you encounter certificate verification issues.
Using Docker:
docker run -p 8080:8080 \
-e KEYCLOAK_ADMIN=admin \
-e KEYCLOAK_ADMIN_PASSWORD=admin \
keycloak-2fa-email:latest \
start-devUsing Podman:
podman run -p 8080:8080 \
-e KEYCLOAK_ADMIN=admin \
-e KEYCLOAK_ADMIN_PASSWORD=admin \
keycloak-2fa-email:latest \
start-devThe project includes a docker-compose.yml file for simplified deployment:
docker-compose upOr with Podman:
podman-compose upAfter starting the container, Keycloak will be available at http://localhost:8080.
The Dockerfile uses a two-stage build approach:
| Stage | Base Image | Purpose |
|---|---|---|
| Builder | maven:3.9-eclipse-temurin-21 |
Compiles the project with Maven and creates the provider JAR |
| Runtime | quay.io/keycloak/keycloak:26.0.0 |
Copies the provider JAR and registers it with Keycloak |
Build Steps:
- Maven compiles the source code (
mvn clean package -DskipTests) - JAR is copied to
/opt/keycloak/providers/ - Keycloak configuration is updated (
kc.sh build)
Configure SMTP settings in your Keycloak realm to enable email delivery:
- Login as admin to your Keycloak installation
- Switch to your target realm
- Navigate to Realm Settings โ Email tab
- Configure your SMTP server settings:
- SMTP Host
- SMTP Port
- From Email Address
- Authentication credentials (if required)
- Enable SSL/TLS (recommended)
Create a custom authentication flow with email OTP:
- Navigate to Authentication โ Flows
- Create a new browser flow (or copy the existing one)
- Add Email OTP authenticator after the Username Password Form
- Set the execution requirement to Required or Alternative
- Bind the new flow to the browser flow
Example Flow Configuration:
The authenticator supports multiple email service providers for enhanced flexibility and reliability.
| Provider | Description | Requirements |
|---|---|---|
| Keycloak SMTP (Default) | Uses Keycloak's built-in SMTP configuration | Realm SMTP settings configured |
| SendGrid | SendGrid cloud email service | SendGrid API key and from email |
| AWS SES | Amazon Simple Email Service | AWS credentials, region, and verified sender |
| Mailgun | Mailgun email delivery service | Coming soon |
- Navigate to Authentication โ Flows
- Select your custom flow containing the Email OTP authenticator
- Click the โ๏ธ (gear/settings) icon next to Email OTP
- Configure the provider settings:
Option 1: Use Keycloak SMTP (Default)
Email Provider: KEYCLOAK
Enable Fallback to Keycloak SMTP: true
No additional configuration needed. Uses realm SMTP settings.
Option 2: Use SendGrid
Email Provider: SENDGRID
SendGrid API Key: SG.xxxxxxxxxxxxxxxxxxxx
SendGrid From Email: noreply@yourdomain.com
SendGrid From Name: Your Company Name (optional)
Enable Fallback to Keycloak SMTP: true (recommended)
Option 3: Use AWS SES
Email Provider: AWS_SES
AWS SES Region: us-east-1
AWS Access Key ID: AKIAIOSFODNN7EXAMPLE
AWS Secret Access Key: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
AWS SES From Email: noreply@yourdomain.com
AWS SES From Name: Your Company Name (optional)
Enable Fallback to Keycloak SMTP: true (recommended)
-
Get SendGrid API Key:
- Sign up at SendGrid
- Navigate to Settings โ API Keys โ Create API Key
- Select Full Access or Restricted Access with Mail Send permissions
- Copy the API key (starts with
SG.)
-
Verify Sender Identity:
- Navigate to Settings โ Sender Authentication
- Either verify a single sender email address OR
- Set up domain authentication for your sending domain
-
Configure in Keycloak:
- Enter the API key in SendGrid API Key field
- Enter your verified sender email in SendGrid From Email
- Optionally set a friendly display name
-
Create IAM User with SES Permissions:
- Go to AWS IAM Console โ Users โ Create User
- Attach policy:
AmazonSESFullAccess(or create custom policy withses:SendEmailpermission) - Create access keys and save the Access Key ID and Secret Access Key
-
Verify Sender Email or Domain:
- Go to AWS SES Console โ Verified identities
- Click Create identity
- For testing: Verify a single email address
- For production: Verify your domain (requires DNS configuration)
- Follow email/DNS verification steps
-
Request Production Access (if needed):
- By default, AWS SES starts in Sandbox mode
- In Sandbox, you can only send to verified addresses
- To send to any email: Request production access in SES Console
-
Choose AWS Region:
- SES is available in specific regions (e.g., us-east-1, eu-west-1)
- Choose region close to your users for lower latency
- Note: Verified identities are region-specific
-
Configure in Keycloak:
- Select
AWS_SESfrom Email Provider dropdown - Enter AWS region (e.g.,
us-east-1) - Enter IAM access key ID
- Enter IAM secret access key
- Enter verified sender email
- Optionally set sender display name
- Select
When Enable Fallback to Keycloak SMTP is enabled (recommended):
- If the primary provider fails, the system automatically falls back to Keycloak's SMTP
- Ensures email delivery reliability even if 3rd party service is unavailable
- Fallback events are logged for monitoring
mvn testNote: Tests may fail on Java 25+ due to Mockito/ByteBuddy compatibility. Use Java 21 for development.
For detailed instructions on testing this authenticator locally with Podman or Docker, see:
Quick start:
# Build and run with Podman
podman build -t keycloak-email-auth:latest .
podman run -d --name keycloak-test \
-p 8080:8080 \
-e KEYCLOAK_ADMIN=admin \
-e KEYCLOAK_ADMIN_PASSWORD=admin \
keycloak-email-auth:latest start-devAccess admin console at: http://localhost:8080/admin
This project supports multiple languages for a better user experience across different regions.
| Language | Code | File | Status |
|---|---|---|---|
| ๐ฌ๐ง English | en |
messages_en.properties |
โ Complete |
| ๐น๐ท Turkish | tr |
messages_tr.properties |
โ Complete |
| ๐ซ๐ท French | fr |
messages_fr.properties |
โ Complete |
| ๐ฎ๐น Italian | it |
messages_it.properties |
โ Complete |
| ๐ช๐ธ Spanish | es |
messages_es.properties |
โ Complete |
| ๐ฉ๐ฐ Danish | da |
messages_da.properties |
โ Complete |
| ๐ฉ๐ช German | de |
messages_de.properties |
โ Complete |
| ๐ท๐บ Russian | ru |
messages_ru.properties |
โ Complete |
| ๐ฆ๐ฟ Azerbaijani | az |
messages_az.properties |
โ Complete |
| ๐ธ๐ฆ Arabic | ar |
messages_ar.properties |
โ Complete |
| ๐น๐ผ Chinese (Traditional) | zh_TW |
messages_zh_TW.properties |
โ Complete |
We welcome contributions for additional language support! Here's how you can add a new language:
-
Navigate to the messages directory:
cd src/main/resources/theme-resources/messages/ -
Create a new properties file:
cp messages_en.properties messages_<language_code>.properties
Replace
<language_code>with the appropriate ISO 639-1 language code (e.g.,defor German,esfor Spanish,jafor Japanese). -
Translate the content: Open the new file and translate all text values while keeping the keys unchanged:
# Example for German (messages_de.properties) resendCode=Code erneut senden emailOtpForm=Bitte geben Sie den sechsstelligen Code ein, der an Ihre E-Mail gesendet wurde.
-
Test your translation:
- Build the project:
mvn clean package - Deploy to Keycloak
- Switch your browser/Keycloak to the new language
- Verify all messages display correctly
- Build the project:
-
Submit a Pull Request:
- Fork the repository
- Create a feature branch:
git checkout -b add-<language>-translation - Commit your changes:
git commit -m "Add <language> translation" - Push to your fork and submit a PR
Here are the main translation keys used in this authenticator:
resendCode=Resend Code
emailOtpForm=Please enter the six digit code...
emailCodeSubject={0} access code
emailCodeBody=Access code: {0}...
email-authenticator-display-name=Email Authenticator
email-authenticator-help-text=Receive a one-time verification code...
email-authenticator-setup-title=Set up Email Authenticator
email-authenticator-setup-description=Use this option to receive...
email-authenticator-setup-button=Enable Email Authenticator
email-authenticator-setup-cancelled=Email authenticator setup cannot...
email-authenticator-setup-error=We couldn't enable Email Authenticator...
email-authenticator-setup-missing-email=Add an email address...
email-authenticator-resend-cooldown=Please wait {0} seconds...Note: Text inside curly braces like
{0},{1}are placeholders for dynamic values. Do not translate these.
Contributions are welcome! Here's how you can help:
- ๐ Add New Translations - Follow the localization guide above
- ๐ Report Bugs - Open an issue with details about the problem
- โจ Suggest Features - Share your ideas via GitHub issues
- ๐ง Submit Pull Requests - Fix bugs or implement new features
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
- Follow existing code style and conventions
- Add comments for complex logic
- Update documentation when needed
- Test your changes thoroughly
This project is licensed under the Apache License 2.0. See the LICENSE file for details.
Made with โค๏ธ for the Keycloak community
