Global SSO Provider Missing From Portal - edmozley/freeitsm GitHub Wiki

A global SSO provider was missing from the portal

Reported in #156 ยท Fixed in #2044 ยท Ships in 2.9.1


What you saw

You ran FreeITSM with more than one company, turned on single sign-on, and added a provider (Keycloak, in the report) with its company set to Global.

  • The analyst login showed Sign in with Keycloak, and it worked.
  • The self-service portal login showed no Keycloak button at all. Typing your email and pressing Continue just asked for a password.

Then you pinned the same provider to Default Company instead. There was still no button on the portal, but typing an email from that company's domain sent you straight to Keycloak. So it looked as if the portal half-worked, depending on a setting that should not have mattered.


What was actually wrong

The portal login has two ways to reach a provider, and on a multi-company install a Global provider fell between them.

1. Buttons up front. On a single-company install, every enabled Global provider is a button. On a multi-company install the page showed no buttons at all โ€” on purpose. A provider can belong to one client company, and printing every client's "Sign in with โ€ฆ" button on a page anyone can load would tell every visitor which identity provider each client uses.

<?php if (!$multiTenant): ?>
    <!-- Single-company: providers are global, so show them up front. -->
    ...buttons...
<?php endif; ?>

2. Email first. You type your email, and api/auth/resolve_login.php works out your company from its domain and looks for that company's providers:

"SELECT id, display_name FROM auth_providers
  WHERE tenant_id = ? AND enabled = 1 AND protocol = 'oidc' ..."

A Global provider has tenant_id = NULL. It belongs to no company, so tenant_id = ? never matches it.

So the button was hidden by rule 1 and the lookup could not find it by rule 2. The only people who could still get in were requesters already linked to that provider by an earlier sign-in, which is why this was easy to miss on an install that had been running for a while.

Why the second report was not a bug

Pinned to Default Company, the provider was found by email, and a company with exactly one provider is sent straight to it โ€” there is nothing to choose. With two or more the portal shows a "Choose how to sign in" list. Not listing a company's own provider up front is the privacy rule above, working as intended.

The rule caught more than it meant to

The reason for hiding buttons was to keep one client's provider away from other clients. A Global provider is not a client's โ€” it serves every company, and the analyst login already shows it to anyone who loads that page. Hiding it on the portal protected nothing and made it unreachable.


How it was fixed

The portal now shows Global providers as buttons on every install. Company-owned providers stay off the page and are still found by email, exactly as before.

<?php if (!empty($ssoProviders)): ?>
    <!-- Global providers serve every company, so show them up front
         on any install (GH #156 - multi-tenant used to hide them). -->
    ...buttons...
<?php endif; ?>

$ssoProviders was already restricted to Global OIDC providers (tenant_id IS NULL AND protocol = 'oidc'), so no company's provider can slip in through this change.

What was deliberately not done

The email lookup could have fallen back to the Global provider when a company has none of its own. It does not, for two reasons:

  • A single-company install does not do that either โ€” an email with no pinned provider goes to the password form, and the button is how you choose SSO.
  • It would silently move every requester who signs in with a password over to SSO the moment someone adds a Global provider.

๐Ÿ“ Files changed

File Change
self-service/login.php Global provider buttons are shown on a multi-company install too; the "Sign in with a local account" link keeps its old single-company-only placement

How it was verified

On a real install with four companies, SSO on, one Global OIDC provider (Okta), two OIDC providers owned by one company (Keycloak and Microsoft) and a Global LDAP directory:

  • Before the fix (the old file restored, the page fetched over HTTP): 0 provider buttons on the portal login.
  • After: exactly 1 โ€” Sign in with Okta. Keycloak and Microsoft, which belong to a company, are still absent; the LDAP directory is still absent (it has nothing to redirect to).
  • The Okta button's link returns a 302 to Okta's /authorize with the portal flag carried, so it starts a real portal sign-in.
  • The email lookup is unchanged: an address on that company's domain still returns the two-provider picker, and a Gmail address still returns the password form.
  • api/auth/oidc_callback.php places a new requester signing in through a Global provider in a company by their email domain (resolveTenantForNewUser()), so nothing downstream assumed a portal provider always had a company.

Not proven here: a complete round trip through Okta's own sign-in screen, which needs a real account on that tenant.


What this means for you

  • Single-company install: nothing changes.
  • Multi-company install with a Global provider: after upgrading, its button appears on the portal login. Nothing to configure.
  • Want a provider on the portal for one company only? Pin it to that company. It stays off the page and is reached by email.

Related pages