Skip to content

Single-sign on (SSO) in front of Fleet Desktop > My Device #47116

Description

@noahtalerman

@noahtalerman: Let's plan on addressing this at the same time:

We don't want SSO to pop up during macOS setup experience.


Goal

User story
As a Fleet user,
I want to require that my end users are signed-in via SSO (IdP) before they can access Fleet Desktop on their macOS, Windows, Linux, or iOS/iPadOS host
so that I can enforce an extra layer of authentication.

Changes

Product

  • UI changes: Figma
  • CLI (fleetctl) usage changes: No changes
  • YAML changes: PR
  • REST API changes: PR
  • Fleet's agent (fleetd) changes: No changes
  • Fleet server configuration changes: No changes
  • Exposed, public API endpoint changes: No changes
  • fleetdm.com changes: No changes
  • GitOps mode UI changes: New radio button field is disabled in GitOps mode.
  • GitOps generation changes: Include new fleet_desktop > sso_enabled key in generated GitOps YAML.
  • Activity changes: PR
  • Permissions changes: No changes
  • Changes to paid features or tiers: No changes
  • My device and fleetdm.com/better changes: No changes
  • Usage statistics: PR
  • Other reference documentation changes: No changes
  • First draft of test plan added
  • Once shipped, requester has been notified
  • Once shipped, dogfooding issue has been filed

Engineering

Sub-tasks:

ℹ️  Please read this issue carefully and understand it. Pay special attention to UI wireframes, especially "dev notes".

Risk assessment

  • Requires testing in a hosted environment: Yes — end-to-end verification needs a real IdP and real fleetd-enrolled devices, including the Setup Experience flow (Fleet Desktop should not trigger My Device auth during Setup Experience enrollment #43593) and an alternative_browser_host topology.
  • Risk level: Low
  • Risk description: fleet_desktop.sso_enabled defaults to false, so every PR merges with zero behavior change until an admin enables it; enforcement is new code alongside (not replacing) existing device auth. Watch for: device-endpoint regressions with the setting off (pinned by snapshot tests in Fleet Desktop SSO: enforcement gate and exclusion list #51521), and the excluded fleetd endpoints (/desktop, /ping, /debug/errors) which must never be gated.

Test plan

Make sure to go through the list and consider all events that might be related to this story, so we catch edge cases earlier.

Core flow

Prerequisites: Fleet Premium; an IdP configured in Settings > Integrations > Authentication (SSO) > End users; at least one host enrolled with fleetd.

  1. As a global admin, go to Settings > Organization settings > Fleet Desktop. Verify the End user authentication radio group renders per Figma with Hourly token rotation selected by default, and select Single sign-on (SSO), then Save.
  2. Verify the enabled_sso_fleet_desktop activity appears in the activity feed (no detail fields).
  3. On an enrolled host, verify the Fleet Desktop tray is unaffected: icon reaches "🟢 My device" (or "🔴 My device (N)" with failing policies), and Self service / About Fleet items appear as before.
  4. Click My device in the tray. Verify the browser is redirected to the IdP sign-in page, and after signing in, lands on the My device page with full data.
  5. Reload the My device page and navigate to Self-service / Software / Policies tabs. Verify no second IdP prompt (session persists).
  6. Call a device API endpoint directly with only the token (e.g. curl -i https://<server>/api/latest/fleet/device/<token>, no cookies). Verify 401 whose JSON body includes "sso_required": true. Verify every excluded endpoint still behaves exactly as with the setting off: GET .../desktop and HEAD .../ping return 200, GET .../transparency redirects, POST .../debug/errors accepts a report, and POST .../sso starts the flow.
  7. Switch the setting back to Hourly token rotation. Verify the disabled_sso_fleet_desktop activity, and that the My device page works with the token alone again.

Edge cases

  • With no IdP configured: verify the SSO radio is disabled with tooltip "This setting requires an IdP configured in Settings > Integrations > Authentication (SSO) > End users.", and PATCH /api/v1/fleet/config with {"fleet_desktop":{"sso_enabled":true}} returns 422 naming the missing IdP.
  • Configure the IdP and sso_enabled: true in the same PATCH payload — succeeds.
  • With SSO enabled, attempt to clear mdm.end_user_authentication (UI and API). Verify 422 telling the user to disable Fleet Desktop SSO first; after disabling SSO, clearing the IdP succeeds.
  • Re-asserting the same sso_enabled value (true→true, false→false) generates no activity.
  • Session expiry: after the device SSO session TTL elapses (or with the cookie deleted), the next My device visit re-prompts the IdP once — no redirect loop.
  • Cookie/host binding: use host A's browser session cookie with host B's device token — expect 401.
  • Invalid/expired device token with a valid SSO session — expect the existing "This URL is invalid or expired." error, not an SSO redirect.
  • Setup Experience (Fleet Desktop should not trigger My Device auth during Setup Experience enrollment #43593): ADE-enroll a Mac with Setup Experience configured and SSO enabled. Verify no IdP prompt appears during Setup Assistant; after setup completes, the next My device click prompts normally.
  • Setup Experience with ADE end user authentication off (mdm.macos_setup.enable_end_user_authentication: false): repeat the check above. The gate exempts every host that is awaiting configuration, whether or not the end user authenticated to the IdP during enrollment, so this path needs its own pass rather than being assumed from the case above.
  • Setup Experience release window: watch the Setup Assistant web view at the moment setup completes and the device is released. Verify it does not flash an IdP redirect or an error before closing. The exemption is keyed on the host still awaiting configuration, and that flag clears when the device acknowledges DeviceConfigured — which can happen while the web view is still open showing its "done" state.
  • Setup Experience exemption boundary: while a host is awaiting configuration, curl -i https://<server>/api/latest/fleet/device/<token> with no cookies returns 200 — this carve-out is deliberate, and means a leaked device URL reaches device endpoints without SSO for the duration of setup. Re-run the same call after setup completes and verify it returns 401 with "sso_required": true.
  • Fleet Desktop Migrate to Fleet: with SSO enabled and no browser session, trigger the tray's migration dialog on a host pending MDM migration. Verify the migration webhook still fires — POST /device/{token}/migrate_mdm is exempt from the gate because fleetd posts it with the device token alone and has no browser in which to sign in.
  • alternative_browser_host set (proxy topology): verify the full SSO round-trip works when browsing through the alternative host.
  • iOS/iPadOS host: verify the device page SSO flow works with certificate-based device auth.
  • Hosts enrolled before the feature was enabled behave identically to newly enrolled hosts.

UI

  • Verify that all UI changes specified in the Figma wireframes are correctly implemented (radio group, labels, updated section description, disabled-state tooltip)
  • Verify expected UI states (loading, empty, error states if applicable), including the My device page "redirecting to sign-in" and SSO-failure states

API

  • Test all API endpoints added or modified in the API changes section of this issue (fleet_desktop.sso_enabled on GET/PATCH /api/v1/fleet/config; POST /api/_version_/fleet/device/{token}/sso; SSO-required 401 on gated device endpoints)
  • Verify any new API endpoints appear in the list when adding an API-only user. The API endpoints display name, method, and path is the same as listed in the API reference docs
  • Verify error handling for invalid inputs where applicable (sso_enabled non-boolean; enabling without IdP; enabling on Free)

GitOps (generate + run)

  • Configure the feature through the UI and run fleetctl generate-gitops
  • Confirm the generated .yml includes the expected fields (org_settings.fleet_desktop.sso_enabled, compare with YAML changes in the Product section)
  • Modify the generated .yml and run fleetctl gitops
  • Confirm the configuration updates correctly in Fleet (including the toggle activity)
  • Enable GitOps mode and verify the feature behaves correctly (End user authentication radios disabled in the UI)

Permissions

  • Verify role restrictions are applied correctly for global roles (admin, maintainer, observer, observer+, GitOps) — only roles that can modify org settings can change the setting; observers see it read-only per existing org-settings behavior
  • Verify role restrictions are applied correctly for fleet-level roles — fleet-scoped users cannot modify this global setting

Premium gating (if this is a premium-only feature)

  • Verify the feature is blocked on Fleet Free in the frontend (Fleet Desktop section absent from org settings nav)
  • Verify the feature is blocked on Fleet Free in the backend (PATCH /config with sso_enabled: true returns the license error; license downgrade resets the value to false)

Upgrade / data migration

  • Verify behavior on a server upgraded from a prior version (not just a fresh install) — existing fleet_desktop config is preserved and sso_enabled defaults to false
  • Verify existing data is migrated/handled correctly (no migration required; app config JSON gains the key on first save)

Feature in isolation (MDM / platform independence)

  • Verify the feature works on a fully configured server (all MDM platforms enabled)
  • Verify the feature works in isolation — Apple MDM off with only the End users IdP configured (the SSO callback route must not require Apple MDM); Windows-only and Linux-only hosts complete the flow

Supplemental testing

Testing notes

Confirmation

  1. Engineer: Added comment to user story confirming successful completion of test plan (include any special setup, test data, or configuration used during development/testing if applicable).
  2. QA: Added comment to user story confirming successful completion of test plan.
  3. QA: Determined whether this story needs Playwright automation.
    • Needs automation: Yes / No
    • If yes, filed a follow-up issue in the :help-qa project with status "Needs automation":

Metadata

Metadata

Assignees

Type

No type

Projects

Status
No status
Status
🎗️ Feature request
Status
✔️Awaiting QA

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions