# AuthStack Connector Framework 

Consumer service for AuthStack SAML 2.0 assertions

## Installation


### Step #1
Add Buckhill's satis to your `composer.json`

```
"repositories": [
  { "type": "composer", "url": "https://satis.buckhill.co.uk" }
]
```


### Step #2
Add `"buckhill/laravel-5.1-saml-sp": "*"` into `composer.json` or `composer require "buckhill/laravel-5.1-saml-sp: "*"`

### Step #3

Create `config/sso.php` file. Use the file located in `samples/sp_config.php` and adjust it accordingly.

Make sure you adjust the config data properly - look at values like `baseUrl`, `entityID` and the metadata of the IDP you're connecting to. You will need to read your IDP's metadata and fill out it's entityID, x509 and the SSO/SLO enpoints in the config file.

You will need to fill out the 'keys' with valid x.509 certificate data.

You can generate a certificate using the following command in a bash shell:

`openssl req -newkey rsa:2048 -new -x509 -days 3652 -nodes -out example.org.crt -keyout example.org.pem`

The public key is entered as a string value, without the `-----BEGIN CERTIFICATE-----` and `-----END CERTIFICATE-----` part.

Example:

```php
<?php

'x509' => 'MIIDXTCCAkWgAwIBAgIJAOjtFEt6oX//MA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV

lQ==',

```

The private key needs to be completely loaded (including `-----BEGIN PRIVATE KEY-----` and `-----END PRIVATE KEY------`) parts, the easiest way is to copy the entire .pem file and include it into the config like so (to avoid any character escaping issues):

```php
<?php
'private' => <<<EOF
-----BEGIN PRIVATE KEY-----

SewoVQXnCrOkG9i/Uj2SHQg=
-----END PRIVATE KEY-----

EOF
,
```


### Step #4

Open `config/app.php` and add the following to `providers` array:

```
'providers' => [
    Buckhill\LaravelSAML\Providers\AuthenticatedUserProvider::class,
    Buckhill\LaravelSAML\Providers\SAMLRoutesProvider::class,
]
```

### Step #5

If everything is setup/configured correctly, you will now have the following routes available:

`{base_url}/sso/saml2.0/metadata.xml` - shows your SP metadata (try changing config values - keys, SP entity ID etc to see changes to the metadata)

`{base_url}/sso/saml2.0/authenticate` - starts the authentication flow (redirects to IDP if configured properly)

`{base_url}/sso/saml2.0/acs` - assertion consumer service endpoint (incoming SAML requests from the IDP end up here)


### Step #6

How to modify the behavior after the assertion consumer service finishes its job:

You can specify a different route / controller for ACS:

- open `config/sso.php` 
- find `SP.routes` key
- look for `SP.routes.acs` and change the path to controller. Default one is `Buckhill\LaravelSAML\Http\Controllers\SSO`
- Create your controller in `App\Http\Controllers` and `extend` the default controller

Example on how to communicate to Buckhill's own Customer Service with extended ACS:

```php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use function AuthStack\SP\authn;
use Illuminate\Support\Facades\Log;
use AuthStack\SP\AttributeCollection;
use Buckhill\CustomerServerClient\Facade\CustomerServer;
use Buckhill\LaravelSAML\Http\Controllers\SSO as SSOController;

class SSO extends SSOController
{
    /**
     * @param Request $request
     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
     */
    public function acs(Request $request)
    {
        return parent::acs($request);
    }

    /**
     * @param Request $request
     * @param AttributeCollection $collection
     */
    protected function afterACS(Request $request, AttributeCollection $collection)
    {
        $data = [
            'type_id'           => 3,
            'signup_id'         => 1,
            'social_id'         => $collection->getNameIdValue(),
            'email'             => $collection->getNameIdValue(),
            'full_name'         => sprintf("%s %s", $collection->get('givenname')->getFirstAttributeValue(), $collection->get('sn')->getFirstAttributeValue()),
            'additional'        => [
                'organization'      => $collection->get('o')->getFirstAttributeValue(),
                'country'           => $collection->get('st')->getFirstAttributeValue(),
                'city'              => $collection->get('l')->getFirstAttributeValue(),
                'postalCode'        => $collection->get('postalcode')->getFirstAttributeValue(),
                'postaladdress'     => $collection->get('postaladdress')->getFirstAttributeValue(),
                'tel'               => $collection->get('telephonenumber')->getFirstAttributeValue()
            ]
        ];

        Log::info("SAML response returned", ['request' => $request->all()]);

        /** @var  $customer \Buckhill\CustomerServerClient\Model\Customer */
        $customer = CustomerServer::retrieve($data);

        $request->session()->put('profile', $customer->toArray());

        session()->put(config('sso.SP.sessionKeyName'), $customer->toArray());
    }
}

```

### Step #7

Add custom route filtering if you need SAML protected routes.

You can do this via the available `\Buckhill\LaravelSAML\Http\Middleware\Authenticated` middleware, which will allow access only with a valid SAML session.

If you will be forwarding the SAML session (checking the received attributes and creating/loggin in users via your applications user system as per the attributes) you probably won't need this - just check the attributes and let your user system assume control from there in the appropriate place (most probably afterACS function in a controller that will extend the provided SSO controller).
