Saml2 plugin for phpList
After cd-ing into the configured phpList plugin directory:
git clone git@github.com:phpList/phplist-plugin-saml2.git
You can configure saml from the phplist configuration page "SSO config" category (except for certificate which should be added manually in the cert folder)
you will need to give write permission to the simplesaml/settings.php file
https://resources.phplist.com/plugin/simplesaml#simplesamlphp_installation_check
- In [phplist-plugin-saml2/plugins/simplesaml/simplesamlphp/config/authsources.php] the following parameters will to be set:
entityID: TheentityIDis essentially the client ID which is specified in Keycloak or IDPidp: The IDP is the identifier for the IdP (Keycloak) which simplesaml would connect to.RelayState: TheRelayStatespecifies wheresimplesamlphpshould redirect to after a successful authentication. Basically it's like a callback url. This should simply be the URL from which the authentication started. Hence, a 'redirect back'.NameIDPolicy: The IdP is expected to return aNameIDevery successful auth session, this name ID is what identifies the user. Depending on the IdP thisNameIDmight change every session. That makes it impossible to tract the user across session. So we have to said theNameIDPolicytopersistentessentially telling the IdP to send the sameNameIDall the time for the same user.
Theauthsources.php will look like (values set automatically from configuration):
<?php
$config = [
//...
//...
// An authentication source which can authenticate against SAML 2.0 IdPs.
'default-sp' => [
'saml:SP',
// The entity ID of this SP.
// Can be NULL/unset, in which case an entity ID is generated based on the metadata URL.
'entityID' => 'account',
// The entity ID of the IdP this SP should contact.
// Can be NULL/unset, in which case the user will be shown a list of available IdPsnt.
'idp' => 'https://sso.phplist.com:8443/realms/master',
'baseurlpath' => 'https://saml.phplist.test/',
'RelayState' => 'http://phplist.test/lists/admin',
'NameIDPolicy' => [
'Format' => 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent',
'AllowCreate' => true
],
],
//...
//...
];- In [phplist-plugin-saml2/plugins/simplesaml/simplesamlphp/config/config.php] the following parameters will be set:
baseurlpath: Thebaseurlpathrefers to the base url the runningSimpleSAMLconfiguration. Depending on where simplesaml was installed, it could be a separate domain such asphplist.com/simplesamlphp/wwwor a path likephplist.com/admin/simplesamlphp/www.
NB: The baseurlpath (which is essentially the simplesaml installation) is where the IdP returns the SAML response after a successful login. The SAML request would then be parsed and simplesamlphp would redirect back to the phplist url that sent the request or the one set via the RelayState property in the config array of authsources.php within the config dir.
The config.php will look like:
<?php
$config = [
//...
//...
'baseurlpath' => 'http://phplist.test/simplesamlphp/www/',
//...
//...
];- In [phplist-plugin-saml2/plugins/saml2/simplesamlphp/metadata/saml20-idp-remote.php] metadata about the IdP will be provided:
- Metadata array: The metadata should be assigned to
$metadata['id'](where id is the idp identifier passed toidpparamater in the config above!) - SingleSignOnService: The keycloak endpoint to send login requests to.
- SingleLogoutService: The keycloak endpoint to send logout requests to.
- certData: This contains certificate information used in signing requests and verifying responses from keycloak.
How listed meta parameters?
More metadions may be fata optound here
The saml20-idp-remote.php file should look like :
<?php
//...
//...
$metadata['https://sso.phplist.com:8443/realms/master'] = [
'SingleSignOnService' => 'https://sso.phplist.com:8443/realms/master/protocol/saml',
'SingleLogoutService' => 'https://sso.phplist.com:8443/realms/master/protocol/saml',
'certData' => 'CERT_STRING_',
];certData will be taken from the cert/saml-remote-idp.crt file (you should add a certificate there, it will not be set from configuration page as other values are)
- Set up
phplist.domain/simplesamlphpto point tophplist-plugin-saml2/plugins/simplesaml/simplesamlphp
- **VERY SIMPLE: ** After following the steps in the configuration phase above, simply copy the contents of
phplist-plugin-saml2/plugins/simplesaml/simplesamlphptoPATH_TO_PHPLIST_INSTALLATION/public_html/simplesamlphp. OR; - A symlink from
phplist-plugin-saml2/plugins/simplesaml/simplesamlphptoPATH_TO_PHPLIST_INSTALLATION/public_html/simplesamlphpshould work. OR; - Server configuration to pass traffic from
phplist.domain/simplesamlphptophplist-plugin-saml2/plugins/simplesaml/simplesamlphp.
Notes: The symlink method would not work in docker and the "VERY SIMPLE" method creates some redundancy. However the goal is that, by whatever means phplist.domain/simplesamlphp points to PATH_TO_PHPLIST_INSTALLATION/public_html/simplesamlphp.
You might be required to manually create a log directory inside PATH_TO_PHPLIST_INSTALLATION/public_html/simplesamlphp with write permissions granted, so: mkdir log && sudo chmod -R a+rwx log
NB: simplesamlphp MUST BE CONFIGURED ON SAME DOMAIN as your phplist installation. Hence phplist.domain/simplesamlphp SHOULD point to phplist-plugin-saml2/plugins/simplesaml/simplesamlphp.
- Updating is not recommended
Keycloak is used as the IdP in this setup. Any other IdP may be used as long as the correct configuration is set in the simplesamlphp config and simplesamlphp metadata directories.
Once keycloak server as been installed an admin user would need to setup. With such a user, it would pe possible create/change the different configurations that would allow keycloak work with simplesamlphp. The two most important parts of the configurations are Realms and Clients
In Keycloak, realms are used to isolate and manage a set of users, credentials, roles, and groups. A user belongs to and logs into a realm. With this in mean you can configure multiple Realms to serve different service providers, applications, organizations or whatever entity that needs to have it's own "database". That said, we do need a realm for this setup!
Keycloak does creates a Master realm by default but more realms can be created as seen under "creating a realm" on the keycloak documentation!
Within the realm, there are clients! A client is an entity that can request Keycloak to authenticate a user. Most often, clients are applications and services that want to use Keycloak to secure themselves and provide a single sign-on solution. Essentially, the client represents or serves as a connector that makes request on behalf of the service provider (in this case simplesamlphp)
Again, we have a couple of default clients created in the Master realm by keycloak! Each client contains access control information such as roles and scope!
The account client is used in this setup to connect keycloak simplesamlphp as it contains good defaults
So under the clients section (https://{host.address.ext}/auth/admin/master/console/#/realms/master/clients/) of keycloak;
- Open the
accountclient or the one created as shown and make sure the configuration metioned below are set accordingly!
- Protocol: The
Client Protocoldropdown is set tosamlto avoidWrong protocolerror. - Signing: The
Sign Assertionsswitch is turned on, as simplesamlphp would throwUnhandled Exception "Neither the assertion nor the response was signed." - AuthnStatement: The
Include Authn Statementis turned on to avoid :Unhandled Exception "No AuthnStatement found in assertion(s)." - Valid Redirect URIs: Set the
Valid Redirect URIsfield to point to the phplist installation (with simplesamlphp plugin) for example,saml.phplist.comor simplyphplist.com.
simplesamlphprequires at leastphp-7.4, phplist 3 accepts,php-7.0,php-7.1,php-7.2,php-7.3.
For
Fatal error:
Fatal error: Uncaught SimpleSAML\Error\CriticalConfigurationError: The configuration is invalid: Setting secure cookie on plain HTTP is not allowed. in ...or
SimpleSAML\Error\CriticalConfigurationError: The configuration is invalid: Setting secure cookie on plain HTTP is not allowed.
Backtrace:Change session.cookie.secure in plugins/simplesaml/simplesamlphp/config.php from true => false.
For
SimpleSAML\Error\Error: UNHANDLEDEXCEPTION
Backtrace:
2 www/_include.php:17 (SimpleSAML_exception_handler)
1 vendor/symfony/error-handler/ErrorHandler.php:607 (Symfony\Component\ErrorHandler\ErrorHandler::handleException)
0 [builtin] (N/A)
Caused by: SimpleSAML\Error\Exception: URL not allowed: http://phplist.test/lists/admin/
Backtrace:
3 lib/SimpleSAML/Utils/HTTP.php:444 (SimpleSAML\Utils\HTTP::checkURLAllowed)
2 modules/saml/www/sp/saml2-acs.php:135 (require)
1 lib/SimpleSAML/Module.php:273 (SimpleSAML\Module::process)
0 www/module.php:10 (N/A)
Add the "not allowed" domain to the list of trusted URLs in config.php:
'trusted.url.domains' => ['phplist.test'],