SandStorm is a cool solution to host simple web services and let users use them easily. It can be installed with a few commands, but still has an issue that bothered me: it is not possible to have a publicly accessible instance, as all of the involved login methods imply some kind of explicit authorization or explicit invitation from the administrator.

The only viable way I've found to publish a public SandStorm instance has been to setup a SAML Identity Provider, implement there new users' registration flow, and activate that specific source as always enabled to access the platform. So, the whole users management happens outside SandStorm and can be implemented as preferred.

Here, some tips and trick to reply the setup.

First of all, let's setup the basic SimpleSamlPHP instance. This tutorial is a good starting point, please begin from here.

A few tips:

  • remember to execute composer install on the root SimpleSamlPHP folder before to proceed further. It is not explicitely reccomended, but without this it will not find the classes required for login
  • get a look to this page and edit the www/_include.php file if the application laments some missing file
  • keep in mind to create the certificates to sign responses. This page suggests to call them saml.crt and saml.pem: ignore it, the default names are server.crt and server.pem
  • get a look to metadata/saml20-idp-hosted.php, it includes some configurations which may be useful to understand what are you doing

Here, it begins the SandStorm-related configuration. And the fuck.

Install and setup this module. It permits to generate users' SAML attributes directly from the database, and attach the email and displayName required by SandStorm.

composer require safire-ac-za/simplesamlphp-module-sqlattribs:dev-master

It requires a database table (called below AttributeFromSQL, as in the examples) where to store the attributes, one per record: get a look on the documentation to create and populate it.

Then edit config/authsources.php and drop the following lines:

'example-userpass' => array(
    'dsn' => 'mysql:host=localhost;port=5432;dbname=your_db_name',
    'username' => 'your_db_username',
    'password' => 'your_db_password',
    'query' => 'SELECT username FROM users WHERE username = :username AND AES_DECRYPT(password,"your_secret") = :password',

Pay attention to the your_secret string in the query: that would be useful when adding new users into the database, as the password would be crypted using that key.

Finally, edit metadata/saml20-sp-remote.php to specify the behaviour to keep when dealing with your SandStorm instance.

$metadata[''] = array(
    'AssertionConsumerService' => '',
    'SingleLogoutService' => '',

    'authproc' => array(
        2 => array(
            'class' => 'saml:PersistentNameID',
            'attribute' => 'username',
        50 => array(
            'class'     => 'sqlattribs:AttributeFromSQL',
            'attribute' => 'username',
            'limit'     => array('email', 'displayName', 'password'),
            'replace'   => true,
            'database'  => array(
                'dsn'       => 'mysql:host=localhost;dbname=your_db_name',
                'username'  => 'your_db_username',
                'password'  => 'your_db_password',
                'table'     => 'AttributeFromSQL',

Here you recognize a reference to the AttributeFromSQL previously created when adding the extra SimpleSamlPHP module. This is the magic configuration to provide SandStorm the SAML attributes it pretends.

Please note that "password" is among the involved attributes. It is due an unclear and untracker behaviour: starting at some point, the database module began to include also the "password" column from the "users" table (which is a binary value) and RSA signature of responses started to fail. So, for each user I've added a fake "password" attribute, left empty, and replaced from what is fetched from "users".

Finally: to customize the login page, edit modules/core/templates/loginuserpass.php.

Starting from here, you have all the elements to implement your own user registration, validation, password recovery flows. Keep in mind to properly store attributes in AttributeFromSQL.

Good luck. You need it.