Groups
Groups

Drupal SimpleSamlPHP - testing authentication source does not redirect properly

2,757 views
Skip to first unread message

Ryan Weiss

unread,
Nov 9, 2015, 5:27:41 PM11/9/15
to SimpleSAMLphp
Hiyas, new to SSO, hoping someone can help here.
We've got a drupal site as our IdP, and a remote Canvas site functioning as the SP. 
When I'm in the Drupal site, trying to test the authentication sources, 


This seems to work, but there seems to be an issue with the URL formatting coming from the test, namely it brings me to the following URL, which shows "Access Denied" because it looks to be messing up the ReturnTo parameter (gives it twice, once urlencoded and one not, as you can see):

If I manually fix the url and go there:

Then that seems to work.
Does anyone have ideas how to fix this ReturnTo formatting issue?

---

Peter Schober

unread,
Nov 10, 2015, 5:09:10 AM11/10/15
to SimpleSAMLphp
* Ryan Weiss <rw3...@gmail.com> [2015-11-09 23:27]:
> When I'm in the Drupal site, trying to test the authentication sources,
>
> http://weiss.dev2.rowanonline.com/simplesaml/module.php/core/authenticate.php?as=rowan-canvas-sp-entityid
>
> This seems to work, but there seems to be an issue with the URL formatting
> coming from the test, namely it brings me to the following URL, which shows
> "Access Denied" because it looks to be messing up the ReturnTo parameter
> (gives it twice, once urlencoded and one not, as you can see):

I'd trace HTTP requests/reponses starting at the above URL to see
where things seem correct and where things go wrong.

The other 2 URLs you post mean nothing to me as those go into Drupal,
so I wouldn't know what to look for.
-peter

Ryan Weiss

unread,
Nov 11, 2015, 8:17:30 PM11/11/15
to SimpleSAMLphp, peter....@univie.ac.at
Hi Peter,

 Thanks a lot for your response!
 So I ran some more tests and sniffing... and here is what I can say:

 In the Canvas dashboard I can debug the SAML login requests from the SP's point of view. Here is the debug information below:
Request ID:
ac13eccd39221f9c656a915a8d273d4ff1a644c862
LoginRequest encoded URL:
    http://weiss.dev2.rowanonline.com/simplesaml/saml2/idp/SSOService.php?SAMLRequest=nZJRT8IwFIXf%2FRVL39logQnNtmRCjCSoC0wffDG166RJ12JvJ%2Frv7YYaEtQHk7709tx7vpzbBFijdjRv3VavxUsrwAVvjdJA%2B4cUtVZTw0AC1awRQB2nm%2Fx6RUk4pDtrnOFGoWC5SBHjeCQ4r0YzQnA94%2FEkZjM8YdOKnI%2BqcV1jFo%2FHfBoTFNwLC9LoFPkxvhugFUsNjmnnS0M8GWDsT0kIJVNK8AMKik%2BvC6krqZ%2F%2FBns6iIBelWUxKG43JQpyAGGdN50bDW0j7EbYV8nF3XqVoq1zO6BRZM2e6dD5FELpeWzLXWtFyE0TdXk88kMvypLuSntwexTY31jsCwFlneG3309WJImOLLKz5LCoGz90uSiMkvz9P4u6NLZh7nc1DnFfkdWg7qVUNEyqvKqsAPApKmX2cyuYEyny0F0U0Sma541Of1b2AQ%3D%3D
  
LoginRequest XML sent to IdP:
    <samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="ac13eccd39221f9c656a915a8d273d4ff1a644c862" Version="2.0" IssueInstant="2015-11-11T22:28:21Z" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" AssertionConsumerServiceURL="https://rowan.test.instructure.com/saml_consume"><saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">http://rowan.instructure.com/saml2</saml:Issuer>
<samlp:NameIDPolicy xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress" AllowCreate="true"></samlp:NameIDPolicy>
</samlp:AuthnRequest>
  
In the sniffing of the request, I find:

Did POST to:

Then a GET:

And then I landed on the Drupal user page when all was said and done...

So this all seemed to work, however there are a few issues... namely:
1. After the SAML login, it stays on the Drupal page, instead of going back to the Canvas site. I have the "RelayState" property set to go to the Canvas site, so I'm not sure why the 'ReturnTo' parameter is being set to the Drupal site.. seems like this is coming from Canvas's (SP's) end...
2. If you look at the "LoginRequest XML sent to IdP" above in the Canvas debug, neither of those URLs exist within the XML, namely:
   -AssertionConsumerServiceURL="https://rowan.test.instructure.com/saml_consume"
   -<saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">http://rowan.instructure.com/saml2</saml:Issuer>

Do you have any idea where those URLs are set, or how to tell Canvas or the SP to use a different ReturnTo value in its request?

Thanks for any help!

Ryan

Ryan Weiss

unread,
Nov 13, 2015, 2:54:32 AM11/13/15
to SimpleSAMLphp
So I've narrowed the issue down a bit...

In the authentication source (config/authsources.php), if I set the entry for my 'drupalauth' key (matched in /metadata/saml20-idp-hosted.php as the 'auth' parameter) to 'saml:SP', I get a redirect loop (my "SingleSignOnService" url is set to "http://weiss.dev2.rowanonline.com/simplesamlphp/www/saml2/idp/SSOService.php?spentityid=default-sp&RelayState=https://rowan.test.instructure.com", as you can see I've manually added those parameters, but they're also matched in the SP metadata/saml20-sp-remote.php config). If I change the 'samp:SP' auth type to 'drupalauth:External', then it hits the drupal site, but it messes the URL in adding the ReturnTo parameter in a jumbled way, as mentioned above:

  ?q=user%2Flogin%3FReturnTo&ReturnTo=http%3A%2F%2Fweiss.dev2.rowanonline.com%2Fsimplesaml%2Fmodule.php%2Fdrupalauth%2Fresume.php%3FState%3D_b63e8f3d......

 ...but that URL brings me to a Durpal "Access Denied" page... if i then remove the first bit, %3FReturnTo, and hit the url, it brings me to the authentication page okay, and when I login, it then brings me back to Access Denied page, because it adds the bad %3FReturnTo bit back onto the URL. When I remove it, I get put on my user page: http://weiss.dev2.rowanonline.com/?q=user.

So that's where I'm at... 

I am assuming we need to use 'drupalauth:External' for our purposes, but 'saml:SP' is the default, and I'm not entirely sure how saml:SP is working, have to read up on it, as is...just wondering why it's giving a redirect loop. I'm including my config's below:

/config/authsources.php:
/arbitrary name, used in the IdP metadata.
'drupalauth' => array(
    /
/'saml:SP',
   
'drupalauth:External',
   
'drupalroot' => '/var/www/weiss.dev2.rowanonline.com/webroot',
   
// The entity ID of this SP.
   
// Can be NULL/unset, in which case an entity ID is generated based on the metadata URL.
   
//'entityID' => 'http://rowan.instructure.com/saml2',
   
'entityID' => 'default-sp',

   
// 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' => null,
   
'idp' => 'drupal-idp-entityid',
   
'saml:sp:Idp' => 'drupal-idp-entityid',
   
'saml:idp' => 'drupal-idp-entityid',
   
// The URL to the discovery service.
   
// Can be NULL/unset, in which case a builtin discovery service will be used.
   
'discoURL' => null,
   
//'privatekey' => 'saml_sp.pem',
   
'certificate' => 'saml_sp.pem',
   
//'certificate' => 'saml_sp.crt',
   
'RelayState' => 'https://rowan.test.instructure.com',
   
'acs.Bindings' => array(
           
'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST',
           
'urn:oasis:names:tc:SAML:1.0:profiles:browser-post'
   
),
     
// Which attributes should be retrieved from the Drupal site.
   
'attributes' => array(
        array
('drupaluservar' => 'uid',  'callit' => 'uid'),
        array
('drupaluservar' => 'name', 'callit' => 'cn'),
        array
('drupaluservar' => 'mail', 'callit' => 'mail'),
        array
('drupaluservar' => 'field_first_name',  'callit' => 'givenName'),
        array
('drupaluservar' => 'field_last_name',   'callit' => 'sn'),
        array
('drupaluservar' => 'field_organization','callit' => 'ou'),
        array
('drupaluservar' => 'roles','callit' => 'roles'),
   
),
   
/* these drupal URLs may not be used? */
   
// the URL of the Drupal logout page
   
'drupal_logout_url' => 'http://weiss.dev2.rowanonline.com/?q=user/logout',
   
// the URL of the Drupal login page
   
'drupal_login_url' => 'http://weiss.dev2.rowanonline.com/?q=user/login',
   
'NameIDFormat' => 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress'
 
),

/metadatasaml20-idp-hosted.php:
$metadata['drupal-idp-entityid'] = array(
 
'auth' => 'drupalauth',
 
'entityid' => 'drupal-idp-entityid',

 
'host' => 'weiss.dev2.rowanonline.com',

 
'RelayState' => 'https://rowan.test.instructure.com',
 
 
'privatekey' => 'saml_sp.pem',
 
'certificate' => 'saml_sp.crt',
 
'certFingerprint' => 'B4:7A:62:5F:36:C0:2D:8A:D4:B6:11:49:68:FC:FF:32:2E:D5:2E:50');



/metadata/saml20-sp-remote.php
$metadata['http://rowan.instructure.com/saml2'] = array(
 
'idp' => 'drupal-idp-entityid',

 
//'AssertionConsumerService' => 'https://rowan.test.instructure.com/saml_consume',
 
'AssertionConsumerService' => 'http://weiss.dev2.rowanonline.com/simplesaml/module.php/saml/sp/saml2-acs.php/default-sp',
 
'SingleSignOnService' => 'http://weiss.dev2.rowanonline.com/simplesamlphp/www/saml2/idp/SSOService.php?spentityid=default-sp&RelayState=https://rowan.test.instructure.com',
 
//'SingleSignOnService'  => 'http://weiss.dev2.rowanonline.com/simplesamlphp/www/saml2/idp/SSOService.php?spentityid=default-sp',
 
'SingleLogoutService' => 'http://weiss.dev2.rowanonline.com/simplesaml/module.php/saml/sp/saml2-logout.php/default-sp',
 
//'SingleLogoutService'  => 'http://weiss.dev2.rowanonline.com/simplesamlphp/www/saml2/idp/SingleLogoutService.php',
 
'RelayState' => 'https://rowan.test.instructure.com/',

 
'privatekey' => 'saml_sp.pem',
 
'certificate' => 'saml_sp.crt',    
 
'certFingerprint' => 'B4:7A:62:5F:36:C0:2D:8A:D4:B6:11:49:68:FC:FF:32:2E:D5:2E:50',
 
//'certData' => 'MIIEHTCCAwWgAwIBAgIJAKfeHFV5rppBMA0GCSqGSIb3DQEBBQUAMIGkMQswCQYDVQQGEwJVUzETMBEGA1UECAwKTmV3IEplcnNleTESMBAGA1UEBwwJR2xhc3Nib3JvMRkwFwYDVQQKDBBSb3dhbiBVbml2ZXJzaXR5MRowGAYDVQQLDBFJbnRlcm5ldCBTZXJ2aWNlczEUMBIGA1UEAwwLcm93YW5vbmxpbmUxHzAdBgkqhkiG9w0BCQEWEHJ3M2lzc0BnbWFpbC5jb20wHhcNMTUxMDE4MTczNzU1WhcNMjUxMDE3MTczNzU1WjCBpDELMAkGA1UEBhMCVVMxEzARBgNVBAgMCk5ldyBKZXJzZXkxEjAQBgNVBAcMCUdsYXNzYm9ybzEZMBcGA1UECgwQUm93YW4gVW5pdmVyc2l0eTEaMBgGA1UECwwRSW50ZXJuZXQgU2VydmljZXMxFDASBgNVBAMMC3Jvd2Fub25saW5lMR8wHQYJKoZIhvcNAQkBFhBydzNpc3NAZ21haWwuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8ILJE8k1fBI+yQTFLoosFNKQUwbpF0lnb6VtbCFCfUgPGh52tdSHSAwllMaQxkoY/sidwfivkUGy0VXTclYgt4JvI5CANyj6UhUNy+YH0PUei8NsPT6qm+3q5SSHW2enSwoP2r7Fswyh8/piza69MnaCskkyksnkqH545q5SIpwrA6GbXpCzCkh04PznEMt8sXSc5x00/BamW2YSBhd+lGukYDx447jMkryWe5RmdLgEugBT1PmHL5LhttV972yMWMgoXxbhnnehnSfT6WBRc8ZMX233xyddnd3n0kzmLvTr88btK1DBNHyb4E6mvysxugNDPi0cP25qRF//z7y+UQIDAQABo1AwTjAdBgNVHQ4EFgQUk1ylAKthb18XAg4EeWN/heib3G0wHwYDVR0jBBgwFoAUk1ylAKthb18XAg4EeWN/heib3G0wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAXsjt+koDn/Sv6r8ywDlX9/p5bNHooHipjBT5x/EbtqYEKJNhnHpJIH/pjxwBQ0Vgye010OyskFth8QzTc/XBOacG5yY6gc4LUGG3VZqvX81ngJa3J/9XWTYlV8j/saPqrXEtDGF9NBSIagV/XXQHLgK+pLyY0SJBO4tMSYwaCztNr8R+bS+Y3Of9oFfUNjhd6ZyKEk+2t1wph5nLS5zzDzFG+gBsDuZtlztGRAoXrWerYPofrZQ2bw0WTVzY4X+/40TAW9/4bv9uK0M4n7mkNK/ve/dTT3zt+J/dN2UfQXHqcNHFbt4qCwRP0s0VS+uclEq0M/dw8T6+fEBakjjFMQ==',
 
'NameIDFormat' => 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress',
 
'attributes.NameFormat' => 'urn:oasis:names:tc:SAML:2.0:attrname-format:basic', //default
 
'simplesaml.nameidattribute' => 'uid', //must match 'callit' variable in authsources.php
 
'simplesaml.attributes' => FALSE
);

//copy the same config for the default
$metadata
['default-sp'] = $metadata['http://rowan.instructure.com/saml2'];



This is the Request XML sent to IdP:
    <samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="baadde73e365abd4db73082516767844f9ea139237" Version="2.0" IssueInstant="2015-11-13T02:51:09Z" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" AssertionConsumerServiceURL="https://rowan.test.instructure.com/saml_consume"><saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">http://rowan.instructure.com/saml2</saml:Issuer>
<samlp:NameIDPolicy xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress" AllowCreate="true"></samlp:NameIDPolicy>
</samlp:AuthnRequest>
  


Aaaany ideas how to prevent the mangled ReturnTo parameter, or get the redirect loop to work properly? 

Ryan Weiss

unread,
Nov 13, 2015, 3:16:31 AM11/13/15
to SimpleSAMLphp
If I try to hit the SP's defined 'AssertionConsumerService' manually, as defined above in /metadata/saml20-sp-remote.php: http://weiss.dev2.rowanonline.com/simplesaml/module.php/saml/sp/saml2-acs.php/drupalauth, and tack on the SAMLRequest parameter from the URL that I land on when I hit the original SAML(Canvas) login page ('https://rowan.test.instructure.com/login/saml', which brings me to a redirect loop, as mentioned above, over at the Drupal/IdP site: 
(Redirect Loop)...
 but then I tried to pull off that SAMLRequest parameter and put on the AssertionConsumerService URL, so:


it gives a new error:
SimpleSAML_Error_BadRequest: BADREQUEST('%REASON%' => 'Invalid message received to AssertionConsumerService endpoint.')
Backtrace:
1 /var/www/weiss.dev2.rowanonline.com/webroot/simplesamlphp/modules/saml/www/sp/saml2-acs.php:18 (require)
0 /var/www/weiss.dev2.rowanonline.com/webroot/simplesamlphp/www/module.php:134 (N/A)

Any ideas on that one?


On Monday, November 9, 2015 at 5:27:41 PM UTC-5, Ryan Weiss wrote:

Jaime Perez Crespo

unread,
Nov 13, 2015, 4:33:13 AM11/13/15
to simple...@googlegroups.com
Hi Ryan,
> (Redirect Loop)…

Have you looked into SimpleSAMLphp log files? You are likely having a misconfiguration in your web server.
That’s to be expected. The AssertionConsumerService, as its name indicates, is intended to *consume* assertions, that is, messages coming from a SAML IdP. You are sending a SAML request instead, which obviously doesn’t contain any assertion at all. No response, no assertion to consume, invalid message received :-)

--
Jaime Pérez
UNINETT / Feide
mail: jaime...@uninett.no
xmpp: ja...@jabber.uninett.no

"Two roads diverged in a wood, and I, I took the one less traveled by, and that has made all the difference."
- Robert Frost

Ryan Weiss

unread,
Nov 13, 2015, 8:30:09 PM11/13/15
to SimpleSAMLphp
Hi Jaime!

 Thanks for your assistance... I have logging enabled on the simplesamlphp module, but for some reason no log files ever show up in /simplesamlphp/log directory (which is defined in simplesamlphp/config/config.php), and the directory permissions are 777 on the log directory. Do you know how I can see the simplesaml logs, or get them generated somehow?

 Regarding the AssertionConsumerService URL, if I just go to the first part (without tacking on the SAMLRequest parameter manually), ie:
  http://weiss.dev2.rowanonline.com/simplesaml/module.php/saml/sp/saml2-acs.php/drupalauth

 It then gives the error:
SimpleSAML_Error_Error: UNHANDLEDEXCEPTION
Backtrace:
0 /var/www/weiss.dev2.rowanonline.com/webroot/simplesamlphp/www/module.php:179 (N/A)
Caused by: Exception: Missing SAMLRequest or SAMLResponse parameter.
Backtrace:
2 /var/www/weiss.dev2.rowanonline.com/webroot/simplesamlphp/vendor/simplesamlphp/saml2/src/SAML2/HTTPRedirect.php:99 (SAML2_HTTPRedirect::receive)
1 /var/www/weiss.dev2.rowanonline.com/webroot/simplesamlphp/modules/saml/www/sp/saml2-acs.php:16 (require)
0 /var/www/weiss.dev2.rowanonline.com/webroot/simplesamlphp/www/module.php:134 (N/A)

So how can I properly define the AssertionConsumerService URL? Something in my config on the IdP side must not be correct, or maybe the IdP's webserver config needs something...?

Ryan

Ryan Weiss

unread,
Nov 13, 2015, 8:36:30 PM11/13/15
to SimpleSAMLphp
If I follow that error, and look at line 16 on saml2-acs.php (in the stack trace), and do some manual debugging:

$b = SAML2_Binding::getCurrentBinding();
if ($b instanceof SAML2_HTTPArtifact) {
 $b
->setSPMetadata($spMetadata);
}

echo
'B: ' . print_r($b);

$response
= $b->receive();
//redirect then happens before going any further

It prints out as B:
SAML2_HTTPRedirect Object
(
    [destination:protected] => 
)
B: 1

Does that mean the redirect is going bad because of some protected resource or something?

Peter Schober

unread,
Nov 14, 2015, 1:49:31 PM11/14/15
to SimpleSAMLphp
* Ryan Weiss <rw3...@gmail.com> [2015-11-14 02:30]:
> Thanks for your assistance... I have logging enabled on the simplesamlphp
> module, but for some reason no log files ever show up in /simplesamlphp/log
> directory (which is defined in simplesamlphp/config/config.php), and the
> directory permissions are 777 on the log directory. Do you know how I can
> see the simplesaml logs, or get them generated somehow?

What's the value of 'loggingdir' in config/config.php?
Can the user PHP is running as create files there? Verify on the
command line or with a simple PHP script you access from the web.
What is 'logging.handler' set to?

> Regarding the AssertionConsumerService URL, if I just go to the first part
> (without tacking on the SAMLRequest parameter manually), ie:
[...]
> It then gives the error:
[...]
> > Caused by: Exception: Missing SAMLRequest or SAMLResponse parameter.

Which is to be expected (accessing that endpoint without the require
parameter will lead to an error telling just that) and I think Jaime
told you that before already. No idea what that should illustrate.

> So how can I properly define the AssertionConsumerService URL?

You don't have to define anything. Once SimpleSAMLphp is accssible on
the web as documented all required endpoints will be defined and
behave correctly.
I don't use SimpleSAMLphp with Drupal or with Drupal extension
modules, so hard to say what's going on here.
-peter

Ryan Weiss

unread,
Nov 14, 2015, 4:14:16 PM11/14/15
to SimpleSAMLphp, peter....@univie.ac.at


On Saturday, November 14, 2015 at 1:49:31 PM UTC-5, Peter Schober wrote:
* Ryan Weiss <rw3...@gmail.com> [2015-11-14 02:30]:
>  Thanks for your assistance... I have logging enabled on the simplesamlphp
> module, but for some reason no log files ever show up in /simplesamlphp/log
> directory (which is defined in simplesamlphp/config/config.php), and the
> directory permissions are 777 on the log directory. Do you know how I can
> see the simplesaml logs, or get them generated somehow?

What's the value of 'loggingdir' in config/config.php?
Can the user PHP is running as create files there? Verify on the
command line or with a simple PHP script you access from the web.
What is 'logging.handler' set to? 

    'loggingdir' => 'log/', 
    'logging.level' => SimpleSAML_Logger::NOTICE,
    'logging.handler' => 'syslog',

  The /log directory has 777 permissions, so I don't see why PHP wouldn't be able to write to it.



>  Regarding the AssertionConsumerService URL, if I just go to the first part
> (without tacking on the SAMLRequest parameter manually), ie:
[...]
>  It then gives the error:
[...]
> > Caused by: Exception: Missing SAMLRequest or SAMLResponse parameter.

Which is to be expected (accessing that endpoint without the require
parameter will lead to an error telling just that) and I think Jaime
told you that before already. No idea what that should illustrate.

Thanks. Jaime was saying the SAMLRequest parameter wouldn't do anything... but if I take it off, it says it expect that parameter, just confusing...
I'm configuring this URL in my service provider's saml20-sp-remote.php config, along with the SingleSignOnService and SingleLogoutService URLs:


> So how can I properly define the AssertionConsumerService URL?

You don't have to define anything. Once SimpleSAMLphp is accssible on
the web as documented all required endpoints will be defined and
behave correctly.
I don't use SimpleSAMLphp with Drupal or with Drupal extension
modules, so hard to say what's going on here.
-peter

Thanks, but why is there config then? Clearly I have to define some of these endpoints, either in the Canvas LMS's SAML config (Login URL and Logout URL must be defined, and I've set those to the Drupal login page), and these other URLs must be valid I am assuming?
 

Jaime Perez Crespo

unread,
Nov 16, 2015, 4:30:22 AM11/16/15
to simple...@googlegroups.com
Hi Ryan,

> On 14 Nov 2015, at 22:14 PM, Ryan Weiss <rw3...@gmail.com> wrote:
>> What's the value of 'loggingdir' in config/config.php?
>> Can the user PHP is running as create files there? Verify on the
>> command line or with a simple PHP script you access from the web.
>> What is 'logging.handler' set to?
>>
> 'loggingdir' => 'log/',
> 'logging.level' => SimpleSAML_Logger::NOTICE,
> 'logging.handler' => 'syslog',
>
> The /log directory has 777 permissions, so I don't see why PHP wouldn't be able to write to it.

Try setting your logging handler to “file" or “errorlog”. Without logs it’s quite difficult that you can solve any issue. You can worry about syslog afterwards.

>>> Caused by: Exception: Missing SAMLRequest or SAMLResponse parameter.
>
>> Which is to be expected (accessing that endpoint without the require
>> parameter will lead to an error telling just that) and I think Jaime
>> told you that before already. No idea what that should illustrate.
>
> Thanks. Jaime was saying the SAMLRequest parameter wouldn't do anything... but if I take it off, it says it expect that parameter, just confusing…

The AssertionConsumerService cannot expect a SAML request because, again, as its name says, it *consumes* assertions. There’s no assertions in a SAML request, only in SAML responses. My guess is that the error message is a generic one used for the exact same error in either the AssertionConsumerService or the SingleSignOnService. But you are right, it can be misleading. Can you open us an issue so that we fix it?

> I'm configuring this URL in my service provider's saml20-sp-remote.php config, along with the SingleSignOnService and SingleLogoutService URLs:
> 'AssertionConsumerService' => 'http://weiss.dev2.rowanonline.com/simplesaml/module.php/saml/sp/saml2-acs.php/drupalauth',
> 'SingleSignOnService' => 'http://weiss.dev2.rowanonline.com/simplesamlphp/www/saml2/idp/SSOService.php?spentityid=drupalauth&RelayState=https://rowan.test.instructure.com',
> 'SingleLogoutService' => 'http://weiss.dev2.rowanonline.com/simplesaml/module.php/saml/sp/saml2-logout.php/default-sp',

That’s all messed up. If you have the role of the service provider, you clearly aren’t a “remote” service provider. That’s what metadata/saml20-sp-remote.php is for, *remote service providers*. You don’t have to touch that file at all. All your configuration needs to go in config/config.ph and config/authsources.php.

Additionally, you are mixing ACS and SSO URLs, which doesn’t make any sense. Since you are the SP, you *consume assertions*, therefore you will expose an ACS URL in your metadata (which works out of the box, you don’t have to specify it or do nothing about it). Now, regarding the IdP you are using to delegate authentication to, that is indeed a *remote IdP*. So you need to add its metadata to the metadata/saml20-idp-remote.php file. Their metadata will contain (or should, at least) SSO and SLO URLs. But again, you don’t need to do anything about it. Just parse their metadata with the SAML metadata converter and paste it into the aforementioned file.

> Thanks, but why is there config then?

To configure things! :-)

> Clearly I have to define some of these endpoints,

No, you don’t. Why do you think you have to?

> either in the Canvas LMS's SAML config

What’s that? The software you are using for your SP? Or the IdP?

> (Login URL and Logout URL must be defined, and I've set those to the Drupal login page),

The Drupal login page has nothing to do with SAML in general or SimpleSAMLphp in particular. It’s a login page, not a SAML SingleSignOnService, so obviously it won’t work. You don’t need to be creative nor guess anything. All you need to configure both sides is the metadata of the other party. That’s what’s telling you where to reach the other party and how to “talk” to it.

> and these other URLs must be valid I am assuming?

All the URLs configured for both sides must be valid, of course. And so they are, as defined in the metadata.

My impression here is that you skipped the documentation at some point after installing SimpleSAMLphp, or you even skipped it completely if you were following some tutorial or any other documentation related to the Drupal plugin. Don’t do that. Go back to SimpleSAMLphp’s documentation and read it. You are mixing everything and there’s no point on trying to fix every individual problem you’ll encounter until you understand what you are doing (and what you need to do). If you have any doubts while following the documentation, please do not hesitate to ask here.

Peter Schober

unread,
Nov 16, 2015, 5:29:54 AM11/16/15
to SimpleSAMLphp
* Ryan Weiss <rw3...@gmail.com> [2015-11-14 22:14]:
> 'loggingdir' => 'log/',
> 'logging.level' => SimpleSAML_Logger::NOTICE,
> 'logging.handler' => 'syslog',
>
> The /log directory has 777 permissions, so I don't see why PHP
> wouldn't be able to write to it.

That explains all logging issues: What value you're setting for
'loggingdir' (ignoring for now that it's a relative path and that
there still might be isses with that) and any file system permissions
there aer irrelevant if you're logging to syslog: loggingdir only
applies if SimpleSAMLphp writes those files itself, i.e. when using
the 'file' logging.handler.
-peter

Ryan Weiss

unread,
Nov 16, 2015, 12:19:17 PM11/16/15
to SimpleSAMLphp


On Monday, November 16, 2015 at 4:30:22 AM UTC-5, Jaime Pérez wrote:
Hi Ryan,

> On 14 Nov 2015, at 22:14 PM, Ryan Weiss <rw3...@gmail.com> wrote:
>> What's the value of 'loggingdir' in config/config.php?
>> Can the user PHP is running as create files there? Verify on the
>> command line or with a simple PHP script you access from the web.
>> What is 'logging.handler' set to?
>>
>     'loggingdir' => 'log/',
>     'logging.level' => SimpleSAML_Logger::NOTICE,
>     'logging.handler' => 'syslog',
>
>   The /log directory has 777 permissions, so I don't see why PHP wouldn't be able to write to it.

Try setting your logging handler to “file" or “errorlog”. Without logs it’s quite difficult that you can solve any issue. You can worry about syslog afterwards.

Ah, thank you!
 
>>> Caused by: Exception: Missing SAMLRequest or SAMLResponse parameter.
>
>> Which is to be expected (accessing that endpoint without the require
>> parameter will lead to an error telling just that) and I think Jaime
>> told you that before already. No idea what that should illustrate.
>
> Thanks. Jaime was saying the SAMLRequest parameter wouldn't do anything... but if I take it off, it says it expect that parameter, just confusing…

The AssertionConsumerService cannot expect a SAML request because, again, as its name says, it *consumes* assertions. There’s no assertions in a SAML request, only in SAML responses. My guess is that the error message is a generic one used for the exact same error in either the AssertionConsumerService or the SingleSignOnService. But you are right, it can be misleading. Can you open us an issue so that we fix it?

OK, probably a generic error then. I will open an issue... Thank you.
 

> I'm configuring this URL in my service provider's saml20-sp-remote.php config, along with the SingleSignOnService and SingleLogoutService URLs:
>   'AssertionConsumerService' => 'http://weiss.dev2.rowanonline.com/simplesaml/module.php/saml/sp/saml2-acs.php/drupalauth',
>   'SingleSignOnService' => 'http://weiss.dev2.rowanonline.com/simplesamlphp/www/saml2/idp/SSOService.php?spentityid=drupalauth&RelayState=https://rowan.test.instructure.com',  
>   'SingleLogoutService' => 'http://weiss.dev2.rowanonline.com/simplesaml/module.php/saml/sp/saml2-logout.php/default-sp',

That’s all messed up. If you have the role of the service provider, you clearly aren’t a “remote” service provider. That’s what metadata/saml20-sp-remote.php is for, *remote service providers*. You don’t have to touch that file at all. All your configuration needs to go in config/config.ph and config/authsources.php.

Our setup is that we have a Canvas Learning Management System on a completely separate server, which is acting as the service provider. Then, on this 'dev2.rowanonline.com' box, we have our Drupal installation which is functioning as the Identity Provider. I don't have access to anything on the servive providers end, other than configuring the SAML setup within the Canvas adminstration panel, which lets me define things like the IdP entity ID, the Logon URL, Logout URL, Ceritificate Fingerprint, and that's basically it. So it is my understanding that I have to configure both the sp-remote.php and idp-hosted.php for these two sources, respectively. Is that correct?
 
 
Additionally, you are mixing ACS and SSO URLs, which doesn’t make any sense. Since you are the SP, you *consume assertions*, therefore you will expose an ACS URL in your metadata (which works out of the box, you don’t have to specify it or do nothing about it). Now, regarding the IdP you are using to delegate authentication to, that is indeed a *remote IdP*. So you need to add its metadata to the metadata/saml20-idp-remote.php file. Their metadata will contain (or should, at least) SSO and SLO URLs. But again, you don’t need to do anything about it. Just parse their metadata with the SAML metadata converter and paste it into the aforementioned file.

> Thanks, but why is there config then?

To configure things! :-)

> Clearly I have to define some of these endpoints,

No, you don’t. Why do you think you have to?
 
Cause the SP is remote (Canvas), and IdP is local/hosted (Drupal, only thing I have access to via command line/SimpleSamlPHP configs)
 


> either in the Canvas LMS's SAML config

What’s that? The software you are using for your SP? Or the IdP?

Software functioning as the SP on a separate server.
 

> (Login URL and Logout URL must be defined, and I've set those to the Drupal login page),

The Drupal login page has nothing to do with SAML in general or SimpleSAMLphp in particular. It’s a login page, not a SAML SingleSignOnService, so obviously it won’t work. You don’t need to be creative nor guess anything. All you need to configure both sides is the metadata of the other party. That’s what’s telling you where to reach the other party and how to “talk” to it.

> and these other URLs must be valid I am assuming?

All the URLs configured for both sides must be valid, of course. And so they are, as defined in the metadata.

My impression here is that you skipped the documentation at some point after installing SimpleSAMLphp, or you even skipped it completely if you were following some tutorial or any other documentation related to the Drupal plugin. Don’t do that. Go back to SimpleSAMLphp’s documentation and read it. You are mixing everything and there’s no point on trying to fix every individual problem you’ll encounter until you understand what you are doing (and what you need to do). If you have any doubts while following the documentation, please do not hesitate to ask here.

Heh, I've read the documentation up and down... Gonna try some more testing now that I seem to have logging working.

Thanks a ton for your help, guys.

Ryan Weiss

unread,
Nov 16, 2015, 12:31:25 PM11/16/15
to SimpleSAMLphp

Jaime Perez Crespo

unread,
Nov 17, 2015, 5:47:21 AM11/17/15
to simple...@googlegroups.com
Hi Ryan,

> On 16 Nov 2015, at 18:31 PM, Ryan Weiss <rw3...@gmail.com> wrote:
> Our setup is that we have a Canvas Learning Management System on a completely separate server, which is acting as the service provider. Then, on this 'dev2.rowanonline.com' box, we have our Drupal installation which is functioning as the Identity Provider. I don't have access to anything on the servive providers end, other than configuring the SAML setup within the Canvas adminstration panel, which lets me define things like the IdP entity ID, the Logon URL, Logout URL, Ceritificate Fingerprint, and that's basically it. So it is my understanding that I have to configure both the sp-remote.php and idp-hosted.php for these two sources, respectively. Is that correct?

Thanks for the detailed explanation, now it’s easier to figure out what your whole system looks like. You got it correctly, if you are an IdP, you need to configure both the sp-remote and the idp-hosted. But you also need to configure auth sources, since your IdP needs to authenticate somehow, and that’s where trouble starts, I think. I don’t know the plugin you are using to integrate Drupal and SimpleSAMLphp, but I would expect it to be intended to delegate authentication, that is, make Drupal a service provider, not an identity provider. I’m speculating here, though.

> If I hit the SingleSignOnService URL manually (that I've defined in saml20-sp-remote.php):

That’s wrong. The SingleSignOnService URL is where you start a SAML login, that is, the IdP. You can see that in the URL you are pasting yourself:

> http://weiss.dev2.rowanonline.com/simplesamlphp/www/saml2/idp/SSOService.php?spentityid=default-sp&RelayState=https://rowan.test.instructure.com

Note the *idp* in “saml2/idp/SSOService.php”. By the way, it looks like you have your entire SimpleSAMLphp installation accessible through the web server. That’s a security issue that you should fix. Now it’s ok as I see you have it protected with HTTP basic auth, but you should fix that before going into production.

In any case, in the metadata/saml20-sp-remote.php file what you define is how to talk to a remote service provider, not your own configuration. the SSOService URL is something of your own, and therefore it doesn’t belong in metadata pertaining to a remote entity (since you are the IdP9. What you need to specify there is the AssertionConsumerService and the SingleLogoutService URLs of the service provider (this Canvas thing).

Additionally, you are also making a mistake with the parameters. The “spentityid” parameter should specify the Entity ID of the Service Provider (Canvas), not the identifier of your local authentication source.
No, that’s neither correct nor normal. The URL you are trying to access directly is used for IdP-initiated login. Therefore, you shouldn’t get a SAML request in there. I’m trying to decode the request and it’s not even a SAML request, but binary data (are you using encryption?).

The only way I can imagine that you might end up having this redirection as well as the subsequent loop, is that you have defined the SP with an entity ID “default-sp” in saml20-sp-remote.php. Then the SP being misconfigured and not recognizing your response after authenticating, sending you a SAML request to the SSOService endpoint, which you will reply immediately with another SAML response since the user already has a session, and so on and so forth.

What does your log file say when you do this?

>>> Clearly I have to define some of these endpoints,
>
>> No, you don’t. Why do you think you have to?
>
> Cause the SP is remote (Canvas), and IdP is local/hosted (Drupal, only thing I have access to via command line/SimpleSamlPHP configs)

You need to configure Canvas according to your IdP metadata. That is, you need to set in the Canvas configuration the following:

- Your IdP entity ID, as expressed in your IdP metadata.
- Your SingleSignOn URL, as expressed in your IdP metadata.
- Your SingleLogout URL, as expressed in your IdP metadata.
- The fingerprint of your certificate, as Canvas apparently is willing to validate your signatures. This means you also need to configure your IdP to sign your responses to Canvas, and you need to make sure the fingerprint of your certificate is correct.

> Heh, I've read the documentation up and down... Gonna try some more testing now that I seem to have logging working.

If I were you, I would forget about Drupal right now. First of all, try to configure SimpleSAMLphp correctly:

1. Solve the issue you have with the whole SSP directory being accessible.
2. Configure an auth source (example-userpass should do the trick).
3. Make sure that auth source works by going to the web interface of your IdP, ‘Authentication’ tab, and then ‘Test configured authentication sources’.
4. If that works fine, configure your IdP (metadata/saml20-idp-hosted.php) to use that auth source.
5. Now, make sure you configured correctly the SP: get their SAML metadata (XML), parse it with the "XML to SimpleSAMLphp metadata converter” tool, paste the results (the PHP code) into metadata/saml20-sp-remote.php (and obviously get rid of the config you had in place).
6. Configure Canvas as I told you above, and try to trigger a login in there.
7. Check that both login and logout works with the auth source you configured.

Once you’ve gone through all steps and everything works fine (you are logged into Canvas with the user you defined in your configuration for example-userpass), you can worry about bringing Drupal into the equation, which is an entirely different story.

Hope that helps.

Ryan Weiss

unread,
Nov 17, 2015, 10:37:05 PM11/17/15
to SimpleSAMLphp
Hi Jaime,

 This is great, thanks a ton for your help.
 Alright so I tried some things....

 First thing I tried was configuring the example-userpass authsource, like this:

'example-userpass' => array(
       
'exampleauth:UserPass',

       
'student:studentpass' => array(
           
'uid' => array('test'),
           
'eduPersonAffiliation' => array('member', 'student'),
       
),
       
'employee:employeepass' => array(
           
'uid' => array('employee'),
           
'eduPersonAffiliation' => array('member', 'employee'),
       
),
   
),

Then I tried to test this in the simplesaml configuration "test authentication sources", but it gives the following error:

SimpleSAML_Error_Error: UNHANDLEDEXCEPTION

Backtrace:
0 /var/www/weiss.dev2.rowanonline.com/webroot/simplesamlphp/www/module.php:179 (N/A)
Caused by: Exception: Could not resolve 'exampleauth:UserPass': No class named 'sspmod_exampleauth_Auth_Source_UserPass'.
Backtrace:
6 /var/www/weiss.dev2.rowanonline.com/webroot/simplesamlphp/lib/SimpleSAML/Module.php:134 (SimpleSAML_Module::resolveClass)
5 /var/www/weiss.dev2.rowanonline.com/webroot/simplesamlphp/lib/SimpleSAML/Auth/Source.php:207 (SimpleSAML_Auth_Source::parseAuthSource)
4 /var/www/weiss.dev2.rowanonline.com/webroot/simplesamlphp/lib/SimpleSAML/Auth/Source.php:247 (SimpleSAML_Auth_Source::getById)
3 /var/www/weiss.dev2.rowanonline.com/webroot/simplesamlphp/lib/SimpleSAML/Auth/Default.php:59 (SimpleSAML_Auth_Default::initLogin)
2 /var/www/weiss.dev2.rowanonline.com/webroot/simplesamlphp/lib/SimpleSAML/Auth/Simple.php:136 (SimpleSAML_Auth_Simple::login)
1 /var/www/weiss.dev2.rowanonline.com/webroot/simplesamlphp/modules/core/www/authenticate.php:45 (require)
0 /var/www/weiss.dev2.rowanonline.com/webroot/simplesamlphp/www/module.php:134 (N/A)

So it's saying it can't find the'sspmod_exampleauth_Auth_Source_UserPass' class, however, this seems to exist just fine in the source code:
/simplesamlphp/modules/exampleauth/lib/Auth/Source/UserPass.php
Viewing this file shows:
class sspmod_exampleauth_Auth_Source_UserPass extends sspmod_core_Auth_UserPassBase { ...

So the class exists. Why wouldn't it be able to find it?

Regarding the logging on the redirect loop... it logs nothing when I test this in the redirect state, unfortunately. 
I can recreate the redirect loop by testing the 'drupalauth' authentication source the same as the example-userpass one above:
http://weiss.dev2.rowanonline.com/simplesaml/module.php/core/authenticate.php?as=drupalauth 

My 'drupalauth' authsources.php config looks like this (please see comments with where I may have things messed up):
'drupalauth' => array(
   
'saml:SP',
   
//'drupalauth:External',
   
//'drupalroot' => '/var/www/weiss.dev2.rowanonline.com/webroot',

   
//is this correct? should be the SP entity ID as defined in saml20-sp-remote.php?
   
'entityID' => 'default-sp',

   
//not sure if all these are necessary

   
'idp' => 'drupal-idp-entityid',
   
'saml:sp:Idp' => 'drupal-idp-entityid',
   
'saml:idp' => 'drupal-idp-entityid',


   
'discoURL' => null,

   
//documentation alluded that I only needed to define 'certificate' as the .pem file here:

   
//'privatekey' => 'saml_sp.pem',
   
'certificate' => 'saml_sp.pem',
   
//'certificate' => 'saml_sp.crt',


   
//should go back to this page at the SP side after login

   
'RelayState' => 'https://rowan.test.instructure.com',

   
'acs.Bindings' => array(
           
'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST',
           
'urn:oasis:names:tc:SAML:1.0:profiles:browser-post'
   
),

     
// Which attributes should be retrieved from the Drupal site.
   
'attributes' => array(
        array
('drupaluservar' => 'uid',  'callit' => 'uid'),
        array
('drupaluservar' => 'name', 'callit' => 'cn'),
        array
('drupaluservar' => 'mail', 'callit' => 'mail'),
        array
('drupaluservar' => 'field_first_name',  'callit' => 'givenName'),
        array
('drupaluservar' => 'field_last_name',   'callit' => 'sn'),
        array
('drupaluservar' => 'field_organization','callit' => 'ou'),
        array
('drupaluservar' => 'roles','callit' => 'roles'),
   
),


   
'drupal_logout_url' => 'http://weiss.dev2.rowanonline.com/?q=user/logout',

   
'drupal_login_url' => 'http://weiss.dev2.rowanonline.com/?q=user/login',

   
'NameIDFormat' => 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient'
   
//'NameIDFormat' => 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress'

   
//'attributes.NameFormat' => 'urn:oasis:names:tc:SAML:2.0:attrname-format:basic',
),

To answer your other questions, I'm using the drupalauth module to do the SimpleSAML integration on the Drupal/IdP end:

And in the Canvas (SP) configuration, I've configured the following in the administration panel:
IdP Entity ID: drupal-idp-entityid (this is what I have defined in saml20-idp-hosted.php, and also referenced as the 'idp' in saml20-sp-remote.php)
Logon URL: http://weiss.dev2.rowanonline.com/simplesaml/saml2/idp/SSOService.php
Logout URL: http://weiss.dev2.rowanonline.com/simplesaml/module.php/saml/sp/saml2-logout.php/default-sp
Certificate fingerprint: B4:7A:62:5F:36:C0:2D:8A:D4:B6:11:49:68:FC:FF:32:2E:D5:2E:50 (was generated from the saml_sp.crt file, and matches the 'certFingerprint' attribute in saml20-sp-remote.php

You wrote that "This means you also need to configure your IdP to sign your responses to Canvas, and you need to make sure the fingerprint of your certificate is correct."
I'm not entirely sure how to do this, or if it's even necessary. Do you have any leads I can read into on how to do that?

Thanks again, Jaime!


Ryan Weiss

unread,
Nov 17, 2015, 11:15:19 PM11/17/15
to SimpleSAMLphp
On further digging, what is also interesting...

If I turn on SAML debugging in the Canvas administration panel (it waits for a request to hit it), and then I try to do the saml login from the SP endpoint (as I have configure above for the Canvas admin config):
http://rowan.test.instructure.com/login/saml

This then hits the redirect loop, landing on the dev2.rowanonline.com side (this is expected due to the current misconfiguration somewhere), but if I then immediately go back to the Canvas panel, and try to 'Refresh' the debugging, so that it will show me the request, it logs me out, which leads me to believe the SAML request is coming back to the SP somehow, and then screwing with the login or the cookie or session or something. If you have any ideas on that...

I'm trying to get a hold of the SAML metadata (XML) as you mentioned. I think this URL provides it, if you can confirm:
https://rowan.test.instructure.com/saml_meta_data

If you can't see that, it gives:
<EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata" entityID="http://rowan.instructure.com/saml2">
<SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
<KeyDescriptor use="encryption">
<X509Data>
<X509Certificate>
MIIE8TCCA9mgAwIBAgIJAOBms/PYWcPLMA0GCSqGSIb3DQEBCwUAMIGrMQswCQYD VQQGEwJVUzENMAsGA1UECBMEVXRhaDEXMBUGA1UEBxMOU2FsdCBMYWtlIENpdHkx GTAXBgNVBAoTEEluc3RydWN0dXJlLCBJbmMxEzARBgNVBAsTCk9wZXJhdGlvbnMx IDAeBgNVBAMTF0NhbnZhcyBTQU1MIENlcnRpZmljYXRlMSIwIAYJKoZIhvcNAQkB FhNvcHNAaW5zdHJ1Y3R1cmUuY29tMB4XDTE1MDQxNTAxMDAwMFoXDTE3MDQyMjAx MDAwMFowgasxCzAJBgNVBAYTAlVTMQ0wCwYDVQQIEwRVdGFoMRcwFQYDVQQHEw5T YWx0IExha2UgQ2l0eTEZMBcGA1UEChMQSW5zdHJ1Y3R1cmUsIEluYzETMBEGA1UE CxMKT3BlcmF0aW9uczEgMB4GA1UEAxMXQ2FudmFzIFNBTUwgQ2VydGlmaWNhdGUx IjAgBgkqhkiG9w0BCQEWE29wc0BpbnN0cnVjdHVyZS5jb20wggEiMA0GCSqGSIb3 DQEBAQUAA4IBDwAwggEKAoIBAQDckDPQGWedlVGC2Z9fn1wNFmN+0IPNi6OSE1nM voTWx2oZlQepaAu4zI5QqOfnV0rW2V1volpoJbu0WelH0DkGzdOEQdWJjAs3nRBf y0evxtpg0tK5kIvGsnN6YcD41YmkfWzvwbMf0cEq1Y0wCmymF6XzOUUE4zsi0nhP m2Z7WiuongDQdR01UsDN13YcpD/i1JXr3YtkNnJ/a1Kc9OXNycI8M5NVo5QQgdx/ Q7zAmTk8p9E0ZRthdOQ/PBicWx39mNmBij5KpqCWlHu3NWdgcG8KXSv5atXU8Crd TRJ3aGIEN9vBYIHe8MHGCzs1QlRfJmXFMkeUSOTnJJx78rMDAgMBAAGjggEUMIIB EDAdBgNVHQ4EFgQUo0WWVlJ1SxZOs11L85ZAuZGyuzEwgeAGA1UdIwSB2DCB1YAU o0WWVlJ1SxZOs11L85ZAuZGyuzGhgbGkga4wgasxCzAJBgNVBAYTAlVTMQ0wCwYD VQQIEwRVdGFoMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEZMBcGA1UEChMQSW5z dHJ1Y3R1cmUsIEluYzETMBEGA1UECxMKT3BlcmF0aW9uczEgMB4GA1UEAxMXQ2Fu dmFzIFNBTUwgQ2VydGlmaWNhdGUxIjAgBgkqhkiG9w0BCQEWE29wc0BpbnN0cnVj dHVyZS5jb22CCQDgZrPz2FnDyzAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUA A4IBAQBV3EmmnzYqYQ5fXNZymG2WaspEW0NeFMhDXa3p3AMIQJbnnU14lR7bqIvf /bLW1YE0fw1kSzsw8VrkQp7k1U+kaYA3i5/FQBy2WtqUCVq2GXZA2gs5YD4nvJB/ F57E//0kEhbATZH9+wJqDkqyIgsrSIlJjiXDth1BppGK8weboPtr9sWV24Ui0+ls w16XTsGlnRRO19g+gXKOZp5ApXkDrB+HwZQvZxiCuSgvJlcBzMdxVvWSL+vPtg8Y shIKzobIhaQ2MzXHLcxrDhW10YFPwDXh8Tfn5iU9ONsaJivuvVhtDYZD1ZzSoPpm q4vYqxxY/6rFJhrCtnlLepSaxlXM
</X509Certificate>
</X509Data>
</KeyInfo>
<EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc">
<KeySize xmlns="http://www.w3.org/2001/04/xmlenc#">128</KeySize>
</EncryptionMethod>
</KeyDescriptor>
<KeyDescriptor use="signing">
<X509Data>
<X509Certificate>
MIIE8TCCA9mgAwIBAgIJAOBms/PYWcPLMA0GCSqGSIb3DQEBCwUAMIGrMQswCQYD VQQGEwJVUzENMAsGA1UECBMEVXRhaDEXMBUGA1UEBxMOU2FsdCBMYWtlIENpdHkx GTAXBgNVBAoTEEluc3RydWN0dXJlLCBJbmMxEzARBgNVBAsTCk9wZXJhdGlvbnMx IDAeBgNVBAMTF0NhbnZhcyBTQU1MIENlcnRpZmljYXRlMSIwIAYJKoZIhvcNAQkB FhNvcHNAaW5zdHJ1Y3R1cmUuY29tMB4XDTE1MDQxNTAxMDAwMFoXDTE3MDQyMjAx MDAwMFowgasxCzAJBgNVBAYTAlVTMQ0wCwYDVQQIEwRVdGFoMRcwFQYDVQQHEw5T YWx0IExha2UgQ2l0eTEZMBcGA1UEChMQSW5zdHJ1Y3R1cmUsIEluYzETMBEGA1UE CxMKT3BlcmF0aW9uczEgMB4GA1UEAxMXQ2FudmFzIFNBTUwgQ2VydGlmaWNhdGUx 
(truncating for security purposes, just in case...)
</X509Certificate>
</X509Data>
</KeyInfo>
</KeyDescriptor>
<SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://rowan.test.instructure.com/login/saml/logout"/>
<AssertionConsumerService index="0" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://rowan.test.instructure.com/saml_consume"/>
<AssertionConsumerService index="1" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://rowan.test.instructure.com/login/saml"/>
<AssertionConsumerService index="2" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://rowan.instructure.com/saml_consume"/>
<AssertionConsumerService index="3" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://rowan.instructure.com/login/saml"/>
<AssertionConsumerService index="4" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://rowan.staging.instructure.com/saml_consume"/>
<AssertionConsumerService index="5" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://rowan.staging.instructure.com/login/saml"/>
<AssertionConsumerService index="6" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://rowan.beta.instructure.com/saml_consume"/>
<AssertionConsumerService index="7" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://rowan.beta.instructure.com/login/saml"/>
</SPSSODescriptor>
<ContactPerson contactType="technical">
<SurName>Administrator</SurName>
<EmailAddress>mailto:in...@instructure.com</EmailAddress>
</ContactPerson>
</EntityDescriptor>

I put this in the metadata converter tool and got a new saml20-sp-remote.php config, which looks really great. I think we're onto something! I'm won't touch the saml20-sp-config.php from this point on.

Now if I test the saml login on the SP:
It still puts me in the redirect loop. This means there is some misconfiguration in the authsources.php or saml20-idp-hosted.php config, or possibly the Canvas admin configuration (Login URL potentially, which is still defined as: http://weiss.dev2.rowanonline.com/simplesaml/saml2/idp/SSOService.php )

The config for the 'drupalauth' authsource is the same as I posted in the last message, except I changed the 'entityID' to the new SP entity ID the metadata gave me:
    'entityID' => 'http://rowan.instructure.com/saml2',

The saml20-idp-hosted.php config looks like this:
$metadata['drupal-idp-entityid'] = array(
 
'auth' => 'drupalauth',
 
'entityid' => 'drupal-idp-entityid',

 
'host' => 'weiss.dev2.rowanonline.com',


 
'RelayState' => 'https://rowan.test.instructure.com',

 
'privatekey' => 'saml_sp.pem',
 
'certificate' => 'saml_sp.crt',
 
'certFingerprint' => 'B4:7A:62:5F:36:C0:2D:8A:D4:B6:11:49:68:FC:FF:32:2E:D5:2E:50',

 
'NameIDFormat' => 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient',
   
//'NameIDFormat' => 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress',
 
 
'SingleSignOnService' => 'http://weiss.dev2.rowanonline.com/simplesaml/saml2/idp/SSOService.php',
 
'SingleLogoutService'  => 'http://weiss.dev2.rowanonline.com/simplesaml/saml2/idp/SingleLogoutService.php',
);

Do you see any glaring errors with this IdP config (or the drupalauth authsource)? 
Is the 'saml:SP' the correct authentication module to be using for this 'drupalauth' authsource? If I try changing it to the 'drupalauth:External' type instead, it brings me to the Drupal login page, and puts me on the user page after login, but doesn't go back to the SP/Canvas (it also malforms the URL with the ReturnTo parameter, all of this mentioned previously), ie:
http://weiss.dev2.rowanonline.com/?q=user%2Flogin%3FReturnTo&ReturnTo=http%3A%2F%2Fweiss.dev2.rowanonline.com%2Fsimplesaml%2Fmodule.php%2Fdrupalauth%2Fresume.php%3FState%3D_d5b786888552dc0d207d4bb7a6bb949e09f6cc32f6%253Ahttp%253A%252F%252Fweiss.dev2.rowanonline.com%252Fsimplesaml%252Fsaml2%252Fidp%252FSSOService.php%253Fspentityid%253Dhttp%25253A%25252F%25252Frowan.instructure.com%25252Fsaml2%2526cookieTime%253D1447819655

It doesn't put anything in the log file when I try the 'drupalauth:External' module, but now that the SP metadata is configured correctly, when using 'saml:SP', the redirect loop produces the following errors in the log:

Nov 17 23:09:58 simplesamlphp WARNING [548aa14a60] Authentication request specifies invalid AssertionConsumerService:
Nov 17 23:09:58 simplesamlphp WARNING [548aa14a60] AssertionConsumerServiceURL: 'http://weiss.dev2.rowanonline.com/simplesaml/module.php/saml/sp/saml2-acs.php/drupalauth'
Nov 17 23:09:58 simplesamlphp WARNING [548aa14a60] ProtocolBinding: 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST'
Nov 17 23:09:58 simplesamlphp WARNING [bf5cf34e30] Authentication request specifies invalid AssertionConsumerService:
Nov 17 23:09:58 simplesamlphp WARNING [bf5cf34e30] AssertionConsumerServiceURL: 'http://weiss.dev2.rowanonline.com/simplesaml/module.php/saml/sp/saml2-acs.php/drupalauth'
Nov 17 23:09:58 simplesamlphp WARNING [bf5cf34e30] ProtocolBinding: 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST'
Nov 17 23:09:58 simplesamlphp WARNING [93d4782c14] Authentication request specifies invalid AssertionConsumerService:
Nov 17 23:09:58 simplesamlphp WARNING [93d4782c14] AssertionConsumerServiceURL: 'http://weiss.dev2.rowanonline.com/simplesaml/module.php/saml/sp/saml2-acs.php/drupalauth'
Nov 17 23:09:58 simplesamlphp WARNING [93d4782c14] ProtocolBinding: 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST'
(and so on...)

I don't have this AssertionConsumerServiceURL defined anywhere. That is newly defined from the metadata converter as mentioned above, and is defined as:
'AssertionConsumerService' =>
  array
(
   
0 =>
    array
(
     
'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST',
     
'Location' => 'https://rowan.test.instructure.com/saml_consume',
     
'index' => 0,
   
),
   
1 =>
    array
(
     
'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST',
     
'Location' => 'https://rowan.test.instructure.com/login/saml',
     
'index' => 1,
   
),
 
...

So that's where I'm at, a little stuck...



Peter Schober

unread,
Nov 18, 2015, 3:30:45 AM11/18/15
to SimpleSAMLphp
* Ryan Weiss <rw3...@gmail.com> [2015-11-18 04:37]:
> First thing I tried was configuring the example-userpass authsource, like
> this:
[...]
> Caused by: Exception: Could not resolve 'exampleauth:UserPass': No class
> named 'sspmod_exampleauth_Auth_Source_UserPass'.

> So it's saying it can't find the'sspmod_exampleauth_Auth_Source_UserPass' class,
> however, this seems to exist just fine in the source code:
> /simplesamlphp/modules/exampleauth/lib/Auth/Source/UserPass.php

It's disabled by default:
$ ls modules/exampleauth/*able*
modules/exampleauth/default-disable

You need to enable it first:
$ touch modules/exampleauth/enable

I'm pretty sure the documentation covers usage of modules somewhere.

It's good we're actually going back to the very first steps of how to
use SimpleSAMLphp as at I couldn't follow all the weird things that
happend (or that you tried/caused). To me all that created the
impression that you knew what you were doing and that you're certain
the basic config is correct. Seems I was mistaken.

> 'drupalauth' => array(
> 'saml:SP',
> //is this correct? should be the SP entity ID as defined in saml20-sp-remote.php?
> 'entityID' => 'default-sp',

The comment above the auth source called 'default-sp' as shipped by
default in SimpleSAMLphp is:

// The entity ID of this SP.

If that isn't clear, there's always the documentation.
So yes, that's the SP's own entityID, but NOT "as defined in
saml20-sp-remote.php" because this here is the SP, and an SP does not
federate with other ("remote") SPs, so saml20-sp-remote.php is fully
irrelevant for an SP. The documentation for the SimpleSAMLphp SP also
never mentions saml20-sp-remote.php.
(A SimpleSAMLphp IDP would use saml20-sp-remote.php, though, and that
would contain your own SP as well as other SPs such as Canvas.
You're confusing yourself by mixing IDP and SP on the same system.)

Jaime already commented on that specific choice of entityID value. No
idea why you would do that, setting the entityID to that specific
string.

As is the case so often, the default is correct, i.e, SSP will (would
have, it you let it) create one dynamically for you. So if you don't
know what it is (and don't read the documentation) it would still be
fine. If you know what it is (and/or read the documentation) you're
free to set it to a URI that uniquely identifies this SAML SP globally.

> //not sure if all these are necessary
> 'idp' => 'drupal-idp-entityid',
> 'saml:sp:Idp' => 'drupal-idp-entityid',
> 'saml:idp' => 'drupal-idp-entityid',

No idea what brings you to that. The shipped code looks like this.

// 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' => NULL,

So no, only the first one would be needed, and only if you wanted to
avoid IDP discovery, i.e., only if this SP only federates with a
single IDP. Meaning if you leave the default everything will still
work, just with ann extra step of chosing the IDP during the login
process. (Which is useless if you only have one IDP, but doesn't break
anything either!)

> //documentation alluded that I only needed to define 'certificate' as the .pem file here:
> //'privatekey' => 'saml_sp.pem',
> 'certificate' => 'saml_sp.pem',
> //'certificate' => 'saml_sp.crt',

Could you please identify that part of the documentation and why you
think it tried to say something like that?
If your SAML SP has a certificate included in its SAML metadata at all
many SAML IDPs will use that to encrypt SAML assertions (or responses)
to your SP with that key. That means your SP would be unable to
decrypt them unless it had the matching private key.
I'm not going to guess whether you take the above to mean having both
the private key and the public key (certificate) in the same file on
disk.

> //should go back to this page at the SP side after login
> 'RelayState' => 'https://rowan.test.instructure.com',

The SP will set that itself (if accessed before authenticating at the
IDP) and that should be a URL at the same server/service/resource the
SAML SP runs in.
So likely you don't have to set that at all.

> 'acs.Bindings'

No idea why you think you need to include this in your authsource.
The defaults as shipped plus adding a 'privatekey' and 'certificate'
(as documented) are enough to make a SAML SP work.

Personally I'd suggest to start over, from scratch.
Then do nothing the documentation doesn't say you must.
Not only will you be done in 5 min, it will also just work.

> // Which attributes should be retrieved from the Drupal site.

No idea about any of the Drupal integration stuff, so can't comment.

> 'NameIDFormat' => 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient'
> //'NameIDFormat' => 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress'

None of this should be needed, from what I remember having read so
far. Leave the defaults.

> //'attributes.NameFormat' =>
> 'urn:oasis:names:tc:SAML:2.0:attrname-format:basic',

Possible but some consider this bad practice. URI name format has the
big advantage that attribute names are globally unique (with properly
chosen URIs) so that there's no discussion about what entity X or Y
considers the proper format/content of "full_name" or whatever other
attribute, which avoids the ugly situation of having to send entity X
something else as the same attribute as entity Y (because the have
non-identical requirements for the same "basic name").

> And in the Canvas (SP) configuration, I've configured the following in the
> administration panel:
> IdP Entity ID: *drupal-idp-entityid* (this is what I have defined in
> saml20-idp-hosted.php, and also referenced as the 'idp' in
> saml20-sp-remote.php)

Correct.

> Logon URL:
> *http://weiss.dev2.rowanonline.com/simplesaml/saml2/idp/SSOService.php*
> Logout URL:
> *http://weiss.dev2.rowanonline.com/simplesaml/module.php/saml/sp/saml2-logout.php/default-sp*

Not if that is on canvas and asks about your IDP. Note the /sp/ in the
URL, that is for your SAML SP. Why not define seperate DNS names and
vhosts for the IDP and SP, that would make that much more clear?

(Of couse that's all Cavas' fault: We have SAML Metadata for all that,
which is machine readable, so why ask people to fill out forms
guessing at the right values when they could have just accepted an XML
file from you instead? Maybe they do, then it's your choice.)

> Certificate fingerprint:
> *B4:7A:62:5F:36:C0:2D:8A:D4:B6:11:49:68:FC:FF:32:2E:D5:2E:50* (was
> generated from the saml_sp.crt file, and matches the 'certFingerprint'
> attribute in saml20-sp-remote.php

No idea what this is about, but if this is still the Canvas GUI where
you configure your SAML IDP then it's certainly NOT something from
saml20-sp-remote.php.

Now I'm wondering what connection you're asking about, your own SP to
your own IDP? Your own IDP to Canvas? Mixing this all up in the same
thread, using config files and settings from all possible actors,
doesn't make this easier for you to understand or for anyone else to
try to help you. I get that ultimately you want ALL OF IT to work, but
you don't go at a problem like this by changing all the settings
everywhere at once.
-peter

Peter Schober

unread,
Nov 18, 2015, 3:34:40 AM11/18/15
to SimpleSAMLphp
* Ryan Weiss <rw3...@gmail.com> [2015-11-18 05:15]:
> The config for the 'drupalauth' authsource is the same as I posted in the
> last message, except I changed the 'entityID' to the new SP entity ID the
> metadata gave me:
> * 'entityID' => 'http://rowan.instructure.com/saml2',*

I'd have to go back though the whole thread but do you even have a
SAML SP running yourself, using SimpleSAMLphp and it's API to protect
a local resource? If not then anything you have in
config/authsources.php that is of the type 'saml:SP' is wrong and
should be commented out/removed.

You don't configure a local SP in SimpleSAMLphp with the name of some
externally run SP. Instead you configure your SimpleSAMLphp IDP with
metadata for the exernal/remote SP.
-peter

Jaime Perez Crespo

unread,
Nov 18, 2015, 4:52:18 AM11/18/15
to simple...@googlegroups.com
Hi Ryan,

As Peter already suggested, I would strongly recommend you to start over. You have an incredible amount of misconfigurations and even non-existent configuration options, not to mention things you shouldn’t be modifying or things that don’t make any sense at all.

You are setting up an IdP, which will use an auth source (drupalauth) to authenticate your users. That’s all you need. No custom code. No SAML SP. No fancy options. Just remove your config directory and start over by copying config-templates into config. Go again through the installation guide:

https://simplesamlphp.org/docs/stable/simplesamlphp-install

Once SSP is up and running again, go through the IdP guide:

https://simplesamlphp.org/docs/stable/simplesamlphp-idp

There’s only one thing you don’t need to touch / remove: metadata/saml20-sp-remote.php. You already have Canvas’ metadata in there, so no need to do that again.

After successfully configuring an example_userpass authsource in config/authsources.php and making sure authentication works fine with it, you can proceed and try to configure the drupalauth authentication source:

https://code.google.com/p/drupalauth/wiki/INSTALLATION

Following all of that, step by step, should yield an IdP working successfully with both Drupal and Canvas.

PD.: the source of your redirect loop is that the auth source in use by your IdP uses a SAML SP defined in authsources.php (drupalauth) that’s pointing to the very same IdP. That is, when your IdP tries to authenticate the user, it sees you told it to perform a SAML authentication against… itself! That’s why you were getting a SAMLRequest sent to your SSOService URL while trying to perform an IdP-first login.

Ryan Weiss

unread,
Nov 18, 2015, 10:49:07 AM11/18/15
to SimpleSAMLphp
Thanks Jaime, and Peter.

Being as this is all new territory for me, and that it wasn't working with basic configuration from the get-go, I kind of fell into this spiral of trying all the configs with different values. Sorry if it looks a little messy. 

I started over, clearing out the configs, and keeping the saml20-sp-remote.php config from the converted metadata.

I enabled the exampleauth module, and tried to test it as an authentication source from the simplesamlphp configuration panel, but it's still falling into a redirect loop, which seems strange. 

Here's what I have for the authsource and the IdP config:

authsources.php:
    'example-userpass' => array(
       
'exampleauth:UserPass',
       
       
'student:studentpass' => array(
           
'uid' => array('test'),
           
'eduPersonAffiliation' => array('member', 'student'),
       
),
       
'employee:employeepass' => array(
           
'uid' => array('employee'),
           
'eduPersonAffiliation' => array('member', 'employee'),
       
),
   
),

saml20-idp-hosted.php:
$metadata['__DYNAMIC:1__'] = array(
 
'host' => '__DEFAULT__',


 
'privatekey' => 'saml_sp.pem',
 
'certificate' => 'saml_sp.crt',


 
'auth' => 'example-userpass'
);

So this is very basic. I've cleared my cache/cookies, and logged out of everything related. 
Why would the example-userpass authentication test fall into the redirect loop?


And nothing gets put into the simplesamlphp log file...

Any ideas on this basic configuration on the Drupal/IdP side?

Thanks.



Ryan Weiss

unread,
Nov 18, 2015, 12:10:44 PM11/18/15
to SimpleSAMLphp
I thought maybe it was looping because the 'ReturnTo' parameter is the same as the origin link for testing the authsource:

The testing link is:

http://weiss.dev2.rowanonline.com/simplesaml/module.php/core/authenticate.php?as=example-userpass


And when I click (as stated above), it brings me to this loop:

http://weiss.dev2.rowanonline.com/simplesaml/module.php/core/loginuserpass.php?AuthState=_c866447c6d7b02aa14a3d9b4667b2a580d0c71c931%3Ahttp%3A%2F%2Fweiss.dev2.rowanonline.com%2Fsimplesaml%2Fmodule.php%2Fcore%2Fas_login.php%3FAuthId%3Dexample-userpass%26ReturnTo%3Dhttp%253A%252F%252Fweiss.dev2.rowanonline.com%252Fsimplesaml%252Fmodule.php%252Fcore%252Fauthenticate.php%253Fas%253Dexample-userpass


Where the ReturnTo parameter is the same as the original link... so that kind of makes sense, but if I change the ReturnTo parameter to anything else (ie. www.google.com), it still falls into the redirect loop, but puts me on a new page/different url:

http://weiss.dev2.rowanonline.com/simplesaml/module.php/core/as_login.php?AuthId=example-userpass&ReturnTo=http%3A%2F%2Fgoogle.com


Just wanted to make you guy aware of that behavior...

Jaime Perez Crespo

unread,
Nov 18, 2015, 5:18:53 PM11/18/15
to simple...@googlegroups.com
Hi Ryan,

> On 18 Nov 2015, at 18:10 PM, Ryan Weiss <rw3...@gmail.com> wrote:
> I thought maybe it was looping because the 'ReturnTo' parameter is the same as the origin link for testing the authsource:

No, the ReturnTo parameter tells SSP where to go back after successful authentication. If authentication succeeds, and everything goes fine, that very same URL will display your attributes instead of redirecting to start authentication. Which leads me to think that your configuration is broken with regard to the session.

What session handler are you using? Cookies configuration?

> Where the ReturnTo parameter is the same as the original link... so that kind of makes sense, but if I change the ReturnTo parameter to anything else (ie. www.google.com), it still falls into the redirect loop, but puts me on a new page/different url:
>
> http://weiss.dev2.rowanonline.com/simplesaml/module.php/core/as_login.php?AuthId=example-userpass&ReturnTo=http%3A%2F%2Fgoogle.com

An open redirection to an external domain is a vulnerability that you should shut down (look at the ‘trusted.url.domains’ configuration option in config.php).

In any case, this is quite difficult to debug with any traces at all. You need to get your logs working first, as debugging without them will be a nightmare. What’s your log-related configuration? Handler, file, level, etc?

Secondly, in order to debug redirections from one page to another, you should be tracking all of them. Install the SAML tracer Firefox extension and enable it while testing. You will be able to see all the HTTP requests and responses, as well as the SAML messages involved.

> authsources.php:
> 'example-userpass' => array(
> 'exampleauth:UserPass',
>
> 'student:studentpass' => array(
> 'uid' => array('test'),
> 'eduPersonAffiliation' => array('member', 'student'),
> ),
> 'employee:employeepass' => array(
> 'uid' => array('employee'),
> 'eduPersonAffiliation' => array('member', 'employee'),
> ),
> ),

This looks good.

> saml20-idp-hosted.php:
> $metadata['__DYNAMIC:1__'] = array(
> 'host' => '__DEFAULT__',
>
> 'privatekey' => 'saml_sp.pem',
> 'certificate' => 'saml_sp.crt',
>
> 'auth' => 'example-userpass'
> );

And this is not even necessary at this point. First we need to get example-userpass working. Then we can move on into SAML interactions.

> So this is very basic. I've cleared my cache/cookies, and logged out of everything related.
> Why would the example-userpass authentication test fall into the redirect loop?
>
> When I click the 'example-userpass' to test, it brings me to the following URL (redirect loop):
> http://weiss.dev2.rowanonline.com/simplesaml/module.php/core/loginuserpass.php?AuthState=_c866447c6d7b02aa14a3d9b4667b2a580d0c71c931%3Ahttp%3A%2F%2Fweiss.dev2.rowanonline.com%2Fsimplesaml%2Fmodule.php%2Fcore%2Fas_login.php%3FAuthId%3Dexample-userpass%26ReturnTo%3Dhttp%253A%252F%252Fweiss.dev2.rowanonline.com%252Fsimplesaml%252Fmodule.php%252Fcore%252Fauthenticate.php%253Fas%253Dexample-userpass
>
> And nothing gets put into the simplesamlphp log file…

As I said, first you need to get your logs working.

> Any ideas on this basic configuration on the Drupal/IdP side?

Looks pretty much like a session misconfiguration. But hard or even impossible to say without any more information.

Ryan Weiss

unread,
Nov 18, 2015, 5:38:12 PM11/18/15
to SimpleSAMLphp
Hi Jaime,

Please see my comments...

On Wednesday, November 18, 2015 at 5:18:53 PM UTC-5, Jaime Pérez wrote:
Hi Ryan,

> On 18 Nov 2015, at 18:10 PM, Ryan Weiss <rw3...@gmail.com> wrote:
> I thought maybe it was looping because the 'ReturnTo' parameter is the same as the origin link for testing the authsource:

No, the ReturnTo parameter tells SSP where to go back after successful authentication. If authentication succeeds, and everything goes fine, that very same URL will display your attributes instead of redirecting to start authentication. Which leads me to think that your configuration is broken with regard to the session.

What session handler are you using? Cookies configuration?

the 'store.type' was set to 'phpsession', so I imagine it was using cookies. I changed it to 'sql' and configured the database, confirmed that it's working. Redirect loops still happens. Nothing is produced in the log file.

> Where the ReturnTo parameter is the same as the original link... so that kind of makes sense, but if I change the ReturnTo parameter to anything else (ie. www.google.com), it still falls into the redirect loop, but puts me on a new page/different url:
>
> http://weiss.dev2.rowanonline.com/simplesaml/module.php/core/as_login.php?AuthId=example-userpass&ReturnTo=http%3A%2F%2Fgoogle.com

An open redirection to an external domain is a vulnerability that you should shut down (look at the ‘trusted.url.domains’ configuration option in config.php).

In any case, this is quite difficult to debug with any traces at all. You need to get your logs working first, as debugging without them will be a nightmare. What’s your log-related configuration? Handler, file, level, etc?
 
 Config is set to:
    'logging.level' => SimpleSAML_Logger::NOTICE,
    'logging.handler' => 'file',

 Permissions on the log directory are set to '777'. Logging does work, just not in this scenario. 


Secondly, in order to debug redirections from one page to another, you should be tracking all of them. Install the SAML tracer Firefox extension and enable it while testing. You will be able to see all the HTTP requests and responses, as well as the SAML messages involved.

OK, I did this. Here is what happens when I try to hit the exampleauth-userpass authsource:

Host: weiss.dev2.rowanonline.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:40.0) Gecko/20100101 Firefox/40.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://weiss.dev2.rowanonline.com/simplesaml/module.php/core/authenticate.php
Cookie: SimpleSAMLSessionID=623f232557fa446afea6b7fb85cae3ff
Authorization: Basic d2Vpc3M6Z3VtZHJvcDQ5

HTTP/?.? 302 Found
Server: Apache/2.2.15 (CentOS)
X-Powered-By: PHP/5.5.26
Set-Cookie: SimpleSAMLSessionID=0b5879b1e3d29446b1a39a199056a175; path=/; httponly
SimpleSAMLSessionID=3ecd15bd758ef62ada62d249e2ba187f; path=/; httponly
Location: http://weiss.dev2.rowanonline.com/simplesaml/module.php/core/loginuserpass.php?AuthState=_619639ae7bd5574fad11cedd68794dc03986fce640%3Ahttp%3A%2F%2Fweiss.dev2.rowanonline.com%2Fsimplesaml%2Fmodule.php%2Fcore%2Fas_login.php%3FAuthId%3Dexample-userpass%26ReturnTo%3Dhttp%253A%252F%252Fweiss.dev2.rowanonline.com%252Fsimplesaml%252Fmodule.php%252Fcore%252Fauthenticate.php%253Fas%253Dexample-userpass
Pragma: no-cache
Cache-Control: no-cache, must-revalidate
Content-Type: text/html; charset=UTF-8
Content-Length: 1289
Accept-Ranges: bytes
Date: Wed, 18 Nov 2015 22:34:58 GMT
X-Varnish: 471250550
Age: 0
Via: 1.1 varnish
Connection: keep-alive
X-Varnish-Cache: MISS


This then redirects to this page:
GET http://weiss.dev2.rowanonline.com/simplesaml/module.php/core/loginuserpass.php?AuthState=_619639ae7bd5574fad11cedd68794dc03986fce640%3Ahttp%3A%2F%2Fweiss.dev2.rowanonline.com%2Fsimplesaml%2Fmodule.php%2Fcore%2Fas_login.php%3FAuthId%3Dexample-userpass%26ReturnTo%3Dhttp%253A%252F%252Fweiss.dev2.rowanonline.com%252Fsimplesaml%252Fmodule.php%252Fcore%252Fauthenticate.php%253Fas%253Dexample-userpass HTTP/1.1
Host: weiss.dev2.rowanonline.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:40.0) Gecko/20100101 Firefox/40.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://weiss.dev2.rowanonline.com/simplesaml/module.php/core/authenticate.php
Cookie: SimpleSAMLSessionID=3ecd15bd758ef62ada62d249e2ba187f
Authorization: Basic d2Vpc3M6Z3VtZHJvcDQ5

HTTP/?.? 302 Found
Server: Apache/2.2.15 (CentOS)
X-Powered-By: PHP/5.5.26
Set-Cookie: SimpleSAMLSessionID=864d3b69992eaa67bddf02dd948e4a1c; path=/; httponly
SimpleSAMLSessionID=d699a30fbeef36fc5f5c3e56da311da2; path=/; httponly
Location: http://weiss.dev2.rowanonline.com/simplesaml/module.php/core/as_login.php?AuthId=example-userpass&ReturnTo=http%3A%2F%2Fweiss.dev2.rowanonline.com%2Fsimplesaml%2Fmodule.php%2Fcore%2Fauthenticate.php%3Fas%3Dexample-userpass
Pragma: no-cache
Cache-Control: no-cache, must-revalidate
Content-Type: text/html; charset=UTF-8
Content-Length: 947
Accept-Ranges: bytes
Date: Wed, 18 Nov 2015 22:34:58 GMT
X-Varnish: 471250551
Age: 0
Via: 1.1 varnish
Connection: keep-alive
X-Varnish-Cache: MISS


And then that redirects to:

GET http://weiss.dev2.rowanonline.com/simplesaml/module.php/core/as_login.php?AuthId=example-userpass&ReturnTo=http%3A%2F%2Fweiss.dev2.rowanonline.com%2Fsimplesaml%2Fmodule.php%2Fcore%2Fauthenticate.php%3Fas%3Dexample-userpass HTTP/1.1
Host: weiss.dev2.rowanonline.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:40.0) Gecko/20100101 Firefox/40.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://weiss.dev2.rowanonline.com/simplesaml/module.php/core/authenticate.php
Cookie: SimpleSAMLSessionID=d699a30fbeef36fc5f5c3e56da311da2
Authorization: Basic d2Vpc3M6Z3VtZHJvcDQ5

HTTP/?.? 302 Found
Server: Apache/2.2.15 (CentOS)
X-Powered-By: PHP/5.5.26
Set-Cookie: SimpleSAMLSessionID=19c4c0d626d98ca56accce1af41f3db5; path=/; httponly
SimpleSAMLSessionID=d2f2e110e0613825b8351662722d2f8a; path=/; httponly
Location: http://weiss.dev2.rowanonline.com/simplesaml/module.php/core/loginuserpass.php?AuthState=_875177fd517730b6e35cb7c02d4173af7653a7fd4d%3Ahttp%3A%2F%2Fweiss.dev2.rowanonline.com%2Fsimplesaml%2Fmodule.php%2Fcore%2Fas_login.php%3FAuthId%3Dexample-userpass%26ReturnTo%3Dhttp%253A%252F%252Fweiss.dev2.rowanonline.com%252Fsimplesaml%252Fmodule.php%252Fcore%252Fauthenticate.php%253Fas%253Dexample-userpass
Pragma: no-cache
Cache-Control: no-cache, must-revalidate
Content-Type: text/html; charset=UTF-8
Content-Length: 1289
Accept-Ranges: bytes
Date: Wed, 18 Nov 2015 22:34:58 GMT
X-Varnish: 471250552
Age: 0
Via: 1.1 varnish
Connection: keep-alive
X-Varnish-Cache: MISS
And then it just bounces back and forth between loginuserpass.php and as_login.php

Hmm, I guess this might have to do with the 302... will look into that a bit.

Thanks, Jaime.

Ryan Weiss

unread,
Nov 26, 2015, 3:03:37 PM11/26/15
to SimpleSAMLphp
A few updates... trying to determine why the session is invalid. I got some logging working in regards to the redirect (had to change logginglevel to 'debug'). I also some of my own debugging in here (the numbers are line numbers of the file):

Nov 26 14:44:03 simplesamlphp NOTICE [0348289a33] core/authenticate.php
Nov 26 14:44:03 simplesamlphp NOTICE [0348289a33] 26Auth/Simple.php __constructor()
Nov 26 14:44:03 simplesamlphp NOTICE [0348289a33] 19 - Authsource instance:
Nov 26 14:44:03 simplesamlphp NOTICE [0348289a33] 1
Nov 26 14:44:03 simplesamlphp NOTICE [0348289a33] 55 - found a session 1
Nov 26 14:44:03 simplesamlphp NOTICE [0348289a33] 660 SimpleSAML_Session::isValid()
Nov 26 14:44:03 simplesamlphp NOTICE [0348289a33] 664 Session not valid because we're not authenticated
Nov 26 14:44:03 simplesamlphp DEBUG [0348289a33] Session: 'example-userpass' not valid because we are not authenticated.
Nov 26 14:57:58 simplesamlphp DEBUG [8e14b21397] $authData array, size: 0 
Nov 26 14:44:03 simplesamlphp NOTICE [0348289a33] 61 SESSION NOT VALID
Nov 26 14:44:03 simplesamlphp NOTICE [0348289a33] 51 - authenticate.php: NOT authenticated..., return to: http://weiss.dev2.rowanonline.com/simplesaml/module.php/core/authenticate.php?as=example-userpass
Nov 26 14:44:03 simplesamlphp DEBUG [0348289a33] Saved state: '_bb469310611d33f2e1b5e8974fc1684d641c6618cc:http://weiss.dev2.rowanonline.com/simplesaml/module.php/core/as_login.php?AuthId=example-userpass&ReturnTo=http%3A%2F%2Fweiss.dev2.rowanonline.com%2Fsimplesaml%2Fmodule.php%2Fcore%2Fauthenticate.php%3Fas%3Dexample-userpass'
Nov 26 14:44:03 simplesamlphp DEBUG [b97166a2c7] Loading state: '_bb469310611d33f2e1b5e8974fc1684d641c6618cc:http://weiss.dev2.rowanonline.com/simplesaml/module.php/core/as_login.php?AuthId=example-userpass&ReturnTo=http%3A%2F%2Fweiss.dev2.rowanonline.com%2Fsimplesaml%2Fmodule.php%2Fcore%2Fauthenticate.php%3Fas%3Dexample-userpass'
Nov 26 14:44:03 simplesamlphp NOTICE [c4c093b446] 26Auth/Simple.php __constructor()
Nov 26 14:44:03 simplesamlphp NOTICE [c4c093b446] 660 SimpleSAML_Session::isValid()
Nov 26 14:44:03 simplesamlphp NOTICE [c4c093b446] 664 Session not valid because we're not authenticated
Nov 26 14:44:03 simplesamlphp DEBUG [c4c093b446] Session: 'example-userpass' not valid because we are not authenticated.
Nov 26 14:57:58 simplesamlphp DEBUG [8e14b21397] $authData array, size: 0 
Nov 26 14:44:03 simplesamlphp DEBUG [c4c093b446] Saved state: '_78f8732bb6a72ca102c9507561edbc6ea61f536694:http://weiss.dev2.rowanonline.com/simplesaml/module.php/core/as_login.php?AuthId=example-userpass&ReturnTo=http%3A%2F%2Fweiss.dev2.rowanonline.com%2Fsimplesaml%2Fmodule.php%2Fcore%2Fauthenticate.php%3Fas%3Dexample-userpass'
Nov 26 14:44:03 simplesamlphp DEBUG [52ce85532c] Loading state: '_78f8732bb6a72ca102c9507561edbc6ea61f536694:http://weiss.dev2.rowanonline.com/simplesaml/module.php/core/as_login.php?AuthId=example-userpass&ReturnTo=http%3A%2F%2Fweiss.dev2.rowanonline.com%2Fsimplesaml%2Fmodule.php%2Fcore%2Fauthenticate.php%3Fas%3Dexample-userpass'
Nov 26 14:44:03 simplesamlphp NOTICE [a5fe8d7832] 26Auth/Simple.php __constructor()
Nov 26 14:44:03 simplesamlphp NOTICE [a5fe8d7832] 660 SimpleSAML_Session::isValid()
Nov 26 14:44:03 simplesamlphp NOTICE [a5fe8d7832] 664 Session not valid because we're not authenticated
Nov 26 14:44:03 simplesamlphp DEBUG [a5fe8d7832] Session: 'example-userpass' not valid because we are not authenticated.
Nov 26 14:57:58 simplesamlphp DEBUG [8e14b21397] $authData array, size: 0 
Nov 26 14:44:03 simplesamlphp DEBUG [a5fe8d7832] Saved state: '_e5de2bb80c6f3fccfcf9f4805fed8b4d0064bdf2d8:http://weiss.dev2.rowanonline.com/simplesaml/module.php/core/as_login.php?AuthId=example-userpass&ReturnTo=http%3A%2F%2Fweiss.dev2.rowanonline.com%2Fsimplesaml%2Fmodule.php%2Fcore%2Fauthenticate.php%3Fas%3Dexample-userpass'

It looks like this is failing because the local $authData array in the SimpleSAML_Session class isn't being populated before the isValid($authSource) is called. Specifically it fails this check: 
if (!isset($this->authData[$authority])) { //returns false from isValid() };

Anyone have any ideas why the authData wouldn't be populated?
My authsources.php has three entries (config removed for brevity):

$config = array(
   
'admin' => array(//config...),
   
'example-userpass' => array(//config...),
   
'drupalauth' => array(//config...)
);

And also, if it matters, the 'SimpleSAMLSessionID cookie is set in my browser during this request. Sessions seem to be persisting.
If anyone has any ideas it would be very helpful. I'll continue to dive into the issue myself.

Thanks,
Ryan

Ryan Weiss

unread,
Nov 28, 2015, 5:09:30 PM11/28/15
to SimpleSAMLphp
So if anyone's still following along...

I hacked together some of the SimpleSAMLPhp lib files to be able to get the authsources properly loaded into the authData array. Seems like I got that part working, but it's now giving this error when I attempt to authenticate with the example-userpass example:
Notice: Undefined index: Expire in /var/www/weiss.dev2.rowanonline.com/webroot/simplesamlphp/lib/SimpleSAML/Session.php on line 696

If I go ahead and add the 'Expire' attribute to the example-userpass authsource, that goes away, but then upon trying to authenticate, it leaves me with this error:

SimpleSAML_Error_Error: UNHANDLEDEXCEPTION
Backtrace:
0 /var/www/weiss.dev2.rowanonline.com/webroot/simplesamlphp/www/module.php:179 (N/A)
Caused by: Exception: Invalid <username>:<password> for authentication source example-userpass: Expire
Backtrace:
6 /var/www/weiss.dev2.rowanonline.com/webroot/simplesamlphp/modules/exampleauth/lib/Auth/Source/UserPass.php:46 (sspmod_exampleauth_Auth_Source_UserPass::__construct)
5 /var/www/weiss.dev2.rowanonline.com/webroot/simplesamlphp/lib/SimpleSAML/Auth/Source.php:224 (SimpleSAML_Auth_Source::parseAuthSource)
4 /var/www/weiss.dev2.rowanonline.com/webroot/simplesamlphp/lib/SimpleSAML/Auth/Source.php:263 (SimpleSAML_Auth_Source::getById)
    'example-userpass' => array(
       
'exampleauth:UserPass',

       
'student:studentpass' => array(
           
'uid' => array('test'),
           
'eduPersonAffiliation' => array('member', 'student'),
       
),
       
'employee:employeepass' => array(
           
'uid' => array('employee'),
           
'eduPersonAffiliation' => array('member', 'employee'),
       
),

       
'Expire' => 60*60
   
),

If I move the 'Expire' attriute into the array of the student:studentpass, and employee:employeepass entries, then try again, I get this error:

SimpleSAML_Error_Error: UNHANDLEDEXCEPTION
Backtrace:
0 /var/www/weiss.dev2.rowanonline.com/webroot/simplesamlphp/www/module.php:179 (N/A)
Caused by: Exception: Invalid attributes for user student in authentication source example-userpass: Invalid attribute value for attribute Expire: 60
Backtrace:
6 /var/www/weiss.dev2.rowanonline.com/webroot/simplesamlphp/modules/exampleauth/lib/Auth/Source/UserPass.php:59 (sspmod_exampleauth_Auth_Source_UserPass::__construct)
5 /var/www/weiss.dev2.rowanonline.com/webroot/simplesamlphp/lib/SimpleSAML/Auth/Source.php:224 (SimpleSAML_Auth_Source::parseAuthSource)
4 /var/www/weiss.dev2.rowanonline.com/webroot/simplesamlphp/lib/SimpleSAML/Auth/Source.php:263 (SimpleSAML_Auth_Source::getById)

So I don't know. I've about had it with this library. After a clean installation, it can't give me any proper error for why the simple example-userpass authentication source test won't work. It just gets stuck in a redirect loop because it can't find a session, as mentioned before, and it can't seem to find a session because the authData doesn't seem to be populated with the authsources, or anything for that matter. I've got all my session config setup properly, have tried cookies, database, both work, tried to chmod 777 the entire simplesamlphp folder. Nothing seems to be working. 

If anyone has any worthwhile ideas, I'll mail you some beer.
Reply all
Reply to author
Forward
0 new messages
Search
Clear search
Close search
Google apps
Main menu