From c8231193c9489d7a50ceef0da7d70dcda41c171f Mon Sep 17 00:00:00 2001 From: Bert-Jan Fikse Date: Fri, 12 Sep 2025 14:04:59 +0200 Subject: [PATCH] chore: add guide to enforce otp for internal users in keycloak --- README.md | 12 ++-- keycloak/enforce-otp-internal.md | 100 +++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+), 5 deletions(-) create mode 100644 keycloak/enforce-otp-internal.md diff --git a/README.md b/README.md index 6098df3..7516c5e 100644 --- a/README.md +++ b/README.md @@ -6,15 +6,17 @@ This repository contains documentation, guides, and reference material. - **[Keycloak](./keycloak/)** 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/)** Documentation and guides related to Microsft Entra configuration and best practices. - [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. -- **[Infrastructure](./infrastructure/)** - Documentation and guides related to infrastructure configuration and best practices. - - [IPV6](./infrastructure/ipv6/ipv6.md) +- **[Infrastructure](./infrastructure/)** + Documentation and guides related to infrastructure configuration and best practices. + - [IPV6](./infrastructure/ipv6/ipv6.md) Documentation of the ipv6 concept. - - [ACME](./infrastructure/acme.md) - Documentation of the ACME concept. \ No newline at end of file + - [ACME](./infrastructure/acme.md) + Documentation of the ACME concept. diff --git a/keycloak/enforce-otp-internal.md b/keycloak/enforce-otp-internal.md new file mode 100644 index 0000000..5c1e730 --- /dev/null +++ b/keycloak/enforce-otp-internal.md @@ -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.