chore: add guide to enforce otp for internal users in keycloak

This commit is contained in:
Bert-Jan Fikse 2025-09-12 14:04:59 +02:00
parent bda8da21c9
commit c8231193c9
Signed by: bert-jan
GPG key ID: C1E0AB516AC16D1A
2 changed files with 107 additions and 5 deletions

View file

@ -6,15 +6,17 @@ This repository contains documentation, guides, and reference material.
- **[Keycloak](./keycloak/)** - **[Keycloak](./keycloak/)**
Documentation and guides related to Keycloak configuration and best practices. Documentation and guides related to Keycloak configuration and best practices.
- [Enforce OTP 2FA for Internal Users](./keycloak/enforce-otp-internal.md)
Step-by-step instructions for enforcing OTP-based two-factor authentication for internal users, while excluding external Microsoft Entra users.
- **[Microsoft Entra](./ms-entra/)** - **[Microsoft Entra](./ms-entra/)**
Documentation and guides related to Microsft Entra configuration and best practices. Documentation and guides related to Microsft Entra configuration and best practices.
- [Enterprise App Integration with Keycloak](./ms-entra/enterprise-app-keycloak.md) - [Enterprise App Integration with Keycloak](./ms-entra/enterprise-app-keycloak.md)
Step-by-step instructions for creating an Enterprise Application in Microsoft Entra (Azure AD) as an identity provider for Keycloak. Step-by-step instructions for creating an Enterprise Application in Microsoft Entra (Azure AD) as an identity provider for Keycloak.
- **[Infrastructure](./infrastructure/)** - **[Infrastructure](./infrastructure/)**
Documentation and guides related to infrastructure configuration and best practices. Documentation and guides related to infrastructure configuration and best practices.
- [IPV6](./infrastructure/ipv6/ipv6.md) - [IPV6](./infrastructure/ipv6/ipv6.md)
Documentation of the ipv6 concept. Documentation of the ipv6 concept.
- [ACME](./infrastructure/acme.md) - [ACME](./infrastructure/acme.md)
Documentation of the ACME concept. Documentation of the ACME concept.

View file

@ -0,0 +1,100 @@
# Enforce OTP (TOTP) 2FA for Internal Users in Keycloak
> **Goal:** Enforce OTP-based two-factor authentication (2FA) for **internal users** managed inside Keycloak in the `Digitalboard` realm, while **external users** coming from Microsoft Entra ID as Identity Provider are not prompted for OTP.
---
## Prerequisites
- Admin access to the **Keycloak Admin Console** for the `Digitalboard` realm.
- A running Keycloak instance (TLS termination handled by Traefik or Keycloak itself).
- Microsoft Entra ID already set up as an **Identity Provider** for the realm.
- Internal users stored directly in Keycloak (username/password authentication).
---
## Steps
### Step 1 — Verify External Identity Provider
1. In the **Digitalboard** realm, open the Admin Console.
2. Navigate to **Identity Providers**.
3. Confirm that **Microsoft Entra ID** is configured (OpenID Connect or SAML).
4. Ensure that external users sign in via this IdP.
---
### Step 2 — Configure OTP Policy
1. In the left-hand menu of the **Digitalboard** realm, go to **Authentication → OTP Policy** (or **Realm Settings → Security Defenses → OTP Policy**, depending on Keycloak version).
2. Configure the following:
- **Type**: `totp` (time based)
- **Digits**: `6`
- **Period**: `30` seconds
- **Algorithm**: `sha512`
- **Look ahead window**: `1-2`
- **Reusable token**: `off`
Click **Save**.
---
### Step 3 — Copy the Browser Flow
1. Navigate to **Authentication → Flows**.
2. Locate the built-in **Browser** flow.
3. Click **Copy**.
4. Enter the new name: `browser-internal-otp`.
This custom flow will handle **internal (local) user logins** for the `Digitalboard` realm.
---
### Step 4 — Add OTP Requirement
1. Open the `browser-internal-otp` flow.
2. Inside the **Browser Forms** sub-flow, locate the **Username Password Form**.
3. After it, click **Add execution** → select **OTP Form** (or **Conditional OTP** if available).
4. Set requirement to **Required**.
This ensures OTP is enforced for all username/password logins (internal users).
---
### Step 5 — Enable “Configure OTP” Required Action
1. In the **Digitalboard** realm, go to **Authentication → Required Actions**.
2. Locate **Configure OTP**.
3. Ensure the status is **Enabled**.
With this enabled, internal users without an OTP configured will be prompted to set it up during login.
---
### Step 6 — Bind the Flow
1. In the **Digitalboard** realm, go to **Authentication → Flows**.
2. Click the flow **browser-internal-otp** to open it.
3. In the top-right, open **Actions → Bind flow**.
4. In the dialog, choose **Browser flow** and click **Save**.
> This makes `browser-internal-otp` the default Browser flow, so **internal (local) users** who log in with username/password must use OTP.
**Important for external (Entra) users:**
- Go to **Identity Providers → (Microsoft Entra)** and ensure **Post Login Flow / Post Broker Login Flow** is **None** (or a flow **without** OTP), so external users don't get a Keycloak OTP prompt after IdP login.
---
### Step 7 — Test the Setup
1. Log in with an **internal Keycloak user** in the `Digitalboard` realm:
- After entering username and password, you should be prompted for OTP (or OTP setup if not already configured).
2. Log in with an **external Microsoft Entra user**:
- You should be redirected to Entra ID for login.
- After successful login, you should be signed in without an additional OTP prompt from Keycloak.
---
## Troubleshooting
- **External users see OTP prompt**: Check that **Post Broker Login Flow** is not set to `browser-internal-otp`.
- **Internal users not asked for OTP**: Verify that the **OTP Form** is present in `browser-internal-otp` and set to **Required**.
- **Looping on OTP setup**: Ensure realm time synchronization (NTP) and correct OTP policy values.
---
## Next Steps
- Roll out OTP to internal users gradually (pilot group).
- Provide instructions for enrolling an authenticator app (Google Authenticator, Microsoft Authenticator, FreeOTP).
- Monitor login events in the `Digitalboard` realm to confirm expected OTP usage.