This describes how to configure a single Joomla install running RO Single Sign On so that it acts as both a SAML Identity Provider (IdP) and a Service Provider (SP) - i.e. it authenticates its own users directly, but every login (including its own front-end/admin login) goes through the SAML flow. This is also the setup used to test an IdP without needing a second site: the SP trusts itself as the IdP ("self-loop").
Concepts and terminology
The component's screen names don't map 1:1 onto "IdP" and "SP" the way you'd expect - keep this in mind or the rest of this doc will be confusing:
| Screen (Components -> RO SSO ->) | What it actually configures |
| Configuration | This instance's own hosted IdP (if "Identity Provider" is enabled) |
| Identity Provider Profiles | A remote IdP this instance (as SP) trusts and can log in through |
| Service Provider Clients | A remote SP this instance (as IdP) trusts and will issue assertions to |
| Certificates | SSL certificate/key pairs available to the above screens |
So making a site act as an IdP is done under **Configuration**. Making it also act as an SP - including trusting itself, for a self-loop test - is done under Identity Provider Profiles (create the SP-side authsource pointing at an IdP) and Service Provider Clients (register that SP as trusted on the IdP side). Both of the latter screens write their generated metadata into the same kind of folder, libraries/simplesamlphp/metadata-generated/<name>/, so Profile aliases and Client output folders must never collide - see "Alias/output folder collisions" below.
Prerequisites
- Install pkg_ro_sso_version.zip (or the individual extension zips) via System -> Manage -> Install.
- Go to System -> Manage -> Plugins, find Authentication - RO Single Sign On, and enable it.
- Go to System -> Manage -> Plugins, find System - RO Single Sign On, and enable it.
- During the installation RO Single Sign On will create a symlink. In case this fails, you will need to do this yourself. This one step needs server/hosting access rather than the Joomla admin - ask your host or developer if you don't have it: a shortcut ("symlink") named sso needs to be created in the site's root folder, pointing at libraries/simplesamlphp/public/. This is what makes the login pages reachable while keeping the rest of that folder private:
ln -sfn libraries/simplesamlphp/public sso - At least one certificate/private key pair created under Certificates.
- Go to Components -> RO SSO -> Configuration.
Step 1 - Configure the site as an Identity Provider
Components -> RO SSO -> Configuration:
- Fill in the general SimpleSAMLphp settings (admin password, secret salt, technical contact).
- Enable Identity Provider.
- Select the private key and certificate to sign assertions with.
- Choose the login module (default: joomla:Joomla, which authenticates against #__users).
- Save.
This writes libraries/simplesamlphp/metadata/saml20-idp-hosted.php, keyed by this instance's IdP entity ID: <scheme>://<host>/<baseurlpath>saml2/idp/metadata.php (e.g. https://idp.example/sso/saml2/idp/metadata.php). That URL is also the metadata endpoint - open it in a browser to confirm it returns SAML metadata XML and that the entityID attribute in that XML matches the URL itself.
Step 2 - Make the site trust an IdP (Identity Provider Profiles)
This is the SP side: it creates a saml:SP authsource that will send login requests to a target IdP. To make the site log itself in through the IdP configured in Step 1, target the site's own metadata endpoint.
Components -> RO SSO -> Identity Provider Profiles -> New:
- Name / Alias - pick something distinct from any existing Client's output folder (see collision warning below). For a self-loop test, e.g. idp.
- Identity Provider Metadata URL - the IdP's metadata endpoint, e.g. https://idp.example/sso/saml2/idp/metadata.php (from Step 1). Leave Identity Provider Login URL empty unless the login endpoint genuinely differs from the metadata URL (ADFS-style setups only) - it's auto-derived from the fetched metadata otherwise, and a stale manual value here is a common source of METADATANOTFOUND errors after the target IdP's metadata changes.
- Configure the attribute/field mapping as needed.
- Save.
Saving fetches the IdP's metadata and writes metadata-generated/<alias>/saml20-idp-remote.php, and adds a saml:SP entry to config/authsources.php keyed by the alias.
Step 3 - Make the IdP trust this SP (Service Provider Clients)
This is the IdP side: the IdP will refuse to process a login request from an SP entity it doesn't have metadata for, so the SP authsource created in Step 2 - including a self-loop pointing back at this same site - must also be registered here.
Components -> RO SSO -> Service Provider Clients -> New:
- Name - descriptive.
- URL - the SP's own metadata endpoint: <scheme>://<host>/<baseurlpath>module.php/saml/sp/metadata.php/<profile-alias>, where <profile-alias> is the alias used in Step 2 (e.g. https://idp.example/sso/module.php/saml/sp/metadata.php/idp).
- Output Folder - pick something distinct from the Profile alias used in Step 2 (and from every other Profile alias / Client output folder). Do not reuse the same name - see below.
- Save.
Step 4 - Test
- Trigger a login through the Profile created in Step 2 (e.g. the site's own login page/module pointed at that profile, or index.php?option=com_sso&task=login.login&profile=<alias>).
- You should be redirected to the IdP login (or silently authenticated if already logged in there), then back, and end up logged into Joomla.
- If it fails, check administratorlogs/simplesamlphp.log (or wherever loggingdir points) for the technical SimpleSAMLphp error - the site itself only shows a generic "single sign-on login could not be completed" message to end users.
Alias/output folder collisions
metadata-generated/<name>/ is exclusive to one metadata source. SimpleSAMLphp's metarefresh module (MetaLoader::writeMetadataFiles()) always checks for all known metadata types (saml20-idp-remote, saml20-sp-remote, attributeauthority-remote) in that directory on every refresh, and deletes whichever type it didn't just regenerate as "stale". If a Profile and a Client share a name, refreshing either one silently wipes out the other's generated file, breaking login with METADATANOTFOUND until the wiped-out one is refreshed again. RO Single Sign On will check for name collisions and will inform you if it finds one.
The component validates this on save (a Profile alias already used by a Client's output folder, or vice versa, is rejected with a clear error) - but always give the Profile (Step 2) and the Client (Step 3) different names, even in a self-loop setup, e.g. idp for the Profile and idp-sp for the Client.
Renaming an alias / output folder
Renaming a Profile's alias or a Client's output folder now automatically removes the old metadata-generated/<old-name>/ directory once the save succeeds, so stale folders don't accumulate.
Known limitation: SimpleSAMLphp's own cron
SimpleSAMLphp's module_cron/module_metarefresh (configured automatically once at least one Profile/Client exists) refreshes remote metadata directly, bypassing this component's PHP entirely. If a remote IdP's entity ID ever changes, that cron can rekey metadata-generated/<alias>/saml20-idp-remote.php with no way for authsources.php's idp target to be notified - only saving/refreshing the Profile through the admin UI re-syncs that. If a working setup suddenly starts failing with METADATANOTFOUND for an entity ID that used to work, re-save the affected Profile.