Keycloak Magic Link MFA Setup with Mideye
Keycloak is an open-source identity and access management (IAM) platform that provides single sign-on (SSO) via OpenID Connect (OIDC), SAML 2.0, and OAuth 2.0.
Mideye Server can provide multi-factor authentication (MFA) for Keycloak using the Magic Link API. A custom Java authenticator (SPI) calls the Mideye REST endpoint during the login flow, sends a push notification or SMS to the user’s phone, and waits for the response.
Architecture
Section titled “Architecture”How it works
Section titled “How it works”- User clicks “Sign in” → application redirects to Keycloak
- User enters username + password
- The custom authenticator reads the user’s phone number from a Keycloak user attribute
- It calls
GET /api/sfwa/auth?msisdn=<phone>on the Mideye Server - Mideye sends a push notification (Mideye+) or SMS magic link to the user
- The user taps Accept (or the API times out / user rejects)
- Keycloak issues OIDC tokens and redirects back to the application
Prerequisites
Section titled “Prerequisites”- Keycloak 22 or later (tested with 26.x)
- Mideye Server 5 or 6 with a configured Magic Link endpoint
- API key generated for that endpoint
- Network access from Keycloak to Mideye Server on TCP port 8443 (HTTPS)
- Java 17+ to build the SPI (or use the pre-built JAR)
Step 1 — Build or download the authenticator SPI
Section titled “Step 1 — Build or download the authenticator SPI”The authenticator SPI source code and a pre-built JAR are available on GitHub:
Option A: Use the pre-built JAR
Section titled “Option A: Use the pre-built JAR”Download mideye-keycloak-spi-1.0.0.jar from keycloak/providers/ in the repository and place it in Keycloak’s providers/ directory.
Option B: Build from source
Section titled “Option B: Build from source”cd keycloak/spimvn clean package -DskipTestscp target/mideye-keycloak-spi-1.0.0.jar /opt/keycloak/providers/After adding the JAR, rebuild Keycloak’s provider cache:
/opt/keycloak/bin/kc.sh buildRestart Keycloak for the new provider to take effect.
Step 2 — Register the phone number attribute
Section titled “Step 2 — Register the phone number attribute”The authenticator reads each user’s phone number from a Keycloak user attribute. You must register this attribute in the realm’s User Profile schema.
- In the Keycloak admin console, go to Realm settings → User profile
- Click Create attribute
- Set:
- Attribute name:
phoneNumber(or your preferred name) - Display name: Phone Number
- Who can edit: Admin, User
- Who can view: Admin, User
- Attribute name:
- Save
Then set the phone number on each user:
- Go to Users → select a user → Attributes tab
- Set
phoneNumberto the user’s international phone number (e.g.,+46701234567)
Step 3 — Create the authentication flow
Section titled “Step 3 — Create the authentication flow”- In the Keycloak admin console, go to Authentication → Flows
- Click Create flow
- Enter a name (e.g.,
Browser with Mideye MFA) and click Create - Click Add execution and add Cookie (set to Alternative)
- Click Add sub-flow, name it
Forms(set to Alternative) - Inside the
Formssub-flow:- Click Add execution → add Username Password Form (set to Required)
- Click Add execution → add Mideye Magic Link Authenticator (set to Required)
The resulting flow should look like:
| Execution | Requirement |
|---|---|
| Cookie | Alternative |
| Forms (sub-flow) | Alternative |
| ↳ Username Password Form | Required |
| ↳ Mideye Magic Link Authenticator | Required |
Step 4 — Configure the authenticator
Section titled “Step 4 — Configure the authenticator”- In the flow editor, click the ⚙ Settings icon on the Mideye Magic Link Authenticator row
- Configure the following:
| Setting | Description | Example |
|---|---|---|
| Mideye Server URL | Base URL of the Magic Link endpoint | https://mideye.example.com:8443/api/sfwa |
| API Key | The API key for the endpoint | your-api-key |
| Phone Attribute | Keycloak user attribute containing the phone number | phoneNumber |
| Timeout (seconds) | How long to wait for user response | 60 |
| Skip TLS Verification | Disable certificate validation (dev/test only) | false |
- Click Save
Step 5 — Bind the flow to the browser
Section titled “Step 5 — Bind the flow to the browser”- Go to Authentication → Flows
- In the Browser flow dropdown at the top, select your new flow (
Browser with Mideye MFA) - Click Bind flow (or use the action menu → Bind flow)
New browser logins to this realm will now require Mideye MFA after the password step.
Testing with Docker
Section titled “Testing with Docker”A complete Docker Compose environment is available in the GitHub repository. It includes Keycloak, a database, the pre-built SPI JAR, and a test OIDC web page:
git clone https://github.com/mideye/mideye-magic-link-examples.gitcd mideye-magic-link-examples/keycloakcp .env.example .env # edit with your Mideye Server detailsdocker compose up -dThen open http://localhost:8080 and sign in to the admin console to configure the flow.
Troubleshooting
Section titled “Troubleshooting”MFA step does not appear
Section titled “MFA step does not appear”- Verify the JAR is in Keycloak’s
providers/directory and that you rankc.sh build - Check that the authentication flow is bound to the browser flow
- Confirm the Mideye Magic Link Authenticator execution is set to Required
Authentication fails with connection error
Section titled “Authentication fails with connection error”- Verify network connectivity from Keycloak to Mideye Server on port 8443
- Check that the Mideye Server URL is correct (include
/api/sfwapath) - For self-signed certificates in test environments, set Skip TLS Verification to
true
User gets “Phone number not found”
Section titled “User gets “Phone number not found””- Confirm the user has the
phoneNumberattribute set (with international prefix) - Check that the Phone Attribute setting matches the attribute name exactly
Timeout or no response
Section titled “Timeout or no response”- Increase the timeout value in the authenticator settings
- Verify the user’s phone number is enrolled in Mideye Server
- Check Mideye Server logs for delivery failures
Related
Section titled “Related”- Magic Link API reference — Full API documentation
- Magic Link example applications — Python, Java, C#, Go examples
- OIDC support in Mideye Server — How the OIDC VSA feature works