AuthUserSaml
Questions answered by this recipe
How can I add "login with SAML" option to my PMWiki?
Description
SAML authentication extension for AuthUser.
This recipe adds the directive:
- (:saml_loginbox:)
Notes
Security Assertion Markup Language(SAML) is an open standard for exchanging authentication and authorization data between parties, in particular, between an identity provider and a service provider. See https://en.wikipedia.org/wiki/Security_Assertion_Markup_Language for a more extensive explanation.
This extension uses the SAML implementation library from SimpleSAMLphp (https://simplesamlphp.org) for integrating SAML authentication into AuthUser. Look at the documentation about SimpleSAMLphp at https://simplesamlphp.org/docs and in particularly the SimpleSAMLphp Service Provider QuickStart page.
In the AuthUserSaml GitHub repository is a docker-examples/
directory which contains 3 examples of an identity provider and a service provider setup using SimpleSAMLphp. Each example is run with docker compose to start both the identity provider and a service provider at once. One example demonstrates SAML with a simple php script, and the other two examples with pmwiki as service provider; once for a basic config, and the other with a more advanced config. The advanced PmWiki example is also used to show Single SignOn and Single Logout feature of SAML by using docker compose to start one instance of IDP and two separate instances of the PmWiki website:
- Single SignOn(SSO): if you login to one PmWiki website with your credentials, you can directly login to the other PmWiki website without needing to supply your credentials again.
- Single Logout(SSL): if you logout from one PmWiki website you are directly logged out from the other PmWiki website.
Take a look at these examples to better understand how it all works. The docker-examples/
directory is also in the AuthUserSaml release.
Installation Process
install cookbook script
1. Create a subdirectory named AuthUserSaml
in the cookbook directory. Then copy the file AuthUserSaml.php
from the release zip into this directory.
2. edit your local/farmconfig.php
or local/config.php
file just before line including authuser.php to add the following line
include_once("$FarmD/cookbook/AuthUserSaml/AuthUserSaml.php"); // Must be included before authuser
4. Modify your wiki's Site.AuthForm
Page to include (suit to your needs):
(:saml_loginbox:)
You can change the text in the login button by setting the $AuthUserSaml_ButtonText variable in your local/farmconfig.php
or local/config.php
file.
5. Modify you wiki's Site.PageActions
(and other similar locations) by replacing
(:if enabled AuthPw:) * %item rel=nofollow class=logout accesskey="$[ak_logout]"%'' [-[[{*$FullName}?action=logout | $[Logout] ]]-]'' (:ifend:)
with
(:if authid:) * %item rel=nofollow class=logout accesskey="$[ak_logout]"%'' [-[[{*$FullName}?action=logout | $[Logout] {$AuthId} ]]-]'' (:else:) * %item rel=nofollow class=login accesskey="$[ak_login]"%'' [-[[{*$FullName}?action=login | $[Login] ]]-]'' (:ifend:)
6. Set your AuthUser permissions as you wish.
A good basic example is provided in the config.php file in the pmwiki.basic docker example which sets authorisation rules such that:
- everone : read permission
- authenticated users: read+write permission
- people in admin group : all permissions
install SimpleSAMLphp
1. Install SimpleSAMLphp in the cookbook/AuthUserSaml/ directory
# some settings (suit to your needs) export SIMPLESAMLPHP_VERSION='1.19.5' export WEBSERVER_ROOT_DIR='/var/www/html' export PMWIKI_DIR="${WEBSERVER_ROOT_DIR}" # install simplesamlphp export SIMPLESAMLPHP_DIR="${PMWIKI_DIR}/cookbook/AuthUserSaml/simplesamlphp" mkdir -p ${SIMPLESAMLPHP_DIR} curl -LO "https://github.com/simplesamlphp/simplesamlphp/releases/download/v${SIMPLESAMLPHP_VERSION}/simplesamlphp-${SIMPLESAMLPHP_VERSION}.tar.gz" tar -xz --strip-components 1 -C ${SIMPLESAMLPHP_DIR} -f simplesamlphp-${SIMPLESAMLPHP_VERSION}.tar.gz chmod -R +rX ${SIMPLESAMLPHP_DIR} # fix permissions so your web server can read the files (suit to your needs)
2. make a softlink named simplesaml
from the root of your webserver to the www
directory in the ${SIMPLESAMLPHP_DIR}
directory
ln -s ${SIMPLESAMLPHP_DIR}/www ${WEBSERVER_ROOT_DIR}/simplesaml
configure SimpleSAMLphp
1. change contact email, adminpassword and secretsalt in ${SIMPLESAMLPHP_DIR}/config/config.php
2. place the certificate from your identity provider in the file ${SIMPLESAMLPHP_DIR}/cert/idp.crt
3. set variables for configuring identity provider (suit to your needs):
export IDP_HOST='your specific IDP host' export SIMPLESAMLPHP_IDP_ENTITY_ID="https://${IDP_HOST}/simplesaml/saml2/idp/metadata.php" export SIMPLESAMLPHP_IDP_SINGLE_SIGNON_SERVICE="https://${IDP_HOST}/simplesaml/saml2/idp/SSOService.php" export SIMPLESAMLPHP_IDP_SINGLE_LOGOUT_SERVICE="https://${IDP_HOST}/simplesaml/saml2/idp/SingleLogoutService.php"
Set in the variable IDP_HOST the DNS hostname value of your specific IDP host. The variable SIMPLESAMLPHP_IDP_ENTITY_ID
is used for writing config/authsources.php
and metadata/saml20-idp-remote.php
, and the variables SIMPLESAMLPHP_IDP_SINGLE_SIGNON_SERVICE
and SIMPLESAMLPHP_IDP_SINGLE_LOGOUT_SERVICE
are used for writing metadata/saml20-idp-remote.php
.
4. configure the remote idp within SP (Adding IdP to the SP). We do this by creating the file ${SIMPLESAMLPHP_DIR}/metadata/saml20-idp-remote.php
with the following content:
cat > ${SIMPLESAMLPHP_DIR}/metadata/saml20-idp-remote.php <<EOF <?php \$metadata['${SIMPLESAMLPHP_IDP_ENTITY_ID}'] = [ 'SingleSignOnService' =>'${SIMPLESAMLPHP_IDP_SINGLE_SIGNON_SERVICE}', 'SingleLogoutService' => '${SIMPLESAMLPHP_IDP_SINGLE_LOGOUT_SERVICE}', 'certificate' => 'idp.crt', ]; EOF
We are using bash heredoc syntax to write content to file where the SIMPLESAMLPHP variables are expanded during the write. Note that the '$' sign for the php metadata variable is escaped to prevent expanding!
SimpleSAMLphp only signs authentication responses by default.
The IDP always signs the authentication responses sent to the SP. The SP always does validate the authentication responses of the IDP. If it would not do so anyone could send an authentication response causing that person to login without being authenticated. That's why we always have to set an idp.crt
in ${SIMPLESAMLPHP_DIR}/metadata/saml20-idp-remote.php
on the SP, because the SP needs the certificate from the IDP to validate the IPD's signature on the authentication responses.
5. configuring auth source in SP. We do this by creating the file ${SIMPLESAMLPHP_DIR}/config/authsources.php
with the following content:
cat > ${SIMPLESAMLPHP_DIR}/config/authsources.php <<EOF <?php \$config = [ // This is a authentication source which handles admin authentication. 'admin' => [ // The default is to use core:AdminPassword, but it can be replaced with // any authentication source. 'core:AdminPassword', ], /* This is the name of this authentication source, and will be used to access it later. */ 'default-sp' => [ 'saml:SP', # 'privatekey' => 'sp.pem', // Enabling a certificate for your Service Provider (optional,see 6) # 'certificate' => 'sp.crt', // => allows you to receive encrypted assertions from IdP (not enforced). # 'assertion.encryption' => TRUE, // '''Enforce''' encryption on assertions received (optional, see 7) # 'redirect.sign' => TRUE, // Sign the authentication request, logout requests and logout responses sent to the IdP. (optional, see 8) # 'redirect.validate' => TRUE, // Validate the signatures on logout requests and logout responses received from IdP (optional, see 9) /* * The entity ID of the IdP this should SP should contact. * Can be NULL/unset, in which case the user will be shown a list of available IdPs. */ 'idp' => '${SIMPLESAMLPHP_IDP_ENTITY_ID}', ], ]; EOF
We are using bash heredoc syntax to write content to file where the SIMPLESAMLPHP variables are expanded during the write. Note that the '$' sign for the php config variable is escaped to prevent expanding!
We are done, this setup should work. However there are some security options you also add to make it more secure in the step 6, 7, 8, and 9 below.
OPTIONAL security options which can be configured in SimpleSAMLphp
6. OPTIONAL: Enabling a certificate for your Service Provider
Some Identity Providers/Federations may require that your Service Providers holds a certificate. If you enable a certificate for your Service Provider, it may be able to sign requests and responses sent to the Identity Provider(step 8), as well as receiving encrypted responses from the IdP. (enforced in step 7).
Create a self-signed certificate in the cert/ directory:
cd ${SIMPLESAMLPHP_DIR}/cert openssl req -newkey rsa:3072 -new -x509 -days 3652 -nodes -out sp.crt -keyout sp.pem
Then edit your ${SIMPLESAMLPHP_DIR}/authsources.php
entry, and uncomment the references to the SP's certificate and private key:
... 'default-sp' => [ 'saml:SP', 'privatekey' => 'sp.pem', // Enabling a certificate for your Service Provider 'certificate' => 'sp.crt', // allows you to receive encrypted assertions from IdP (not enforced). ...
7. OPTIONAL: Enforce encryption on assertions received
Edit your ${SIMPLESAMLPHP_DIR}/authsources.php
entry, and add the assertion.encryption
option:
... 'default-sp' => [ 'saml:SP', 'privatekey' => 'sp.pem', // REQUIRED for receiving encrypted messages from IdP 'certificate' => 'sp.crt', // The IdP must have 'sp.crt' to encrypt. ... 'assertion.encryption' => TRUE, ...
From From the SimpleSAMLphp documentation we read
assertion.encryption Whether assertions received by this SP must be encrypted. The default value is FALSE . If this option is set to TRUE , unencrypted assertions will be rejected.
Thus if assertion.encryption
is set to TRUE incoming assertions MUST be encrypted and unencrypted assertions will be rejected.
This requires that the assertion.encryption
option is enabled on the IdP which causes assertions send from the IdP to this SP to be encrypted.
If 'assertion.encryption' is set to FALSE it will handle unencrypted assertions, but it will also handle encrypted assertions ONLY IF certificate of the IDP (idp.crt) is configured in ${SIMPLESAMLPHP_DIR}/config/authsources.php which is by default REQUIRED!!! (see explanation in step 4 why)
You must supply the sp.crt
to the IdP, otherwise it cannot send encrypted messages to the SP which the SP can decrypt which its own
private key sp.pem
.
8. OPTIONAL: Sign the authentication request, logout requests and logout responses sent to the IdP.
Edit your ${SIMPLESAMLPHP_DIR}/authsources.php
entry, and add the redirect.sign
option:
... 'default-sp' => [ 'saml:SP', 'privatekey' => 'sp.pem', // use to sign by SP 'certificate' => 'sp.crt', // used to validate signature by IdP ... 'redirect.sign' => TRUE, ...
From From the SimpleSAMLphp documentation we read
redirect.sign Whether authentication requests, logout requests and logout responses sent from this SP should be signed. The default is FALSE .
By enabling the 'redirect.sign' option on the SP, the SP does sign authentication requests, logout requests and logout responses sent from this SP to the IdP. Signatures are only validated by the IdP if on the IdP site the 'redirect.sign' option is enabled otherwise the signatures will just be ignored by the IdP.
You must supply the sp.crt
to the IdP, otherwise it cannot validate the signature from the SP.
9. OPTIONAL: Validate the signatures on logout requests and logout responses received from IdP
Edit your ${SIMPLESAMLPHP_DIR}/authsources.php
entry, and add the redirect.sign
and redirect.validate
options:
... 'default-sp' => [ 'saml:SP', #'privatekey' => 'sp.pem', // sp keys are not needed for validating signatures from IdP, #'certificate' => 'sp.crt', // we only need the 'idp.crt' certificate for validating ... 'redirect.validate' => TRUE, ...
From From the SimpleSAMLphp documentation we read
redirect.validate Whether logout requests and logout responses received by this SP should be validated. The default is FALSE .
By enabling the 'redirect.sign' option on the SP, the SP does validate signatures on logout requests and logout responses received by this SP from the IdP. This requires that the signature is added on IdP site by enabling the 'redirect.sign' option on the IdP, because otherwise you get error on SP: Validation of received messages enabled, but no signature found on message.
Release notes
- 2022-08-19 first release authusersaml_20220819.zip
User notes? : If you use, used or reviewed this recipe, you can add your name. These statistics appear in the Cookbook listings and will help newcomers browsing through the wiki.