# Apache Guacamole OIDC Integration with Authentik - Research Report **Research Task:** RESEARCH-003 **Date:** 2026-01-20 **Objective:** Comprehensive research on Apache Guacamole OIDC integration with Authentik --- ## 1. Complete List of OPENID_ Environment Variables ### Required Environment Variables For Docker installations of Apache Guacamole, the following environment variables are **required**: | Variable | Description | Example Value | |----------|-------------|---------------| | `OPENID_AUTHORIZATION_ENDPOINT` | Authorization endpoint URI from IdP | `https://sso.obr.sh/application/o/authorize/` | | `OPENID_JWKS_ENDPOINT` | JWKS endpoint for validating ID tokens (JWTs) | `https://sso.obr.sh/application/o//jwks/` | | `OPENID_ISSUER` | Expected issuer for all received ID tokens | `https://sso.obr.sh/application/o//` | | `OPENID_CLIENT_ID` | OpenID client ID for your application | From Authentik provider configuration | | `OPENID_REDIRECT_URI` | Full callback URL for Guacamole | `https://remote.obr.sh/guacamole/api/auth/openid-connect/callback` | ### Optional Environment Variables | Variable | Description | Default Value | |----------|-------------|---------------| | `OPENID_ENABLED` | Explicitly enable the extension | `true` (or set any OPENID_ variable) | | `OPENID_USERNAME_CLAIM_TYPE` | JWT claim for username | `email` | | `OPENID_GROUPS_CLAIM_TYPE` | JWT claim for groups | `groups` | | `OPENID_ATTRIBUTES_CLAIM_TYPE` | Comma-separated list of claims to expose as `OIDC_*` attributes | (empty) | | `OPENID_SCOPE` | OpenID scopes to request | `openid email profile` | | `OPENID_ALLOWED_CLOCK_SKEW` | Clock skew tolerance for token validation | `30` (seconds) | | `OPENID_MAX_TOKEN_VALIDITY` | Maximum token validity period | `300` (minutes/5 hours) | | `OPENID_MAX_NONCE_VALIDITY` | Maximum nonce validity period | `10` (minutes) | ### Extension Loading Control | Variable | Description | Effect | |----------|-------------|--------| | `EXTENSION_PRIORITY` | Controls authentication flow | `openid` = auto-redirect to IdP | | | | `*,openid` = show login screen first | ### Additional Configuration Requirement For standalone installations (non-Docker), you must enable environment property evaluation: ```properties # In /etc/guacamole/guacamole.properties enable-environment-properties: true ``` --- ## 2. Connection-Level Authentication Flow ### User Authentication vs. Connection Authentication **Critical Finding:** OIDC in Guacamole handles **user authentication** to the Guacamole web interface, **NOT connection-level authentication** to RDP/VNC/SSH hosts. ### How It Works 1. **User logs into Guacamole** via OIDC (SSO to Authentik) 2. **Guacamole creates a session** for the authenticated user 3. **Connections are accessed** based on permissions stored in the database extension (JDBC) 4. **Target system authentication** happens separately using configured credentials ### The Credential Passthrough Problem #### With LDAP Authentication (Works) ``` User → LDAP login → Guacamole stores credentials → RDP connection ↓ ${GUAC_USERNAME} and ${GUAC_PASSWORD} available ``` #### With OIDC Authentication (Does NOT Work) ``` User → OIDC login → Guacamole gets token only → RDP connection ↓ ${GUAC_PASSWORD} is NOT available (password never sent to Guacamole) ``` ### Parameter Tokens Available | Token | LDAP Auth | OIDC Auth | Notes | |-------|-----------|-----------|-------| | `${GUAC_USERNAME}` | ✓ Available | ✓ Available | Username from claim | | `${GUAC_PASSWORD}` | ✓ Available | ✗ NOT Available | Password never leaves IdP | ### OIDC Attribute Passthrough The `OPENID_ATTRIBUTES_CLAIM_TYPE` variable allows exposing JWT claims as `OIDC_*` parameters: ```bash # Example: Expose custom claims OPENID_ATTRIBUTES_CLAIM_TYPE=workstationName,department,employeeId ``` This creates connection parameters: - `${OIDC_workstationName}` - `${OIDC_department}` - `${OIDC_employeeId}` **Use Case:** Dynamic connection routing based on user attributes, NOT credential passthrough. --- ## 3. MFA Flow with TOTP Passthrough ### Guacamole's TOTP Support Apache Guacamole supports **TOTP (Time-based One-Time Password)** as a second authentication factor. ### TOTP Authentication Flow ``` ┌─────────────────────────────────────────────────────────────┐ │ 1. User attempts to log in │ │ ↓ │ │ 2. Primary authentication (OIDC/LDAP/Database) │ │ ↓ │ │ 3. If successful, TOTP extension checks for enrolled device │ │ ├─ Device enrolled: Prompt for TOTP code │ │ └─ No device: Force enrollment (QR code scan) │ │ ↓ │ │ 4. User enters 6-digit code from authenticator app │ │ ↓ │ │ 5. If code validates: Grant access │ │ └─ If code fails: Deny access │ └─────────────────────────────────────────────────────────────┘ ``` ### TOTP Extension Configuration **Extension File:** `guacamole-auth-totp-*.jar` **Environment Variables (Docker):** | Variable | Description | Default | |----------|-------------|---------| | `TOTP_ISSUER` | Issuer name shown in authenticator app | `Apache Guacamole` | | `TOTP_DIGITS` | Number of digits in TOTP code | `6` | | `TOTP_PERIOD` | Time period for code validity | `30` (seconds) | | `TOTP_MODE` | TOTP generation mode | `sha1` | ### Layered Authentication: OIDC + TOTP **Prerequisites:** - Database authentication extension (JDBC) installed for key storage - OIDC extension for primary authentication - TOTP extension for second factor **Flow:** 1. User → Authentik (OIDC with MFA at IdP level) → Guacamole login 2. Guacamole → TOTP challenge (separate from Authentik MFA) 3. User → Enters TOTP code → Access granted ### Important Limitation: Duo vs. TOTP with SSO **From official documentation:** > "Guacamole's Duo support cannot currently be used alongside single sign-on (SSO). If you need both MFA and SSO, you must use your SSO provider's own Duo integration or use TOTP instead of Duo." ### MFA Architecture Options #### Option A: MFA at IdP Level (Authentik) ``` User → Authentik (with TOTP/WebAuthn) → Guacamole Pros: Single MFA enforcement point, better UX Cons: No Guacamole-level MFA control ``` #### Option B: MFA at Guacamole Level ``` User → Authentik (no MFA) → Guacamole TOTP → Access Pros: Guacamole controls second factor Cons: Users authenticate twice (SSO + TOTP) ``` #### Option C: Dual MFA (Most Secure) ``` User → Authentik (with MFA) → Guacamole TOTP → Access Pros: Defense in depth, two independent factors Cons: Potential user friction ``` --- ## 4. RDP NLA Compatibility with SSO ### What is RDP NLA? **Network Level Authentication (NLA)** is a security feature in RDP that requires authentication **before** establishing a full remote desktop session. ### The Fundamental Incompatibility **Critical Finding:** OIDC SSO and RDP NLA have a credential passthrough problem. #### Why It Doesn't Work ``` ┌──────────────────────────────────────────────────────────┐ │ OIDC Flow (No Password to Guacamole) │ ├──────────────────────────────────────────────────────────┤ │ User → Authentik → JWT Token → Guacamole │ │ │ │ RDP NLA Requirement (Needs Actual Password) │ │ │ │ Guacamole → Windows Server (NLA) → ??? No password ??? │ └──────────────────────────────────────────────────────────┘ ``` **The Problem:** - OIDC authentication means the user's password **never reaches Guacamole** - RDP NLA requires a username/password for NTLM or Kerberos authentication - `${GUAC_PASSWORD}` token is **empty** when using OIDC ### Confirmed by Community Evidence **From mailing list discussions:** > "When using OpenID Connect (or SAML, or CAS without the ClearPass extension) for Guacamole login, the user's password is not shared between the Identity Provider (IdP) and Guacamole, meaning the `${GUAC_PASSWORD}` variable will not be available for use in RDP connections." ### Current Status of FreeRDP NLA Support Guacamole uses **FreeRDP** for RDP connections. Key limitations: 1. **NTLM-only NLA:** FreeRDP currently only supports NTLM variant of NLA 2. **No Kerberos NLA:** Kerberos NLA support is in development 3. **Protected Users Group:** Users in AD "Protected Users" group cannot authenticate via NTLM NLA ### Workarounds and Solutions #### Solution 1: Disable NLA on Target Systems ``` Pros: Simple, works immediately Cons: Reduced security, Microsoft discourages this ``` #### Solution 2: Credential Prompting ``` Leave RDP username/password blank → User prompted during connection Pros: Works with OIDC Cons: Users log in twice (SSO + RDP prompt) ``` #### Solution 3: Pre-configured Shared Accounts ``` Store RDP credentials in Guacamole connection config Pros: Single sign-on UX maintained Cons: Shared accounts, loses per-user audit trail ``` #### Solution 4: Use LDAP Instead of OIDC (Not Recommended) ``` LDAP auth → ${GUAC_PASSWORD} available → RDP NLA works Pros: Credential passthrough works Cons: Loses SSO benefits, security regression ``` #### Solution 5: Custom Authentication Extension **Community Solution:** `guacamole-auth-header-password` ```bash # Example: Pass credentials via HTTP headers http-username-header=OIDC_REMOTE_USER http-password-header=OIDC_access_token # Not a real password http-groups-header=OIDC_CLAIM_sdDesktopProjects ``` **Note:** This doesn't solve the password problem but shows extension architecture. #### Solution 6: CAS with ClearPass (Alternative SSO) ``` Apache Guacamole 0.9.14+ includes CAS credential pass-through using "ClearPass" which allows ${GUAC_USERNAME} and ${GUAC_PASSWORD} tokens with SSO ``` **Requires:** CAS server instead of OIDC ### Azure AD / Entra Joined Systems **Additional Complexity:** - Azure AD Joined (Entra-joined) systems may require web-based authentication - Guacamole cannot pass through the web sign-in mechanism - **Hybrid joined** (Azure AD + Domain joined) systems work better **From community reports:** > "Hybrid joined systems with NLA enabled are working fine with Guacamole/RDP" ### Recommended Approach for SSO + RDP NLA **Best Practice Architecture:** 1. **Use OIDC for Guacamole authentication** (SSO to Authentik) 2. **Configure RDP connections** with one of: - **Option A:** Dedicated service accounts (stored in connection config) - **Option B:** Prompt users for RDP credentials (UX compromise) - **Option C:** Disable NLA on internal trusted network segments only 3. **Implement connection-level access control** via Authentik groups 4. **Enable audit logging** to track connection access (even with shared accounts) --- ## 5. Authentik-Specific Configuration Notes ### Authentik Provider Setup **Provider Type:** OAuth2/OpenID Connect **Client Type:** Confidential **Scopes:** `openid`, `email`, `profile` ### Critical Authentik Settings 1. **Redirect URI:** ``` https://remote.obr.sh/guacamole/api/auth/oidc/callback ``` 2. **Token Validity:** ``` Max 300 minutes (5 hours) - Guacamole limitation ``` 3. **Signing Key:** ``` authentik Self-signed Certificate ``` ### Username Claim Configuration **Two Options:** #### Option A: Use `sub` (Recommended) ```bash OPENID_USERNAME_CLAIM_TYPE=sub ``` - Pros: Immutable, unique identifier - Cons: Not human-readable (UUIDs) - **Important:** Disable "Allow users to change username" in Authentik #### Option B: Use `preferred_username` ```bash OPENID_USERNAME_CLAIM_TYPE=preferred_username ``` - Pros: Human-readable usernames - Cons: May change if user updates profile - **Requires:** Custom property mapping in Authentik ### Custom Property Mapping for Usernames **In Authentik:** Create Scope Mapping to expose custom username attribute ```python # Example: Map custom field to preferred_username claim { "preferred_username": user.attributes.get("guacamole_username", user.username) } ``` ### Pre-creating Admin User **Best Practice:** Create admin user in Guacamole database **before** enabling OIDC ```sql -- Insert user matching Authentik username INSERT INTO guacamole_entity (name, type) VALUES ('admin@example.com', 'USER'); -- Grant admin permissions INSERT INTO guacamole_user_permission (entity_id, permission) VALUES ((SELECT entity_id FROM guacamole_entity WHERE name='admin@example.com'), 'ADMINISTER'); ``` --- ## 6. Key Takeaways and Recommendations ### Confirmed Capabilities ✓ OIDC authentication to Guacamole web interface works well with Authentik ✓ Username passthrough (`${GUAC_USERNAME}`) available with OIDC ✓ Custom JWT claims can be exposed as `${OIDC_*}` parameters ✓ TOTP MFA can be layered on top of OIDC authentication ✓ Groups from Authentik can control connection access ### Critical Limitations ✗ Password passthrough (`${GUAC_PASSWORD}`) does NOT work with OIDC ✗ RDP NLA requires passwords, creating incompatibility with OIDC SSO ✗ No per-connection SSO (OIDC only authenticates to Guacamole, not target systems) ✗ Duo MFA cannot be used with SSO (use TOTP instead) ### Recommended Architecture **For Pangolin/Authentik/Guacamole Integration:** 1. **Primary Authentication:** OIDC to Authentik (SSO) 2. **MFA Strategy:** MFA at Authentik level (TOTP/WebAuthn) 3. **RDP Authentication:** - Service accounts for automated access - User prompting for per-user audit requirements - NLA disabled on trusted internal segments (if acceptable) 4. **Database Extension:** Required for connection storage and TOTP keys 5. **Group Mapping:** Use `OPENID_GROUPS_CLAIM_TYPE=groups` to control access ### Environment Variable Template for Pangolin ```bash # Authentik OIDC Integration OPENID_AUTHORIZATION_ENDPOINT=https://sso.obr.sh/application/o/authorize/ OPENID_JWKS_ENDPOINT=https://sso.obr.sh/application/o/guacamole/jwks/ OPENID_ISSUER=https://sso.obr.sh/application/o/guacamole/ OPENID_CLIENT_ID= OPENID_REDIRECT_URI=https://remote.obr.sh/guacamole/api/auth/oidc/callback # Claim Configuration OPENID_USERNAME_CLAIM_TYPE=preferred_username OPENID_GROUPS_CLAIM_TYPE=groups OPENID_SCOPE=openid email profile # Token Settings OPENID_MAX_TOKEN_VALIDITY=300 OPENID_ALLOWED_CLOCK_SKEW=30 # Extension Loading EXTENSION_PRIORITY=openid OPENID_ENABLED=true # Enable environment variables in guacamole.properties enable-environment-properties: true ``` --- ## References - Apache Guacamole Official Documentation: https://guacamole.apache.org/doc/gug/openid-auth.html - Authentik Integration Guide: https://docs.goauthentik.io/integrations/services/apache-guacamole/ - Guacamole Mailing List Archives: https://www.mail-archive.com/user@guacamole.apache.org/ - FreeRDP NLA Limitations: Community reports on NTLM vs Kerberos support - TOTP Extension Guide: https://guacamole.apache.org/doc/gug/totp-auth.html --- **Research Completed:** 2026-01-20 **Task:** RESEARCH-003 **Status:** Complete