Skip to content

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.

Web App(your app)Keycloak(IdP)Mideye Server(MFA) OIDC ID TokenHTTPSAccept / Reject UserKeycloakMideye Server 1. Login (username + password)2. GET /api/sfwa/auth?msisdn=+46701234567 3. Push or SMS to phone4. User taps Accept5. {"code":"TOUCH_ACCEPTED"}6. Success (ID token)
  1. User clicks “Sign in” → application redirects to Keycloak
  2. User enters username + password
  3. The custom authenticator reads the user’s phone number from a Keycloak user attribute
  4. It calls GET /api/sfwa/auth?msisdn=<phone> on the Mideye Server
  5. Mideye sends a push notification (Mideye+) or SMS magic link to the user
  6. The user taps Accept (or the API times out / user rejects)
  7. Keycloak issues OIDC tokens and redirects back to the application
  • 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:

Download mideye-keycloak-spi-1.0.0.jar from keycloak/providers/ in the repository and place it in Keycloak’s providers/ directory.

Terminal window
cd keycloak/spi
mvn clean package -DskipTests
cp target/mideye-keycloak-spi-1.0.0.jar /opt/keycloak/providers/

After adding the JAR, rebuild Keycloak’s provider cache:

Terminal window
/opt/keycloak/bin/kc.sh build

Restart 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.

  1. In the Keycloak admin console, go to Realm settingsUser profile
  2. Click Create attribute
  3. Set:
    • Attribute name: phoneNumber (or your preferred name)
    • Display name: Phone Number
    • Who can edit: Admin, User
    • Who can view: Admin, User
  4. Save

Then set the phone number on each user:

  1. Go to Users → select a user → Attributes tab
  2. Set phoneNumber to the user’s international phone number (e.g., +46701234567)
  1. In the Keycloak admin console, go to AuthenticationFlows
  2. Click Create flow
  3. Enter a name (e.g., Browser with Mideye MFA) and click Create
  4. Click Add execution and add Cookie (set to Alternative)
  5. Click Add sub-flow, name it Forms (set to Alternative)
  6. Inside the Forms sub-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:

ExecutionRequirement
CookieAlternative
Forms (sub-flow)Alternative
  ↳ Username Password FormRequired
  ↳ Mideye Magic Link AuthenticatorRequired
  1. In the flow editor, click the ⚙ Settings icon on the Mideye Magic Link Authenticator row
  2. Configure the following:
SettingDescriptionExample
Mideye Server URLBase URL of the Magic Link endpointhttps://mideye.example.com:8443/api/sfwa
API KeyThe API key for the endpointyour-api-key
Phone AttributeKeycloak user attribute containing the phone numberphoneNumber
Timeout (seconds)How long to wait for user response60
Skip TLS VerificationDisable certificate validation (dev/test only)false
  1. Click Save
  1. Go to AuthenticationFlows
  2. In the Browser flow dropdown at the top, select your new flow (Browser with Mideye MFA)
  3. 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.

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:

Terminal window
git clone https://github.com/mideye/mideye-magic-link-examples.git
cd mideye-magic-link-examples/keycloak
cp .env.example .env # edit with your Mideye Server details
docker compose up -d

Then open http://localhost:8080 and sign in to the admin console to configure the flow.

  • Verify the JAR is in Keycloak’s providers/ directory and that you ran kc.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/sfwa path)
  • For self-signed certificates in test environments, set Skip TLS Verification to true
  • Confirm the user has the phoneNumber attribute set (with international prefix)
  • Check that the Phone Attribute setting matches the attribute name exactly
  • 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