Good morning,
I am attempting to setup a SAML server and I am kinda stuck. This is my first time playing with SAML, let alone building and configuring a IdP server so I apologize if the problem I am facing is a simple one.
My goal is to authenticate a web application against LDAP. I didn't write the web application, I was just told that it only supports SAML for authentication. I would like to map the following LDAP fields to custom names in the response (LDAP => Response):
sAMAccountName => NameID
givenName => first_name
sn => last_name
mail => email
telephoneNumber => phone
I have successfully authenticated the SP to this IdP that I am trying to configure when the IdP is using the exampleauth:UserPass (see configuration below), however when I get to trying to authenticate it against LDAP, I am hitting an unhandled exception. The logs show "Caused by: DOMException: Error parsing XML string."
I know the problem is with my configuration... I just have no clue what the problem could be. See below for configuration and logs.
Any suggestions?
Thank you very much.
SimpleSAML_Error_Error: UNHANDLEDEXCEPTION
Backtrace: 0 /var/simplesamlphp/www/module.php:170 (N/A) Caused by: DOMException: Error parsing XML string. Backtrace: 15 /var/simplesamlphp/lib/SimpleSAML/Utils/XML.php:234 (SimpleSAML\Utils\XML::formatXMLString) 14 /var/simplesamlphp/lib/SimpleSAML/Utils/XML.php:115 (SimpleSAML\Utils\XML::debugSAMLMessage) 13 /var/simplesamlphp/lib/SimpleSAML/Utilities.php:683 (SimpleSAML_Utilities::debugMessage) 12 /var/simplesamlphp/vendor/simplesamlphp/saml2/src/SAML2/Compat/Ssp/Container.php:39 (SAML2_Compat_Ssp_Container::debugMessage) 11 /var/simplesamlphp/vendor/simplesamlphp/saml2/src/SAML2/HTTPPost.php:29 (SAML2_HTTPPost::send) 10 /var/simplesamlphp/modules/saml/lib/IdP/SAML2.php:78 (sspmod_saml_IdP_SAML2::sendResponse) 9 [builtin] (call_user_func) 8 /var/simplesamlphp/lib/SimpleSAML/IdP.php:287 (SimpleSAML_IdP::postAuthProc) 7 /var/simplesamlphp/lib/SimpleSAML/IdP.php:333 (SimpleSAML_IdP::postAuth) 6 [builtin] (call_user_func) 5 /var/simplesamlphp/lib/SimpleSAML/Auth/Source.php:229 (SimpleSAML_Auth_Source::loginCompleted) 4 [builtin] (call_user_func) 3 /var/simplesamlphp/lib/SimpleSAML/Auth/Source.php:145 (SimpleSAML_Auth_Source::completeAuth) 2 /var/simplesamlphp/modules/core/lib/Auth/UserPassBase.php:266 (sspmod_core_Auth_UserPassBase::handleLogin) 1 /var/simplesamlphp/modules/core/www/loginuserpass.php:67 (require) 0 /var/simplesamlphp/www/module.php:127 (N/A)
/var/log/messages
May 9 06:06:53 SAMLServ1 simplesamlphp[56732]: 6 [309acdc86a] SAML2.0 - IdP.SSOService: Accessing SAML 2.0 IdP endpoint SSOService
May 9 06:06:53 SAMLServ1 simplesamlphp[56732]: 6 [309acdc86a] SAML2.0 - IdP.SSOService: incoming authentication request: 'INST0'
May 9 06:06:53 SAMLServ1 simplesamlphp[56187]: 6 [309acdc86a] Template: Looking up [{login:processing]: not translated at all.
May 9 06:07:02 SAMLServ1 simplesamlphp[56682]: 5 STAT [309acdc86a] User 'admin1' has been successfully authenticated.
May 9 06:07:02 SAMLServ1 simplesamlphp[56682]: 5 STAT [309acdc86a] saml20-idp-SSO-first INST0 http://192.168.152.10/sso/saml2/idp/metadata.php NA
May 9 06:07:02 SAMLServ1 simplesamlphp[56682]: 5 STAT [309acdc86a] saml20-idp-SSO INST0 http://192.168.152.10/sso/saml2/idp/metadata.php NA
May 9 06:07:02 SAMLServ1 simplesamlphp[56682]: 6 [309acdc86a] Sending SAML 2.0 Response to 'INST0'
May 9 06:07:02 SAMLServ1 simplesamlphp[56682]: 3 [309acdc86a] SimpleSAML_Error_Error: UNHANDLEDEXCEPTION
May 9 06:07:02 SAMLServ1 simplesamlphp[56682]: 3 [309acdc86a] Backtrace:
May 9 06:07:02 SAMLServ1 simplesamlphp[56682]: 3 [309acdc86a] 0 /var/simplesamlphp/www/module.php:170 (N/A)
May 9 06:07:02 SAMLServ1 simplesamlphp[56682]: 3 [309acdc86a] Caused by: DOMException: Error parsing XML string.
May 9 06:07:02 SAMLServ1 simplesamlphp[56682]: 3 [309acdc86a] Backtrace:
May 9 06:07:02 SAMLServ1 simplesamlphp[56682]: 3 [309acdc86a] 15 /var/simplesamlphp/lib/SimpleSAML/Utils/XML.php:234 (SimpleSAML\Utils\XML::formatXMLString)
May 9 06:07:02 SAMLServ1 simplesamlphp[56682]: 3 [309acdc86a] 14 /var/simplesamlphp/lib/SimpleSAML/Utils/XML.php:115 (SimpleSAML\Utils\XML::debugSAMLMessage)
May 9 06:07:02 SAMLServ1 simplesamlphp[56682]: 3 [309acdc86a] 13 /var/simplesamlphp/lib/SimpleSAML/Utilities.php:683 (SimpleSAML_Utilities::debugMessage)
May 9 06:07:02 SAMLServ1 simplesamlphp[56682]: 3 [309acdc86a] 12 /var/simplesamlphp/vendor/simplesamlphp/saml2/src/SAML2/Compat/Ssp/Container.php:39 (SAML2_Compat_Ssp_Container::debugMessage)
May 9 06:07:02 SAMLServ1 simplesamlphp[56682]: 3 [309acdc86a] 11 /var/simplesamlphp/vendor/simplesamlphp/saml2/src/SAML2/HTTPPost.php:29 (SAML2_HTTPPost::send)
May 9 06:07:02 SAMLServ1 simplesamlphp[56682]: 3 [309acdc86a] 10 /var/simplesamlphp/modules/saml/lib/IdP/SAML2.php:78 (sspmod_saml_IdP_SAML2::sendResponse)
May 9 06:07:02 SAMLServ1 simplesamlphp[56682]: 3 [309acdc86a] 9 [builtin] (call_user_func)
May 9 06:07:02 SAMLServ1 simplesamlphp[56682]: 3 [309acdc86a] 8 /var/simplesamlphp/lib/SimpleSAML/IdP.php:287 (SimpleSAML_IdP::postAuthProc)
May 9 06:07:02 SAMLServ1 simplesamlphp[56682]: 3 [309acdc86a] 7 /var/simplesamlphp/lib/SimpleSAML/IdP.php:333 (SimpleSAML_IdP::postAuth)
May 9 06:07:02 SAMLServ1 simplesamlphp[56682]: 3 [309acdc86a] 6 [builtin] (call_user_func)
May 9 06:07:02 SAMLServ1 simplesamlphp[56682]: 3 [309acdc86a] 5 /var/simplesamlphp/lib/SimpleSAML/Auth/Source.php:229 (SimpleSAML_Auth_Source::loginCompleted)
May 9 06:07:02 SAMLServ1 simplesamlphp[56682]: 3 [309acdc86a] 4 [builtin] (call_user_func)
May 9 06:07:02 SAMLServ1 simplesamlphp[56682]: 3 [309acdc86a] 3 /var/simplesamlphp/lib/SimpleSAML/Auth/Source.php:145 (SimpleSAML_Auth_Source::completeAuth)
May 9 06:07:02 SAMLServ1 simplesamlphp[56682]: 3 [309acdc86a] 2 /var/simplesamlphp/modules/core/lib/Auth/UserPassBase.php:266 (sspmod_core_Auth_UserPassBase::handleLogin)
May 9 06:07:02 SAMLServ1 simplesamlphp[56682]: 3 [309acdc86a] 1 /var/simplesamlphp/modules/core/www/loginuserpass.php:67 (require)
May 9 06:07:02 SAMLServ1 simplesamlphp[56682]: 3 [309acdc86a] 0 /var/simplesamlphp/www/module.php:127 (N/A)
May 9 06:07:02 SAMLServ1 simplesamlphp[56682]: 3 [309acdc86a] Error report with id b0781dee generated.
metadata/saml20-idp-hosted.php
$metadata['__DYNAMIC:1__'] = array(
'host' => '__DEFAULT__',
'privatekey' => 'simplesamlphp.pem',
'certificate' => 'simplesamlphp.crt',
'auth' => 'domain-ldap',
// 'auth' => 'example-userpass',
);
metadata/saml20-sp-remote.php
$metadata['INST0'] = array(
'AssertionConsumerService' => 'http://portal.domain.com/login.php',
'SingleLogoutService' => 'http://portal.domain.com/logout.php',
'NameIDFormat' => 'urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified',
'authproc' => array(
3 => array(
'class' => 'saml:AttributeNameID',
'attribute' => 'sAMAccountName',
'Format' => 'urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified',
),
),
);
config/authsources.php
'example-userpass' => array(
'exampleauth:UserPass',
'admin1:P4ss30rd' => array(
'NameID' => array('admin1'),
'first_name' => array('My'),
'last_name' => array('Admin 1'),
'name' => array('My Admin 1'),
'email' => array('some...@example.org'),
'phone' => array('1234567890'),
),
),
'domain-ldap' => array(
'ldap:LDAP',
// Give the user an option to save their username for future login attempts
// And when enabled, what should the default be, to save the username or not
//'remember.username.enabled' => FALSE,
//'remember.username.checked' => FALSE,
// The hostname of the LDAP server.
'hostname' => '192.168.152.11',
// Whether SSL/TLS should be used when contacting the LDAP server.
'enable_tls' => FALSE,
// Whether debug output from the LDAP library should be enabled.
// Default is FALSE.
'debug' => TRUE,
// The timeout for accessing the LDAP server, in seconds.
// The default is 0, which means no timeout.
'timeout' => 30,
// The port used when accessing the LDAP server.
// The default is 389.
'port' => 389,
// Set whether to follow referrals. AD Controllers may require FALSE to function.
'referrals' => FALSE,
// Which attributes should be retrieved from the LDAP server.
// This can be an array of attribute names, or NULL, in which case
// all attributes are fetched.
'attributes' => NULL,
// The pattern which should be used to create the users DN given the username.
// %username% in this pattern will be replaced with the users username.
//
// This option is not used if the search.enable option is set to TRUE.
'dnpattern' => 'uid=%username%,DC=my,DC=domain,DC=com',
// As an alternative to specifying a pattern for the users DN, it is possible to
// search for the username in a set of attributes. This is enabled by this option.
'search.enable' => TRUE,
// The DN which will be used as a base for the search.
// This can be a single string, in which case only that DN is searched, or an
// array of strings, in which case they will be searched in the order given.
'search.base' => 'DC=my,DC=domain,DC=com',
// The attribute(s) the username should match against.
//
// This is an array with one or more attribute names. Any of the attributes in
// the array may match the value the username.
'search.attributes' => array('uid', 'mail', 'sAMAccountName'),
// The username & password the SimpleSAMLphp should bind to before searching. If
// this is left as NULL, no bind will be performed before searching.
'search.username' => 'admin1',
'search.password' => '<password>',
// If the directory uses privilege separation,
// the authenticated user may not be able to retrieve
// all required attribures, a privileged entity is required
// to get them. This is enabled with this option.
'priv.read' => FALSE,
// The DN & password the SimpleSAMLphp should bind to before
// retrieving attributes. These options are required if
// 'priv.read' is set to TRUE.
'priv.username' => NULL,
'priv.password' => NULL,
'authproc' => array(
2 => array(
'class' => 'saml:PersistentNameID',
'attribute' => 'sAMAccountName',
),
10 => array(
'class' => 'core:AttributeMap',
'givenName' => 'first_name',
'sn' => 'last_name',
'cn' => 'name',
'mail' => 'mail',
'telephoneNumber' => 'phone',
),
100 => array(
'class' => 'core:PHP',
'code' => '
if(!empty($attributes["sAMAccountName"])) {
$employeeID = $attributes["sAMAccountName"][0];
$attributes["employeeID"] = array($employeeID);
}
if(!empty($attributes["givenName"])){
$firstName = $attributes["givenName"][0];
$attributes["first_name"] = array($firstName);
}
',
),
),
Since it is working I have been afraid to remove the PHP code so I plan to just leave it. I don't think it is doing anything useful though.
saml20-sp-remote.php
'simplesaml.attributes' => true,
'attributes' => array('first_name', 'last_name', 'name', 'email', 'phone'),
'NameIDFormat' => 'urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified',
'authproc' => array(
3 => array(
'class' => 'saml:AttributeNameID',
'attribute' => 'sAMAccountName',
'Format' => 'urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified',
),
),