This plugin helps you to login by phone number.
| Keycloak Version | Plugin Version |
|---|---|
| 21 | ✅ 1.1.0 |
| 22 | ✅ 26.1.3 |
| 23 | ✅ 26.1.3 |
| 24 | ✅ 26.1.3 |
| 25 | ✅ 26.1.3 |
| 26 | ✅ 26.1.3 |
The Keycloak Phone Number Login Plugin is a custom extension for Keycloak that enables authentication via SMS-based phone number login. Instead of (or in addition to) traditional username/password logins, this plugin allows end-users to authenticate using their phone number. The process includes:
- Phone Number Entry: Users enter their phone number.
- Confirmation: The system displays a formatted version of the number for user confirmation.
- User Lookup/Creation: The plugin resolves a user by phone number (and creates one after phone verification if needed).
- SMS TAN Sending: A TAN is requested and sent via an external SMS API.
- TAN Validation: The user inputs the TAN to complete authentication.
- Profile Update: On successful TAN verification, users can update their profile information.
This modular plugin uses a multi-step flow and is designed with separation of concerns in mind, using a dedicated service layer for SMS and phone number processing.
The SmsService has been enhanced to support both Basic Authentication and OAuth2 Client Credentials Grant for secure communication with the SMS provider. The plugin prioritizes OAuth2 if the required environment variables are set; otherwise, it falls back to Basic Auth.
All declared providers are now implemented:
APIAMQPRABBITMQKAFKASNS_SQS
API is the REST provider. AMQP, RABBITMQ, KAFKA, and SNS_SQS now each have their own SmsGateway implementation in their respective packages.
For non-API providers, the plugin generates a TAN + hash, publishes a SEND_SMS event payload to the configured transport, and validates the submitted TAN locally (hash-bound, one-time, 5-minute TTL).
SMS_API_URL is interpreted per provider:
API: REST base URLKAFKA: Kafka bootstrap servers (example:localhost:9092)RABBITMQ: RabbitMQ AMQP URI (example:amqp://guest:guest@localhost:5672/%2f)AMQP: AMQP URISNS_SQS: optional AWS endpoint override (useful for LocalStack)
You can download the latest plugin JARs from GitHub releases using curl. For example:
curl -L -o keycloak-phonenumber-login.jar https://github.com/vymalo/keycloak-phone-number/releases/download/v<version>/keycloak-phonenumber-login-<version>.jar
curl -L -o keycloak-phonenumber-theme.jar https://github.com/vymalo/keycloak-phone-number/releases/download/v<version>/keycloak-phonenumber-theme-<version>.jar
curl -L -o keycloak-phonenumber-api.jar https://github.com/vymalo/keycloak-phone-number/releases/download/v<version>/keycloak-phonenumber-api-<version>.jar
# Optional provider gateways (mount the one you configure as smsProvider)
curl -L -o keycloak-phonenumber-amqp.jar https://github.com/vymalo/keycloak-phone-number/releases/download/v<version>/keycloak-phonenumber-amqp-<version>.jar
curl -L -o keycloak-phonenumber-rabbitmq.jar https://github.com/vymalo/keycloak-phone-number/releases/download/v<version>/keycloak-phonenumber-rabbitmq-<version>.jar
curl -L -o keycloak-phonenumber-kafka.jar https://github.com/vymalo/keycloak-phone-number/releases/download/v<version>/keycloak-phonenumber-kafka-<version>.jar
curl -L -o keycloak-phonenumber-sns-sqs.jar https://github.com/vymalo/keycloak-phone-number/releases/download/v<version>/keycloak-phonenumber-sns-sqs-<version>.jarOnce you have the JAR, mount it into the Keycloak server. For example, when running Keycloak in Docker, you can mount the plugin as a volume:
docker run -d \
--name keycloak \
-p 8080:8080 \
-e KEYCLOAK_ADMIN=admin \
-e KEYCLOAK_ADMIN_PASSWORD=password \
-e SMS_API_URL=http://your-sms-api-url \
-e SMS_API_COUNTRY_PATTERN='cm|de|fr' \
-e SMS_API_AUTH_USERNAME=someuser \
-e SMS_API_AUTH_PASSWORD=somepassword \
-e OAUTH2_CLIENT_ID=some-client-id \
-e OAUTH2_CLIENT_SECRET=some-client-secret \
-e OAUTH2_TOKEN_ENDPOINT=http://token-mock:8080/token \
-v /path/to/keycloak-phonenumber-login.jar:/opt/keycloak/providers/keycloak-phonenumber-login.jar \
-v /path/to/keycloak-phonenumber-kafka.jar:/opt/keycloak/providers/keycloak-phonenumber-kafka.jar \
-v /path/to/keycloak-phonenumber-theme.jar:/opt/keycloak/providers/keycloak-phonenumber-theme.jar \
quay.io/keycloak/keycloak:26.5.2 start-devMount the gateway jar that matches your configured smsProvider (API, AMQP, RABBITMQ, KAFKA, SNS_SQS).
apiVersion: apps/v1
kind: Deployment
metadata:
name: keycloak
spec:
replicas: 1
selector:
matchLabels:
app: keycloak
template:
metadata:
labels:
app: keycloak
spec:
volumes:
- name: plugin-volume
emptyDir: {}
initContainers:
- name: download-plugin
image: curlimages/curl:8.1.2
env:
- name: VERSION
value: 26.5.2
command:
- sh
- -c
- |
curl -L -o /plugin/keycloak-phonenumber-login.jar https://github.com/vymalo/keycloak-phone-number/releases/download/v$VERSION/keycloak-phonenumber-login-$VERSION.jar
curl -L -o /plugin/keycloak-phonenumber-api.jar https://github.com/vymalo/keycloak-phone-number/releases/download/v$VERSION/keycloak-phonenumber-api-$VERSION.jar
curl -L -o /plugin/keycloak-phonenumber-theme.jar https://github.com/vymalo/keycloak-phone-number/releases/download/v$VERSION/keycloak-phonenumber-theme-$VERSION.jar
volumeMounts:
- name: plugin-volume
mountPath: /plugin
containers:
- name: keycloak
image: quay.io/keycloak/keycloak:26.5.2
ports:
- containerPort: 8080
env:
- name: KEYCLOAK_ADMIN
value: "admin"
- name: KEYCLOAK_ADMIN_PASSWORD
value: "password"
- name: SMS_API_URL
value: "http://your-sms-api-url"
- name: SMS_API_COUNTRY_PATTERN
value: "cm|de|fr"
- name: SMS_API_AUTH_USERNAME
value: "someuser"
- name: SMS_API_AUTH_PASSWORD
value: "somepassword"
- name: OAUTH2_CLIENT_ID
value: "some-client-id"
- name: OAUTH2_CLIENT_SECRET
value: "some-client-secret"
- name: OAUTH2_TOKEN_ENDPOINT
value: "http://token-mock:8080/token"
volumeMounts:
- name: plugin-volume
mountPath: /opt/keycloak/providersTip: For Kubernetes, it's more common to use a sidecar or init container to download the plugin from GitHub and copy it into the appropriate directory.
The following environment variables are used by the plugin:
- KEYCLOAK_ADMIN: The administrator username for Keycloak.
- KEYCLOAK_ADMIN_PASSWORD: The administrator password for Keycloak.
- KC_LOG_CONSOLE_COLOR: Enables colored logging in the console (set to
'true'or'false'). - KC_HTTP_PORT: The HTTP port on which Keycloak runs.
- SMS_API_URL: The base URL of the SMS API service.
- SMS_API_COUNTRY_PATTERN: A regex pattern to match supported phone number country codes.
- SMS_API_AUTH_USERNAME: The basic auth username for the SMS API.
- SMS_API_AUTH_PASSWORD: The basic auth password for the SMS API.
- OAUTH2_CLIENT_ID: The client ID for OAuth2 authentication with the SMS provider.
- OAUTH2_CLIENT_SECRET: The client secret for OAuth2 authentication with the SMS provider.
- OAUTH2_TOKEN_ENDPOINT: The URL of the token endpoint for OAuth2 authentication (e.g.,
http://token-mock:8080/tokenfor testing, orhttp://your-auth-server/oauth/tokenin production). - SMS_KAFKA_TOPIC: Kafka topic used by
KAFKAprovider (default:keycloak.sms.events). - SMS_RABBITMQ_QUEUE: Queue used by
RABBITMQprovider (default:keycloak.sms.events). - SMS_AMQP_EXCHANGE: Exchange used by
AMQPprovider (default:keycloak.sms.events). - SMS_AMQP_ROUTING_KEY: Routing key used by
AMQPprovider (default:sms.send). - SMS_SNS_TOPIC_ARN: SNS topic ARN used by
SNS_SQSprovider. - SMS_SQS_QUEUE_URL: SQS queue URL used by
SNS_SQSprovider.
Configure these variables in your deployment (Docker, Kubernetes, etc.) as shown in the examples above.
The plugin is built as a monorepo under packages/:
packages/keycloak-phonenumber-abstractions: shared interfaces and models used by all providers.packages/keycloak-phonenumber-login: Keycloak authenticator flow implementation.packages/keycloak-phonenumber-api: OpenAPI-based SMS provider implementation.packages/keycloak-phonenumber-sns-sqs: SNS/SQS provider implementation.packages/keycloak-phonenumber-rabbitmq: RabbitMQ provider implementation.packages/keycloak-phonenumber-amqp: AMQP provider implementation.packages/keycloak-phonenumber-kafka: Kafka provider implementation.packages/keycloak-phonenumber-theme: login theme package.
Dependency injection (via CDI) is used to wire components together, making the system more modular, testable, and maintainable.
We welcome contributions! Here’s how you can get involved:
- Use the GitHub issues page to report bugs, suggest enhancements, or request features.
- Ensure your issue includes detailed reproduction steps and relevant logs.
- Fork the Repository:
Create a fork, then clone it locally. - Branching Model:
- Use feature branches for new features or fixes.
- Ensure your branch name is descriptive (e.g.,
feature/sms-service-refactor).
- Coding Standards:
Follow the existing coding conventions.- Write unit tests for your changes.
- Run
mvn clean installand ensure all tests pass.
- Pull Requests:
Submit a pull request with a clear description of your changes, referencing any issues addressed.
- Update documentation as needed with your changes.
- Provide feedback on areas for improvement or additional features.
For more details or questions, please contact dev@ssegning.com.
