This extension adds RESTful endpoints to Keycloak to support programmatic management of Time-Based One-Time Password (TOTP) credentials. It enables external systems to integrate TOTP setup and verification workflows without relying on the Keycloak UI.
Note: This is a Java-based rewrite of the original Kotlin implementation by MediHause.
- Generate TOTP secrets and QR codes (Base32 and base64 image)
- Register TOTP credentials for a user
- Verify user-provided TOTP codes
- API secured with service account bearer token
- Supports credential overwrite logic
- Tested on Keycloak 26
This project uses Maven for building the JAR file.
git clone https://github.com/arisusantolie/keycloak-totp-api-provider.git
cd keycloak-totp-api-provider
Use the mvn
to generate JAR with dependencies:
mvn clean install package -DskipTests
The final JAR will be located in target/
, named similar to:
keycloak-totp-api-provider-1.0.jar
-
Copy the JAR into the Keycloak
providers
directory:cp target/keycloak-totp-api-provider-1.0.jar $KEYCLOAK_HOME/providers/
-
Rebuild Keycloak:
$KEYCLOAK_HOME/bin/kc.sh build
Update your Docker Compose or docker run
with:
volumes:
- ./keycloak-totp-api-provider-1.0.jar:/opt/keycloak/providers/keycloak-totp-api-provider-1.0.jar
Add this to your Dockerfile:
COPY keycloak-totp-api-provider-1.0.jar /opt/keycloak/providers/
Then rebuild your image.
All endpoints follow the pattern:
{{BASE_URL}}/realms/{{REALM}}/totp-api/{{USER_ID}}/...
GET /generate
Generates a TOTP secret and base64-encoded QR code.
Response:
{
"encodedSecret": "OFIWESBQGBLFG432HB5G6TTLIVIEGU2O",
"qrCode": "iVBORw0KGgoAAAANSUhEUg..."
}
POST /register
Registers a TOTP credential for the user.
Request Body:
{
"deviceName": "MyDevice",
"encodedSecret": "OFIWESBQGBLFG432HB5G6TTLIVIEGU2O",
"initialCode": "128356",
"overwrite": true
}
Response:
{
"message": "OTP credential registered"
}
POST /verify
Validates a user-supplied TOTP code.
Request Body:
{
"deviceName": "MyDevice",
"code": "128356"
}
Response:
{
"message": "OTP code is valid"
}
POST /remove-totp
Remove User TOTP code by deviceName.
Request Body:
{
"deviceName": "MyDevice"
}
Response:
{
"message": "OTP credential removed"
}
Get /get-totp-credentials
Get all user totp credential.
Response:
{
"deviceName":[
"MyDevice"
]
}
To access the API endpoints, the caller must:
- Be authenticated using a Bearer token.
- Use a service account.
- Have the
manage-totp
realm-level role assigned.
- Go to the Keycloak Admin Console.
- Navigate to Clients and click Create.
- Set the
Client ID
(e.g.,totp-api-client
) and click Save. - In the client settings:
- Set Client authentication = ON
- Set Service accounts enabled = ON
- Save your changes.
- Go to the Service Account Roles tab.
- Assign the
manage-totp
realm role to the service account user.
curl -X POST \
"https://<KEYCLOAK-HOST>/realms/<REALM>/protocol/openid-connect/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "client_id=totp-api-client" \
-d "client_secret=<CLIENT_SECRET>"
Response:
{
"access_token": "eyJhbGci...",
"expires_in": 300,
...
}
Use the access_token
in the Authorization
header for your API calls:
-H "Authorization: Bearer <access_token>"
Original Kotlin version created by MediHause. This version is a Java port for improved compatibility and integration with existing Java-based Keycloak extensions.