• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..23-Oct-2020-

extlib/xmlseclibs/H23-Oct-2020-1,9471,619

lib/H23-Oct-2020-9,3226,555

CHANGELOGH A D22-Oct-202013.1 KiB255217

LICENSEH A D22-Oct-20201 KiB2419

README.mdH A D22-Oct-202068.7 KiB1,7041,283

_toolkit_loader.phpH A D22-Oct-2020611 2613

advanced_settings_example.phpH A D22-Oct-20206.3 KiB15158

compatibility.phpH A D22-Oct-2020346 137

composer.jsonH A D22-Oct-20201 KiB3837

settings_example.phpH A D22-Oct-20206.1 KiB13846

README.md

1# OneLogin's SAML PHP Toolkit
2
3[![Build Status](https://api.travis-ci.org/onelogin/php-saml.png?branch=master)](http://travis-ci.org/onelogin/php-saml) [![Coverage Status](https://coveralls.io/repos/onelogin/php-saml/badge.png)](https://coveralls.io/r/onelogin/php-saml) [![License](https://poser.pugx.org/onelogin/php-saml/license.png)](https://packagist.org/packages/onelogin/php-saml)
4
5Add SAML support to your PHP software using this library.
6Forget those complicated libraries and use this open source library provided
7and supported by OneLogin Inc.
8
9
10**The 3.X branch is compatible with PHP > 7.1, so if you are using that PHP version, use it and not the 2.X or the master branch**
11
12Warning
13-------
14
15Version 2.18.0 introduces the 'rejectUnsolicitedResponsesWithInResponseTo' setting parameter, by default disabled, that will allow invalidate unsolicited SAMLResponse. This version as well will reject SAMLResponse if requestId was provided to the validator but the SAMLResponse does not contain a InResponseTo attribute.  And an additional setting parameter 'destinationStrictlyMatches', by default disabled, that will force that the Destination URL should strictly match to the address that process the SAMLResponse.
16
17Version 2.17.1 updates xmlseclibs to 3.0.4 (CVE-2019-3465), but php-saml was not directly affected since it implements additional checks that prevent to exploit that vulnerability.
18
19Version 2.17.0 sets strict mode active by default
20
21Update php-saml to 2.15.0, this version includes a security patch related to XEE attacks
22
23php-saml is not affected by [201803-01](https://simplesamlphp.org/security/201803-01)
24
25Update php-saml to 2.10.4, this version includes a security patch related to
26[signature validations on LogoutRequests/LogoutResponses](https://github.com/onelogin/php-saml/commit/949359f5cad5e1d085c4e5447d9aa8f49a6e82a1)
27
28Update php-saml to 2.10.0, this version includes a security patch that contains extra validations that will prevent signature wrapping attacks. [CVE-2016-1000253](https://github.com/distributedweaknessfiling/DWF-Database-Artifacts/blob/ab8ae6e845eb506fbeb10a7e4ccb379f0b4222ca/DWF/2016/1000253/CVE-2016-1000253.json)
29
30php-saml < v2.10.0 is vulnerable and allows signature wrapping!
31
32
33Security Guidelines
34-------------------
35
36If you believe you have discovered a security vulnerability in this toolkit, please report it at https://www.onelogin.com/security with a description. We follow responsible disclosure guidelines, and will work with you to quickly find a resolution.
37
38
39Why add SAML support to my software?
40------------------------------------
41
42SAML is an XML-based standard for web browser single sign-on and is defined by
43the OASIS Security Services Technical Committee. The standard has been around
44since 2002, but lately it is becoming popular due its advantages:
45
46 * **Usability** - One-click access from portals or intranets, deep linking,
47   password elimination and automatically renewing sessions make life
48   easier for the user.
49 * **Security** - Based on strong digital signatures for authentication and
50   integrity, SAML is a secure single sign-on protocol that the largest
51   and most security conscious enterprises in the world rely on.
52 * **Speed** - SAML is fast. One browser redirect is all it takes to securely
53   sign a user into an application.
54 * **Phishing Prevention** - If you don’t have a password for an app, you
55   can’t be tricked into entering it on a fake login page.
56 * **IT Friendly** - SAML simplifies life for IT because it centralizes
57   authentication, provides greater visibility and makes directory
58   integration easier.
59 * **Opportunity** - B2B cloud vendor should support SAML to facilitate the
60   integration of their product.
61
62
63General description
64-------------------
65
66OneLogin's SAML PHP toolkit let you build a SP (Service Provider) over
67your PHP application and connect it to any IdP (Identity Provider).
68
69Supports:
70
71 * SSO and SLO (SP-Initiated and IdP-Initiated).
72 * Assertion and nameId encryption.
73 * Assertion signature.
74 * Message signature: AuthNRequest, LogoutRequest, LogoutResponses.
75 * Enable an Assertion Consumer Service endpoint.
76 * Enable a Single Logout Service endpoint.
77 * Publish the SP metadata (which can be signed).
78
79Key features:
80
81 * **saml2int** - Implements the SAML 2.0 Web Browser SSO Profile.
82 * **Session-less** - Forget those common conflicts between the SP and
83   the final app, the toolkit delegate session in the final app.
84 * **Easy to use** - Programmer will be allowed to code high-level and
85   low-level programming, 2 easy to use APIs are available.
86 * **Tested** - Thoroughly tested.
87 * **Popular** - OneLogin's customers use it. Many PHP SAML plugins uses it.
88
89Integrate your PHP toolkit at OneLogin using this guide: [https://developers.onelogin.com/page/saml-toolkit-for-php](https://developers.onelogin.com/page/saml-toolkit-for-php)
90
91Installation
92------------
93
94### Dependencies ###
95
96 * `php >= 5.3.3` and some core extensions like `php-xml`, `php-date`, `php-zlib`.
97 * `openssl`. Install the openssl library. It handles x509 certificates.
98 * `mcrypt`. Install that library and its php driver if you're going to handle
99   encrypted data (`nameID`, `assertions`).
100 * `gettext`. Install that library and its php driver. It handles translations.
101 * `curl`. Install that library and its php driver if you plan to use the IdP Metadata parser.
102
103Since [PHP 5.3 is officially unsupported](http://php.net/eol.php) we recommend you to use a newer PHP version.
104
105### Code ###
106
107#### Option 1. clone the repository from  github ####
108
109git clone git@github.com:onelogin/php-saml.git
110
111#### Option 2. Download from github ####
112
113The toolkit is hosted on github. You can download it from:
114
115 * Latest release: https://github.com/onelogin/php-saml/releases/latest
116 * Master repo: https://github.com/onelogin/php-saml/tree/master
117
118Copy the core of the library inside the php application. (each application has its
119structure so take your time to locate the PHP SAML toolkit in the best place).
120See the "Guide to add SAML support to my app" to know how.
121
122Take in mind that the compressed file only contains the main files.
123If you plan to play with the demos, use the Option 1.
124
125#### Option 3. Composer ####
126
127The toolkit supports [composer](https://getcomposer.org/). You can find the `onelogin/php-saml` package at https://packagist.org/packages/onelogin/php-saml
128
129In order to import the saml toolkit to your current php project, execute
130```
131composer require onelogin/php-saml
132```
133
134After installation has completed you will find at the `vendor/` folder a new folder named `onelogin` and inside the `php-saml`. Make sure you are including the autoloader provided by composer. It can be found at `vendor/autoload.php`.
135
136**Important** In this option, the x509 certs must be stored at `vendor/onelogin/php-saml/certs`
137and settings file stored at `vendor/onelogin/php-saml`.
138
139Your settings are at risk of being deleted when updating packages using `composer update` or similar commands. So it is **highly** recommended that instead of using settings files, you pass the settings as an array directly to the constructor (explained later in this document). If you do not use this approach your settings are at risk of being deleted when updating packages using `composer update` or similar commands.
140
141Compatibility
142-------------
143
144This 2.0 version has a new library. The toolkit is still compatible.
145
146The old code that you used in order to add SAML support will continue working
147with minor changes. You only need to load the files of the `lib/Saml` folder.
148(notice that the `compatibility.php` file do that).
149
150The old-demo folder contains code from an old app that uses the old version of
151the toolkit (v.1). Take a look.
152
153Sometimes the names of the classes of the old code could be a bit different
154and if that is your case you must change them for `OneLogin_Saml_Settings`,
155`OneLogin_Saml_Response`, `OneLogin_Saml_AuthRequest` or `OneLogin_Saml_Metadata`.
156
157We recommend that you migrate the old code to the new one to be able to use
158the new features that the new library Saml2 carries.
159
160
161Namespaces
162----------
163
164If you are using the library with a framework like Symfony that contains
165namespaces, remember that calls to the class must be done by adding a backslash (`\`) to the
166start, for example to use the static method getSelfURLNoQuery use:
167
168    \OneLogin_Saml2_Utils::getSelfURLNoQuery()
169
170
171Security warning
172----------------
173
174In production, the `strict` parameter **MUST** be set as `"true"` and the
175`signatureAlgorithm` and `digestAlgorithm` under `security` must be set to
176something other than SHA1 (see https://shattered.io/ ). Otherwise your
177environment is not secure and will be exposed to attacks.
178
179In production also we highly recommended to register on the settings the IdP certificate instead of using the fingerprint method. The fingerprint, is a hash, so at the end is open to a collision attack that can end on a signature validation bypass. Other SAML toolkits deprecated that mechanism, we maintain it for compatibility and also to be used on test environment.
180
181Getting started
182---------------
183
184### Knowing the toolkit ###
185
186The new OneLogin SAML Toolkit contains different folders (`certs`, `endpoints`,
187`extlib`, `lib`, `demo`, etc.) and some files.
188
189Let's start describing the folders:
190
191#### `certs/` ####
192
193SAML requires a x509 cert to sign and encrypt elements like `NameID`, `Message`,
194`Assertion`, `Metadata`.
195
196If our environment requires sign or encrypt support, this folder may contain
197the x509 cert and the private key that the SP will use:
198
199 * `sp.crt` - The public cert of the SP
200 * `sp.key` - The private key of the SP
201
202Or also we can provide those data in the setting file at the `$settings['sp']['x509cert']`
203and the `$settings['sp']['privateKey']`.
204
205Sometimes we could need a signature on the metadata published by the SP, in
206this case we could use the x509 cert previously mentioned or use a new x509
207cert: `metadata.crt` and `metadata.key`.
208
209Use `sp_new.crt` if you are in a key rollover process and you want to
210publish that x509 certificate on Service Provider metadata.
211
212#### `extlib/` ####
213
214This folder contains the 3rd party libraries that the toolkit uses. At the
215moment only uses the `xmlseclibs` (author Robert Richards, BSD Licensed) which
216handle the sign and the encryption of xml elements.
217
218
219#### `lib/` ####
220
221This folder contains the heart of the toolkit, the libraries:
222
223 * `Saml` folder contains a modified version of the toolkit v.1 and allows the
224   old code to keep working. (This library is provided to maintain
225   backward compatibility).
226 * `Saml2` folder contains the new version of the classes and methods that
227   are described in a later section.
228
229
230#### `doc/` ####
231
232This folder contains the API documentation of the toolkit.
233
234
235#### `endpoints/` ####
236
237The toolkit has three endpoints:
238
239 * `metadata.php` - Where the metadata of the SP is published.
240 * `acs.php` - Assertion Consumer Service. Processes the SAML Responses.
241 * `sls.php` - Single Logout Service. Processes Logout Requests and Logout
242   Responses.
243
244You can use the files provided by the toolkit or create your own endpoints
245files when adding SAML support to your applications. Take in mind that those
246endpoints files uses the setting file of the toolkit's base folder.
247
248
249#### `locale/` ####
250
251Locale folder contains some translations: `en_US` and `es_ES` as a proof of concept.
252Currently there are no translations but we will eventually localize the messages
253and support multiple languages.
254
255
256#### Other important files ####
257
258* `settings_example.php` - A template to be used in order to create a
259  settings.php file which contains the basic configuration info of the toolkit.
260* `advanced_settings_example.php` - A template to be used in order to create a
261  advanced_settings.php file which contains extra configuration info related to
262  the security, the contact person, and the organization associated to the SP.
263* `_toolkit_loader.php` - This file load the toolkit libraries (The SAML2 lib).
264* `compatibility` - Import that file to make compatible your old code with the
265  new toolkit (loads the SAML library).
266
267
268#### Miscellaneous ####
269
270* `tests/` - Contains the unit test of the toolkit.
271* `demo1/` - Contains an example of a simple PHP app with SAML support.
272  Read the `Readme.txt` inside for more info.
273* `demo2/` - Contains another example.
274* `demo-old/` - Contains an example that uses the code of the older version of the
275  the toolkit to demonstrate the backwards compatibility.
276
277
278### How it works ###
279
280#### Settings ####
281
282First of all we need to configure the toolkit. The SP's info, the IdP's info,
283and in some cases, configure advanced security issues like signatures and
284encryption.
285
286There are two ways to provide the settings information:
287
288 * Use a `settings.php` file that we should locate at the base folder of the
289   toolkit.
290 * Use an array with the setting data and provide it directly to the
291   constructor of the class.
292
293
294There is a template file, `settings_example.php`, so you can make a copy of this
295file, rename and edit it.
296
297```php
298<?php
299
300$settings = array (
301    // If 'strict' is True, then the PHP Toolkit will reject unsigned
302    // or unencrypted messages if it expects them to be signed or encrypted.
303    // Also it will reject the messages if the SAML standard is not strictly
304    // followed: Destination, NameId, Conditions ... are validated too.
305    'strict' => true,
306
307    // Enable debug mode (to print errors).
308    'debug' => false,
309
310    // Set a BaseURL to be used instead of try to guess
311    // the BaseURL of the view that process the SAML Message.
312    // Ex http://sp.example.com/
313    //    http://example.com/sp/
314    'baseurl' => null,
315
316    // Service Provider Data that we are deploying.
317    'sp' => array (
318        // Identifier of the SP entity  (must be a URI)
319        'entityId' => '',
320        // Specifies info about where and how the <AuthnResponse> message MUST be
321        // returned to the requester, in this case our SP.
322        'assertionConsumerService' => array (
323            // URL Location where the <Response> from the IdP will be returned
324            'url' => '',
325            // SAML protocol binding to be used when returning the <Response>
326            // message. OneLogin Toolkit supports this endpoint for the
327            // HTTP-POST binding only.
328            'binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST',
329        ),
330        // If you need to specify requested attributes, set a
331        // attributeConsumingService. nameFormat, attributeValue and
332        // friendlyName can be omitted
333        "attributeConsumingService"=> array(
334                "serviceName" => "SP test",
335                "serviceDescription" => "Test Service",
336                "requestedAttributes" => array(
337                    array(
338                        "name" => "",
339                        "isRequired" => false,
340                        "nameFormat" => "",
341                        "friendlyName" => "",
342                        "attributeValue" => array()
343                    )
344                )
345        ),
346        // Specifies info about where and how the <Logout Response> message MUST be
347        // returned to the requester, in this case our SP.
348        'singleLogoutService' => array (
349            // URL Location where the <Response> from the IdP will be returned
350            'url' => '',
351            // SAML protocol binding to be used when returning the <Response>
352            // message. OneLogin Toolkit supports the HTTP-Redirect binding
353            // only for this endpoint.
354            'binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect',
355        ),
356        // Specifies the constraints on the name identifier to be used to
357        // represent the requested subject.
358        // Take a look on lib/Saml2/Constants.php to see the NameIdFormat supported.
359        'NameIDFormat' => 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress',
360        // Usually x509cert and privateKey of the SP are provided by files placed at
361        // the certs folder. But we can also provide them with the following parameters
362        'x509cert' => '',
363        'privateKey' => '',
364
365        /*
366         * Key rollover
367         * If you plan to update the SP x509cert and privateKey
368         * you can define here the new x509cert and it will be
369         * published on the SP metadata so Identity Providers can
370         * read them and get ready for rollover.
371         */
372        // 'x509certNew' => '',
373    ),
374
375    // Identity Provider Data that we want connected with our SP.
376    'idp' => array (
377        // Identifier of the IdP entity  (must be a URI)
378        'entityId' => '',
379        // SSO endpoint info of the IdP. (Authentication Request protocol)
380        'singleSignOnService' => array (
381            // URL Target of the IdP where the Authentication Request Message
382            // will be sent.
383            'url' => '',
384            // SAML protocol binding to be used when returning the <Response>
385            // message. OneLogin Toolkit supports the HTTP-Redirect binding
386            // only for this endpoint.
387            'binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect',
388        ),
389        // SLO endpoint info of the IdP.
390        'singleLogoutService' => array (
391            // URL Location of the IdP where SLO Request will be sent.
392            'url' => '',
393            // URL location of the IdP where the SP will send the SLO Response (ResponseLocation)
394            // if not set, url for the SLO Request will be used
395            'responseUrl' => '',
396            // SAML protocol binding to be used when returning the <Response>
397            // message. OneLogin Toolkit supports the HTTP-Redirect binding
398            // only for this endpoint.
399            'binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect',
400        ),
401        // Public x509 certificate of the IdP
402        'x509cert' => '',
403        /*
404         *  Instead of use the whole x509cert you can use a fingerprint in order to
405         *  validate a SAMLResponse, but we don't recommend to use that
406         *  method on production since is exploitable by a collision attack.
407         *  (openssl x509 -noout -fingerprint -in "idp.crt" to generate it,
408         *   or add for example the -sha256 , -sha384 or -sha512 parameter)
409         *
410         *  If a fingerprint is provided, then the certFingerprintAlgorithm is required in order to
411         *  let the toolkit know which algorithm was used. Possible values: sha1, sha256, sha384 or sha512
412         *  'sha1' is the default value.
413         *
414         *  Notice that if you want to validate any SAML Message sent by the HTTP-Redirect binding, you
415         *  will need to provide the whole x509cert.
416         */
417        // 'certFingerprint' => '',
418        // 'certFingerprintAlgorithm' => 'sha1',
419
420        /* In some scenarios the IdP uses different certificates for
421         * signing/encryption, or is under key rollover phase and
422         * more than one certificate is published on IdP metadata.
423         * In order to handle that the toolkit offers that parameter.
424         * (when used, 'x509cert' and 'certFingerprint' values are
425         * ignored).
426         */
427        // 'x509certMulti' => array(
428        //      'signing' => array(
429        //          0 => '<cert1-string>',
430        //      ),
431        //      'encryption' => array(
432        //          0 => '<cert2-string>',
433        //      )
434        // ),
435    ),
436);
437```
438In addition to the required settings data (IdP, SP), there is extra
439information that could be defined. In the same way that a template exists
440for the basic info, there is a template for that advanced info located
441at the base folder of the toolkit and named `advanced_settings_example.php`
442that you can copy and rename it as `advanced_settings.php`
443
444```php
445<?php
446
447$advancedSettings = array (
448
449    // Compression settings
450    'compress' => array (
451        'requests' => true,
452        'responses' => true
453    ),
454    // Security settings
455    'security' => array (
456
457        /** signatures and encryptions offered */
458
459        // Indicates that the nameID of the <samlp:logoutRequest> sent by this SP
460        // will be encrypted.
461        'nameIdEncrypted' => false,
462
463        // Indicates whether the <samlp:AuthnRequest> messages sent by this SP
464        // will be signed.  [Metadata of the SP will offer this info]
465        'authnRequestsSigned' => false,
466
467        // Indicates whether the <samlp:logoutRequest> messages sent by this SP
468        // will be signed.
469        'logoutRequestSigned' => false,
470
471        // Indicates whether the <samlp:logoutResponse> messages sent by this SP
472        // will be signed.
473        'logoutResponseSigned' => false,
474
475        /* Sign the Metadata
476         False || True (use sp certs) || array (
477                                                    keyFileName => 'metadata.key',
478                                                    certFileName => 'metadata.crt'
479                                               )
480                                      || array (
481                                                    'x509cert' => '',
482                                                    'privateKey' => ''
483                                               )
484        */
485        'signMetadata' => false,
486
487        /** signatures and encryptions required **/
488
489        // Indicates a requirement for the <samlp:Response>, <samlp:LogoutRequest>
490        // and <samlp:LogoutResponse> elements received by this SP to be signed.
491        'wantMessagesSigned' => false,
492
493        // Indicates a requirement for the <saml:Assertion> elements received by
494        // this SP to be encrypted.
495        'wantAssertionsEncrypted' => false,
496
497        // Indicates a requirement for the <saml:Assertion> elements received by
498        // this SP to be signed. [Metadata of the SP will offer this info]
499        'wantAssertionsSigned' => false,
500
501        // Indicates a requirement for the NameID element on the SAMLResponse
502        // received by this SP to be present.
503        'wantNameId' => true,
504
505        // Indicates a requirement for the NameID received by
506        // this SP to be encrypted.
507        'wantNameIdEncrypted' => false,
508
509        // Authentication context.
510        // Set to false and no AuthContext will be sent in the AuthNRequest.
511        // Set true or don't present this parameter and you will get an AuthContext 'exact' 'urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport'.
512        // Set an array with the possible auth context values: array ('urn:oasis:names:tc:SAML:2.0:ac:classes:Password', 'urn:oasis:names:tc:SAML:2.0:ac:classes:X509').
513        'requestedAuthnContext' => true,
514
515        // Indicates if the SP will validate all received xmls.
516        // (In order to validate the xml, 'strict' and 'wantXMLValidation' must be true).
517        'wantXMLValidation' => true,
518
519        // If true, SAMLResponses with an empty value at its Destination
520        // attribute will not be rejected for this fact.
521        'relaxDestinationValidation' => false,
522
523        // If true, Destination URL should strictly match to the address to
524        // which the response has been sent.
525        // Notice that if 'relaxDestinationValidation' is true an empty Destintation
526        // will be accepted.
527        'destinationStrictlyMatches' => false,
528
529        // If true, SAMLResponses with an InResponseTo value will be rejectd if not
530        // AuthNRequest ID provided to the validation method.
531        'rejectUnsolicitedResponsesWithInResponseTo' => false,
532
533        // Algorithm that the toolkit will use on signing process. Options:
534        //    'http://www.w3.org/2000/09/xmldsig#rsa-sha1'
535        //    'http://www.w3.org/2000/09/xmldsig#dsa-sha1'
536        //    'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256'
537        //    'http://www.w3.org/2001/04/xmldsig-more#rsa-sha384'
538        //    'http://www.w3.org/2001/04/xmldsig-more#rsa-sha512'
539        // Notice that sha1 is a deprecated algorithm and should not be used
540        'signatureAlgorithm' => 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256',
541
542        // Algorithm that the toolkit will use on digest process. Options:
543        //    'http://www.w3.org/2000/09/xmldsig#sha1'
544        //    'http://www.w3.org/2001/04/xmlenc#sha256'
545        //    'http://www.w3.org/2001/04/xmldsig-more#sha384'
546        //    'http://www.w3.org/2001/04/xmlenc#sha512'
547        // Notice that sha1 is a deprecated algorithm and should not be used
548        'digestAlgorithm' => 'http://www.w3.org/2001/04/xmlenc#sha256',
549
550        // ADFS URL-Encodes SAML data as lowercase, and the toolkit by default uses
551        // uppercase. Turn it True for ADFS compatibility on signature verification
552        'lowercaseUrlencoding' => false,
553    ),
554
555    // Contact information template, it is recommended to supply a
556    // technical and support contacts.
557    'contactPerson' => array (
558        'technical' => array (
559            'givenName' => '',
560            'emailAddress' => ''
561        ),
562        'support' => array (
563            'givenName' => '',
564            'emailAddress' => ''
565        ),
566    ),
567
568    // Organization information template, the info in en_US lang is
569    // recomended, add more if required.
570    'organization' => array (
571        'en-US' => array(
572            'name' => '',
573            'displayname' => '',
574            'url' => ''
575        ),
576    ),
577);
578```
579
580The compression settings allow you to instruct whether or not the IdP can accept
581data that has been compressed using [gzip](gzip) ('requests' and 'responses').
582But if we provide a `$deflate` boolean parameter to the `getRequest` or `getResponse` method it will have priority over the compression settings.
583
584In the security section, you can set the way that the SP will handle the messages
585and assertions. Contact the admin of the IdP and ask him what the IdP expects,
586and decide what validations will handle the SP and what requirements the SP will have
587and communicate them to the IdP's admin too.
588
589Once we know what kind of data could be configured, let's talk about the way
590settings are handled within the toolkit.
591
592The settings files described (`settings.php` and `advanced_settings.php`) are loaded
593by the toolkit if no other array with settings info is provided in the constructor of the toolkit. Let's see some examples.
594
595```php
596// Initializes toolkit with settings.php & advanced_settings files.
597$auth = new OneLogin_Saml2_Auth();
598//or
599$settings = new OneLogin_Saml2_Settings();
600
601// Initializes toolkit with the array provided.
602$auth = new OneLogin_Saml2_Auth($settingsInfo);
603//or
604$settings = new OneLogin_Saml2_Settings($settingsInfo);
605```
606
607You can declare the `$settingsInfo` in the file that contains the constructor
608execution or locate them in any file and load the file in order to get the
609array available as we see in the following example:
610
611```php
612<?php
613
614require_once 'custom_settings.php';  // The custom_settings.php contains a
615                                     // $settingsInfo array.
616
617$auth = new OneLogin_Saml2_Auth($settingsInfo);
618```
619
620
621#### How load the library ####
622
623In order to use the toolkit library you need to import the `_toolkit_loader.php`
624file located on the base folder of the toolkit. You can load this file in this
625way:
626
627```php
628<?php
629
630define("TOOLKIT_PATH", '/var/www/php-saml/');
631require_once(TOOLKIT_PATH . '_toolkit_loader.php');
632```
633
634After that line we will be able to use the classes (and their methods) of the
635toolkit (because the external and the Saml2 libraries files are loaded).
636
637If you wrote the code of your SAML app for the version 1 of the PHP-SAML toolkit
638you will need to load the `compatibility.php`, file which loads the SAML library files,
639in addition to the the `_toolkit_loader.php`.
640
641That SAML library uses the new classes and methods of the latest version of the
642toolkits but maintain the old classes, methods, and workflow of the old process
643to accomplish the same things.
644
645We strongly recommend migrating your old code and use the new API of the
646new toolkit due there are a lot of new features that you can't handle with the
647old code.
648
649
650#### Initiate SSO ####
651
652In order to send an `AuthNRequest` to the IdP:
653
654```php
655<?php
656
657define("TOOLKIT_PATH", '/var/www/php-saml/');
658require_once(TOOLKIT_PATH . '_toolkit_loader.php');   // We load the SAML2 lib
659
660$auth = new OneLogin_Saml2_Auth(); // Constructor of the SP, loads settings.php
661                                   // and advanced_settings.php
662$auth->login();   // Method that sent the AuthNRequest
663```
664
665The `AuthNRequest` will be sent signed or unsigned based on the security info
666of the `advanced_settings.php` (`'authnRequestsSigned'`).
667
668
669The IdP will then return the SAML Response to the user's client. The client is then forwarded to the Attribute Consumer Service of the SP with this information. If we do not set a `'url'` param in the login method and we are using the default ACS provided by the toolkit (`endpoints/acs.php`), then the ACS endpoint will redirect the user to the file that launched the SSO request.
670
671We can set a `'returnTo'` url to change the workflow and redirect the user to the other PHP file.
672
673```php
674$newTargetUrl = 'http://example.com/consume2.php';
675$auth = new OneLogin_Saml2_Auth();
676$auth->login($newTargetUrl);
677```
678
679The login method can receive other six optional parameters:
680
681* `$parameters` - An array of parameters that will be added to the `GET` in the HTTP-Redirect.
682* `$forceAuthn` - When true the `AuthNRequest` will set the `ForceAuthn='true'`
683* `$isPassive` - When true the `AuthNRequest` will set the `Ispassive='true'`
684* `$strict` - True if we want to stay (returns the url string) False to redirect
685* `$setNameIdPolicy` - When true the AuthNRequest will set a nameIdPolicy element.
686* `$nameIdValueReq` - Indicates to the IdP the subject that should be authenticated.
687
688If a match on the future SAMLResponse ID and the AuthNRequest ID to be sent is required, that AuthNRequest ID must to be extracted and saved.
689
690```php
691$ssoBuiltUrl = $auth->login(null, array(), false, false, true);
692$_SESSION['AuthNRequestID'] = $auth->getLastRequestID();
693header('Pragma: no-cache');
694header('Cache-Control: no-cache, must-revalidate');
695header('Location: ' . $ssoBuiltUrl);
696exit();
697```
698
699#### The SP Endpoints ####
700
701Related to the SP there are three important views: The metadata view, the ACS view and the SLS view. The toolkit
702provides examples of those views in the endpoints directory.
703
704##### SP Metadata `endpoints/metadata.php` #####
705
706This code will provide the XML metadata file of our SP, based on the info that we provided in the settings files.
707
708```php
709<?php
710
711define("TOOLKIT_PATH", '/var/www/php-saml/');
712require_once dirname(TOOLKIT_PATH.'/_toolkit_loader.php';
713
714try {
715    $auth = new OneLogin_Saml2_Auth();
716    $settings = $auth->getSettings();
717    $metadata = $settings->getSPMetadata();
718    $errors = $settings->validateMetadata($metadata);
719    if (empty($errors)) {
720        header('Content-Type: text/xml');
721        echo $metadata;
722    } else {
723        throw new OneLogin_Saml2_Error(
724            'Invalid SP metadata: '.implode(', ', $errors),
725            OneLogin_Saml2_Error::METADATA_SP_INVALID
726        );
727    }
728} catch (Exception $e) {
729    echo $e->getMessage();
730}
731```
732The `getSPMetadata` will return the metadata signed or not based
733on the security info of the `advanced_settings.php` (`'signMetadata'`).
734
735Before the XML metadata is exposed, a check takes place to ensure
736that the info to be provided is valid.
737
738Instead of use the Auth object, you can directly use
739
740```php
741$settings = new OneLogin_Saml2_Settings($settingsInfo, true);
742```
743to get the settings object and with the true parameter we will avoid the IdP Settings validation.
744
745
746##### Attribute Consumer Service(ACS) `endpoints/acs.php` #####
747
748This code handles the SAML response that the IdP forwards to the SP through the user's client.
749
750```php
751<?php
752
753session_start();  // IMPORTANT: This is required in order to be able
754                  // to store the user data in the session.
755
756define("TOOLKIT_PATH", '/var/www/php-saml/');
757require_once dirname(TOOLKIT_PATH.'/_toolkit_loader.php';
758
759$auth = new OneLogin_Saml2_Auth();
760
761if (isset($_SESSION) && isset($_SESSION['AuthNRequestID'])) {
762    $requestID = $_SESSION['AuthNRequestID'];
763} else {
764    $requestID = null;
765}
766
767$auth->processResponse($requestID);
768unset($_SESSION['AuthNRequestID']);
769
770$errors = $auth->getErrors();
771
772if (!empty($errors)) {
773    echo '<p>', implode(', ', $errors), '</p>';
774    exit();
775}
776
777if (!$auth->isAuthenticated()) {
778    echo "<p>Not authenticated</p>";
779    exit();
780}
781
782$_SESSION['samlUserdata'] = $auth->getAttributes();
783$_SESSION['samlNameId'] = $auth->getNameId();
784$_SESSION['samlNameIdFormat'] = $auth->getNameIdFormat();
785$_SESSION['samlNameidNameQualifier'] = $auth->getNameIdNameQualifier();
786$_SESSION['samlNameidSPNameQualifier'] = $auth->getNameIdSPNameQualifier();
787$_SESSION['samlSessionIndex'] = $auth->getSessionIndex();
788
789if (isset($_POST['RelayState']) && OneLogin_Saml2_Utils::getSelfURL() != $_POST['RelayState']) {
790    $auth->redirectTo($_POST['RelayState']);
791}
792
793$attributes = $_SESSION['samlUserdata'];
794$nameId = $_SESSION['samlNameId'];
795
796echo '<h1>Identified user: '. htmlentities($nameId) .'</h1>';
797
798if (!empty($attributes)) {
799    echo '<h2>'._('User attributes:').'</h2>';
800    echo '<table><thead><th>'._('Name').'</th><th>'._('Values').'</th></thead><tbody>';
801    foreach ($attributes as $attributeName => $attributeValues) {
802        echo '<tr><td>' . htmlentities($attributeName) . '</td><td><ul>';
803        foreach ($attributeValues as $attributeValue) {
804            echo '<li>' . htmlentities($attributeValue) . '</li>';
805        }
806        echo '</ul></td></tr>';
807    }
808    echo '</tbody></table>';
809} else {
810    echo _('No attributes found.');
811}
812```
813
814The SAML response is processed and then checked that there are no errors.
815It also verifies that the user is authenticated and stored the userdata in session.
816
817At that point there are two possible alternatives:
818
819 1. If no `RelayState` is provided, we could show the user data in this view
820 or however we wanted.
821
822 2. If `RelayState` is provided, a redirection takes place.
823
824Notice that we saved the user data in the session before the redirection to
825have the user data available at the `RelayState` view.
826
827
828###### The `getAttributes` method ######
829
830In order to retrieve attributes we can use:
831
832```php
833$attributes = $auth->getAttributes();
834```
835
836With this method we get all the user data provided by the IdP in the Assertion
837of the SAML Response.
838
839If we execute ```print_r($attributes)``` we could get:
840
841```php
842Array
843(
844    [cn] => Array
845        (
846            [0] => John
847        )
848    [sn] => Array
849        (
850            [0] => Doe
851        )
852    [mail] => Array
853        (
854            [0] => john.doe@example.com
855        )
856    [groups] => Array
857        (
858            [0] => users
859            [1] => members
860        )
861)
862```
863
864Each attribute name can be used as an index into `$attributes` to obtain the value. Every attribute value
865is an array - a single-valued attribute is an array of a single element.
866
867
868The following code is equivalent:
869
870```php
871$attributes = $auth->getAttributes();
872print_r($attributes['cn']);
873```
874
875```php
876print_r($auth->getAttribute('cn'));
877```
878
879
880Before trying to get an attribute, check that the user is
881authenticated. If the user isn't authenticated or if there were
882no attributes in the SAML assertion, an empty array will be
883returned. For example, if we call to `getAttributes` before a
884`$auth->processResponse`, the `getAttributes()` will return an
885empty array.
886
887
888##### Single Logout Service (SLS) `endpoints/sls.php` #####
889
890This code handles the Logout Request and the Logout Responses.
891
892```php
893<?php
894
895session_start();  // IMPORTANT: This is required in order to be able
896                  // to close the user session.
897
898define("TOOLKIT_PATH", '/var/www/php-saml/');
899require_once dirname(TOOLKIT_PATH.'/_toolkit_loader.php';
900
901$auth = new OneLogin_Saml2_Auth();
902
903if (isset($_SESSION) && isset($_SESSION['LogoutRequestID'])) {
904    $requestID = $_SESSION['LogoutRequestID'];
905} else {
906    $requestID = null;
907}
908
909$auth->processSLO(false, $requestID);
910
911$errors = $auth->getErrors();
912
913if (empty($errors)) {
914    echo 'Sucessfully logged out';
915} else {
916    echo implode(', ', $errors);
917}
918```
919
920If the SLS endpoints receives a Logout Response, the response is
921validated and the session could be closed
922
923
924
925```php
926// part of the processSLO method
927
928$logoutResponse = new OneLogin_Saml2_LogoutResponse($this->_settings, $_GET['SAMLResponse']);
929if (!$logoutResponse->isValid($requestId)) {
930    $this->_errors[] = 'invalid_logout_response';
931} else if ($logoutResponse->getStatus() !== OneLogin_Saml2_Constants::STATUS_SUCCESS) {
932    $this->_errors[] = 'logout_not_success';
933} else {
934    if (!$keepLocalSession) {
935        OneLogin_Saml2_Utils::deleteLocalSession();
936    }
937}
938```
939
940If the SLS endpoints receives an Logout Request, the request is validated,
941the session is closed and a Logout Response is sent to the SLS endpoint of
942the IdP.
943
944```php
945// part of the processSLO method
946
947$decoded = base64_decode($_GET['SAMLRequest']);
948$request = gzinflate($decoded);
949if (!OneLogin_Saml2_LogoutRequest::isValid($this->_settings, $request)) {
950    $this->_errors[] = 'invalid_logout_request';
951} else {
952    if (!$keepLocalSession) {
953        OneLogin_Saml2_Utils::deleteLocalSession();
954    }
955
956    $inResponseTo = $request->id;
957    $responseBuilder = new OneLogin_Saml2_LogoutResponse($this->_settings);
958    $responseBuilder->build($inResponseTo);
959    $logoutResponse = $responseBuilder->getResponse();
960
961    $parameters = array('SAMLResponse' => $logoutResponse);
962    if (isset($_GET['RelayState'])) {
963        $parameters['RelayState'] = $_GET['RelayState'];
964    }
965
966    $security = $this->_settings->getSecurityData();
967    if (isset($security['logoutResponseSigned']) && $security['logoutResponseSigned']) {
968        $signature = $this->buildResponseSignature($logoutResponse, $parameters['RelayState'], $security['signatureAlgorithm']);
969        $parameters['SigAlg'] = $security['signatureAlgorithm'];
970        $parameters['Signature'] = $signature;
971    }
972
973    $this->redirectTo($this->getSLOurl(), $parameters);
974}
975```
976
977If you aren't using the default PHP session, or otherwise need a manual
978way to destroy the session, you can pass a callback method to the
979`processSLO` method as the fourth parameter
980
981```php
982$keepLocalSession = False;
983$callback = function () {
984    // Destroy user session
985};
986
987$auth->processSLO($keepLocalSession, null, false, $callback);
988```
989
990
991If we don't want that `processSLO` to destroy the session, pass a true
992parameter to the `processSLO` method
993
994```php
995$keepLocalSession = True;
996$auth->processSLO($keepLocalSession);
997```
998
999#### Initiate SLO ####
1000
1001In order to send a Logout Request to the IdP:
1002
1003```php
1004<?php
1005
1006define("TOOLKIT_PATH", '/var/www/php-saml/');
1007require_once(TOOLKIT_PATH . '_toolkit_loader.php');
1008
1009$auth = new OneLogin_Saml2_Auth();
1010
1011$auth->logout();   // Method that sent the Logout Request.
1012```
1013
1014Also there are eight optional parameters that can be set:
1015* `$returnTo` - The target URL the user should be returned to after logout.
1016* `$parameters` - Extra parameters to be added to the GET.
1017* `$name_id` - That will be used to build the LogoutRequest. If `name_id` parameter is not set and the auth object processed a
1018SAML Response with a `NameId`, then this `NameId` will be used.
1019* `$session_index` - SessionIndex that identifies the session of the user.
1020* `$stay` - True if we want to stay (returns the url string) False to redirect.
1021* `$nameIdFormat` - The NameID Format will be set in the LogoutRequest.
1022* `$nameIdNameQualifier` - The NameID NameQualifier will be set in the LogoutRequest.
1023* `$nameIdSPNameQualifier` - The NameID SP NameQualifier will be set in the LogoutRequest.
1024
1025The Logout Request will be sent signed or unsigned based on the security
1026info of the `advanced_settings.php` (`'logoutRequestSigned'`).
1027
1028The IdP will return the Logout Response through the user's client to the
1029Single Logout Service of the SP.
1030If we do not set a `'url'` param in the logout method and are using the
1031default SLS provided by the toolkit (`endpoints/sls.php`), then the SLS
1032endpoint will redirect the user to the file that launched the SLO request.
1033
1034We can set an `'returnTo'` url to change the workflow and redirect the user
1035to other php file.
1036
1037```php
1038$newTargetUrl = 'http://example.com/loggedOut.php';
1039$auth = new OneLogin_Saml2_Auth();
1040$auth->logout($newTargetUrl);
1041```
1042A more complex logout with all the parameters:
1043```
1044$auth = new OneLogin_Saml2_Auth();
1045$returnTo = null;
1046$paramters = array();
1047$nameId = null;
1048$sessionIndex = null;
1049$nameIdFormat = null;
1050$nameIdNameQualifier = null;
1051$nameIdSPNameQualifier = null;
1052
1053if (isset($_SESSION['samlNameId'])) {
1054    $nameId = $_SESSION['samlNameId'];
1055}
1056if (isset($_SESSION['samlSessionIndex'])) {
1057    $sessionIndex = $_SESSION['samlSessionIndex'];
1058}
1059if (isset($_SESSION['samlNameIdFormat'])) {
1060    $nameIdFormat = $_SESSION['samlNameIdFormat'];
1061}
1062if (isset($_SESSION['samlNameIdNameQualifier'])) {
1063    $nameIdNameQualifier = $_SESSION['samlNameIdNameQualifier'];
1064}
1065if (isset($_SESSION['samlNameIdSPNameQualifier'])) {
1066    $nameIdSPNameQualifier = $_SESSION['samlNameIdSPNameQualifier'];
1067}
1068$auth->logout($returnTo, $paramters, $nameId, $sessionIndex, false, $nameIdFormat, $nameIdNameQualifier, $nameIdSPNameQualifier);
1069```
1070
1071If a match on the future LogoutResponse ID and the LogoutRequest ID to be sent is required, that LogoutRequest ID must to be extracted and stored.
1072
1073```php
1074$sloBuiltUrl = $auth->logout(null, $paramters, $nameId, $sessionIndex, true);
1075$_SESSION['LogoutRequestID'] = $auth->getLastRequestID();
1076header('Pragma: no-cache');
1077header('Cache-Control: no-cache, must-revalidate');
1078header('Location: ' . $sloBuiltUrl);
1079exit();
1080```
1081
1082#### Example of a view that initiates the SSO request and handles the response (is the acs target) ####
1083
1084We can code a unique file that initiates the SSO process, handle the response, get the attributes, initiate
1085the SLO and processes the logout response.
1086
1087Note: Review the `demo1` folder that contains that use case; in a later section we
1088explain the demo1 use case further in detail.
1089
1090```php
1091<?php
1092
1093session_start();    // Initialize the session, we do that because
1094                    // Note that processResponse and processSLO
1095                    // methods could manipulate/close that session
1096
1097require_once dirname(__DIR__).'/_toolkit_loader.php'; // Load Saml2 and external libs
1098require_once 'settings.php';    // Load the setting info as an Array
1099
1100$auth = new OneLogin_Saml2_Auth($settingsInfo);  // Initialize the SP SAML instance
1101
1102if (isset($_GET['sso'])) {    // SSO action.  Will send an AuthNRequest to the IdP
1103    $auth->login();
1104} else if (isset($_GET['sso2'])) {              // Another SSO action
1105    $returnTo = $spBaseUrl.'/demo1/attrs.php';  // but set a custom RelayState URL
1106    $auth->login($returnTo);
1107} else if (isset($_GET['slo'])) {  // SLO action. Will sent a Logout Request to IdP
1108    $auth->logout();
1109} else if (isset($_GET['acs'])) {  // Assertion Consumer Service
1110    $auth->processResponse();      // Process the Response of the IdP, get the
1111                                   // attributes and put then at
1112                                   // $_SESSION['samlUserdata']
1113
1114    $errors = $auth->getErrors();  // This method receives an array with the errors
1115                                   // that could took place during the process
1116
1117    if (!empty($errors)) {
1118        echo '<p>', implode(', ', $errors), '</p>';
1119    }
1120                                          // This check if the response was
1121    if (!$auth->isAuthenticated()) {      // sucessfully validated and the user
1122        echo "<p>Not authenticated</p>";  // data retrieved or not
1123        exit();
1124    }
1125
1126    $_SESSION['samlUserdata'] = $auth->getAttributes(); // Retrieves user data
1127    if (isset($_POST['RelayState']) && OneLogin_Saml2_Utils::getSelfURL() != $_POST['RelayState']) {
1128        $auth->redirectTo($_POST['RelayState']);  // Redirect if there is a
1129    }                                             // relayState set
1130} else if (isset($_GET['sls'])) {   // Single Logout Service
1131    $auth->processSLO();            // Process the Logout Request & Logout Response
1132    $errors = $auth->getErrors(); // Retrieves possible validation errors
1133    if (empty($errors)) {
1134        echo '<p>Sucessfully logged out</p>';
1135    } else {
1136        echo '<p>', implode(', ', $errors), '</p>';
1137    }
1138}
1139
1140if (isset($_SESSION['samlUserdata'])) {   // If there is user data we print it.
1141    if (!empty($_SESSION['samlUserdata'])) {
1142        $attributes = $_SESSION['samlUserdata'];
1143        echo 'You have the following attributes:<br>';
1144        echo '<table><thead><th>Name</th><th>Values</th></thead><tbody>';
1145        foreach ($attributes as $attributeName => $attributeValues) {
1146            echo '<tr><td>' . htmlentities($attributeName) . '</td><td><ul>';
1147            foreach ($attributeValues as $attributeValue) {
1148                echo '<li>' . htmlentities($attributeValue) . '</li>';
1149            }
1150            echo '</ul></td></tr>';
1151        }
1152        echo '</tbody></table>';
1153    } else {                             // If there is not user data, we notify
1154        echo "<p>You don't have any attribute</p>";
1155    }
1156
1157    echo '<p><a href="?slo" >Logout</a></p>'; // Print some links with possible
1158} else {                                      // actions
1159    echo '<p><a href="?sso" >Login</a></p>';
1160    echo '<p><a href="?sso2" >Login and access to attrs.php page</a></p>';
1161}
1162```
1163
1164#### Example (using Composer) that initiates the SSO request and handles the response (is the acs target) ####
1165
1166Install package via composer:
1167```
1168composer require onelogin/php-saml
1169```
1170
1171Create an index.php:
1172```php
1173<?php
1174require('vendor/autoload.php');
1175
1176session_start();
1177$needsAuth = empty($_SESSION['samlUserdata']);
1178
1179if ($needsAuth) {
1180    // put SAML settings into an array to avoid placing files in the
1181    // composer vendor/ directories
1182    $samlsettings = array(/*...config goes here...*/);
1183
1184    $auth = new \OneLogin\Saml2\Auth($samlsettings);
1185
1186    if (!empty($_REQUEST['SAMLResponse']) && !empty($_REQUEST['RelayState'])) {
1187        $auth->processResponse(null);
1188        $errors = $auth->getErrors();
1189        if (empty($errors)) {
1190            // user has authenticated successfully
1191            $needsAuth = false;
1192            $_SESSION['samlUserdata'] = $auth->getAttributes();
1193        }
1194    }
1195
1196    if ($needsAuth) {
1197        $auth->login();
1198    }
1199}
1200
1201// rest of your app goes here
1202```
1203
1204#### URL-guessing methods ####
1205
1206php-saml toolkit uses a bunch of methods in OneLogin_Saml2_Utils that try to guess the URL where the SAML messages are processed.
1207
1208* `getSelfHost` Returns the current host.
1209* `getSelfPort` Return the port number used for the request
1210* `isHTTPS` Checks if the protocol is https or http.
1211* `getSelfURLhost` Returns the protocol + the current host + the port (if different than common ports).
1212* `getSelfURL` Returns the URL of the current host + current view + query.
1213* `getSelfURLNoQuery` Returns the URL of the current host + current view.
1214* `getSelfRoutedURLNoQuery` Returns the routed URL of the current host + current view.
1215
1216getSelfURLNoQuery and getSelfRoutedURLNoQuery are used to calculate the currentURL in order to validate SAML elements like Destination or Recipient.
1217
1218When the PHP application is behind a proxy or a load balancer we can execute `setProxyVars(true)` and `setSelfPort` and `isHTTPS` will take care of the `$_SERVER["HTTP_X_FORWARDED_PORT"]` and `$_SERVER['HTTP_X_FORWARDED_PROTO']` vars (otherwise they are ignored).
1219
1220Also a developer can use `setSelfProtocol`, `setSelfHost`, `setSelfPort` and `getBaseURLPath` to define a specific value to be returned by `isHTTPS`, `getSelfHost`, `getSelfPort` and `getBaseURLPath`. And define a `setBasePath` to be used on the `getSelfURL` and `getSelfRoutedURLNoQuery` to replace the data extracted from `$_SERVER["REQUEST_URI"]`.
1221
1222At the settings the developer will be able to set a `'baseurl'` parameter that automatically will use `setBaseURL` to set values for `setSelfProtocol`, `setSelfHost`, `setSelfPort` and `setBaseURLPath`.
1223
1224
1225### Working behind load balancer ###
1226
1227Is possible that asserting request URL and Destination attribute of SAML response fails when working behind load balancer with SSL offload.
1228
1229You should be able to workaround this by configuring your server so that it is aware of the proxy and returns the original url when requested.
1230
1231Or by using the method described on the previous section.
1232
1233
1234### SP Key rollover ###
1235
1236If you plan to update the SP x509cert and privateKey you can define the new x509cert as `$settings['sp']['x509certNew']` and it will be
1237published on the SP metadata so Identity Providers can read them and get ready for rollover.
1238
1239
1240### IdP with multiple certificates ###
1241
1242In some scenarios the IdP uses different certificates for
1243signing/encryption, or is under key rollover phase and more than one certificate is published on IdP metadata.
1244
1245In order to handle that the toolkit offers the `$settings['idp']['x509certMulti']` parameter.
1246
1247When that parameter is used, `'x509cert'` and `'certFingerprint'` values will be ignored by the toolkit.
1248
1249The `'x509certMulti'` is an array with 2 keys:
1250- `'signing'`. An array of certs that will be used to validate IdP signature
1251- `'encryption'` An array with one unique cert that will be used to encrypt data to be sent to the IdP
1252
1253
1254### Replay attacks ###
1255
1256In order to avoid replay attacks, you can store the ID of the SAML messages already processed, to avoid processing them twice. Since the Messages expires and will be invalidated due that fact, you don't need to store those IDs longer than the time frame that you currently accepting.
1257
1258Get the ID of the last processed message/assertion with the `getLastMessageId/getLastAssertionId` methods of the Auth object.
1259
1260
1261### Main classes and methods ###
1262
1263Described below are the main classes and methods that can be invoked.
1264
1265#### The Old Saml library ####
1266
1267Lets start describing the classes and methods of the SAML library, an evolution
1268of the old v.1 toolkit that is provided to keep the backward compability.
1269Most of them use classes and methods of the new SAML2 library.
1270
1271##### OneLogin_Saml_AuthRequest - `AuthRequest.php` #####
1272
1273Has the protected attribute `$auth`, an `OneLogin_Saml2_Auth` object.
1274
1275* `OneLogin_Saml_AuthRequest` - Constructs `OneLogin_Saml2_Auth`,
1276  initializing the SP SAML instance.
1277* `getRedirectUrl($returnTo)` - Obtains the SSO URL containing the AuthRequest
1278  message deflated.
1279
1280
1281##### OneLogin_Saml_Response - `Response.php` #####
1282
1283* `OneLogin_Saml_Response` - Constructor that process the SAML Response,
1284  Internally initializes an SP SAML instance and an `OneLogin_Saml2_Response`.
1285* `get_saml_attributes` - Retrieves an Array with the logged user data.
1286
1287
1288##### OneLogin_Saml_Settings - `Settings.php` #####
1289
1290A simple class used to build the Setting object used in the v1.0 of the toolkit.
1291
1292##### OneLogin_Saml_Metadata - `Metadata.php` #####
1293
1294* `OneLogin_Saml_Metadata` - Constructor that build the Metadata XML info based
1295  on the settings of the SP
1296* `getXml` - An XML with the metadata info of the SP
1297
1298
1299##### OneLogin_Saml_XmlSec - `XmlSec.php` #####
1300
1301Auxiliary class that contains methods to validate the SAML Response:
1302`validateNumAssertions`, `validateTimestamps`, `isValid` (which
1303uses the other two previous methods and also validate the signature of
1304SAML Response).
1305
1306
1307#### Saml2 library ####
1308
1309Lets describe now the classes and methods of the SAML2 library.
1310
1311##### OneLogin_Saml2_Auth - Auth.php #####
1312
1313Main class of OneLogin PHP Toolkit
1314
1315 * `OneLogin_Saml2_Auth` - Initializes the SP SAML instance
1316 * `login` - Initiates the SSO process.
1317 * `logout` - Initiates the SLO process.
1318 * `processResponse` - Process the SAML Response sent by the IdP.
1319 * `processSLO` - Process the SAML Logout Response / Logout Request sent by the
1320   IdP.
1321 * `redirectTo` - Redirects the user to the url past by parameter or to the url
1322   that we defined in our SSO Request.
1323 * `isAuthenticated` - Checks if the user is authenticated or not.
1324 * `getAttributes` - Returns the set of SAML attributes.
1325 * `getAttribute` - Returns the requested SAML attribute
1326 * `getNameId` - Returns the nameID
1327 * `getNameIdFormat` - Gets the NameID Format provided by the SAML response from the IdP.
1328 * `getNameIdNameQualifier` - Gets the NameID NameQualifier provided from the SAML Response String.
1329 * `getNameIdNameSPQualifier` - Gets the NameID SP NameQualifier provided from the SAML Response String.
1330 * `getSessionIndex` - Gets the SessionIndex from the AuthnStatement.
1331 * `getErrors` - Returns if there were any error
1332 * `getSSOurl` - Gets the SSO url.
1333 * `getSLOurl` - Gets the SLO url.
1334 * `getLastRequestID` - The ID of the last Request SAML message generated.
1335 * `buildRequestSignature` - Generates the Signature for a SAML Request
1336 * `buildResponseSignature` - Generates the Signature for a SAML Response
1337 * `getSettings` - Returns the settings info
1338 * `setStrict` - Set the strict mode active/disable
1339 * `getLastRequestID` - Gets the ID of the last AuthNRequest or LogoutRequest generated by the Service Provider.
1340 * `getLastRequestXML` - Returns the most recently-constructed/processed XML SAML request (AuthNRequest, LogoutRequest)
1341 * `getLastResponseXML` - Returns the most recently-constructed/processed XML SAML response (SAMLResponse, LogoutResponse). If the SAMLResponse had an encrypted assertion, decrypts it.
1342
1343
1344##### OneLogin_Saml2_AuthnRequest - `AuthnRequest.php` #####
1345
1346SAML 2 Authentication Request class
1347
1348 * `OneLogin_Saml2_AuthnRequest` - Constructs the `AuthnRequest` object.
1349 * `getRequest` - Returns deflated, base64 encoded, unsigned `AuthnRequest`.
1350 * `getId` - Returns the `AuthNRequest` ID.
1351 * `getXML` - Returns the XML that will be sent as part of the request.
1352
1353##### OneLogin_Saml2_Response - `Response.php` #####
1354
1355SAML 2 Authentication Response class
1356
1357 * `OneLogin_Saml2_Response` - Constructs the SAML Response object.
1358 * `isValid` - Determines if the SAML Response is valid using the certificate.
1359 * `checkStatus` - Checks if the Status is success.
1360 * `getAudiences` - Gets the audiences.
1361 * `getIssuers` - Gets the Issuers (from Response and Assertion)
1362 * `getNameIdData` - Gets the NameID Data provided by the SAML response from the
1363   IdP.
1364 * `getNameId` - Gets the NameID provided by the SAML response from the IdP.
1365 * `getNameIdFormat` - Gets the NameID Format provided by the SAML response from the IdP.
1366 * `getNameIdNameQualifier` - Gets the NameID NameQualifier provided from the SAML Response String.
1367 * `getNameIdNameSPQualifier` - Gets the NameID SP NameQualifier provided from the SAML Response String.
1368 * `getSessionNotOnOrAfter` - Gets the SessionNotOnOrAfter from the
1369   AuthnStatement
1370 * `getSessionIndex` - Gets the SessionIndex from the AuthnStatement.
1371 * `getAttributes` - Gets the Attributes from the AttributeStatement element.
1372 * `validateNumAssertions` - Verifies that the document only contains a single
1373   Assertion (encrypted or not).
1374 * `validateTimestamps` - Verifies that the document is still valid according
1375   Conditions Element.
1376 * `getError` - After executing a validation process, if it fails, this method returns the cause
1377 * `getXMLDocument` - Returns the SAML Response document (If contains an encrypted assertion, decrypts it)
1378
1379##### OneLogin_Saml2_LogoutRequest - `LogoutRequest.php` #####
1380
1381SAML 2 Logout Request class
1382
1383 * `OneLogin_Saml2_LogoutRequest` - Constructs the Logout Request object.
1384 * `getRequest` - Returns the Logout Request defated, base64encoded, unsigned
1385 * `getID` - Returns the ID of the Logout Request. (If you have the object you can access to the id attribute)
1386 * `getNameIdData` - Gets the NameID Data of the the Logout Request.
1387 * `getNameId` - Gets the NameID of the Logout Request.
1388 * `getIssuer` - Gets the Issuer of the Logout Request.
1389 * `getSessionIndexes` - Gets the SessionIndexes from the Logout Request.
1390 * `isValid` - Checks if the Logout Request received is valid.
1391 * `getError` - After executing a validation process, if it fails, this method returns the cause
1392 * `getXML` - Returns the XML that will be sent as part of the request or that was received at the SP.
1393
1394##### OneLogin_Saml2_LogoutResponse - `LogoutResponse.php` #####
1395
1396SAML 2 Logout Response class
1397
1398 * `OneLogin_Saml2_LogoutResponse` - Constructs a Logout Response object
1399   (Initialize params from settings and if provided load the Logout Response)
1400 * `getIssuer` - Gets the Issuer of the Logout Response.
1401 * `getStatus` - Gets the Status of the Logout Response.
1402 * `isValid` - Determines if the SAML LogoutResponse is valid
1403 * `build` - Generates a Logout Response object.
1404 * `getResponse` - Returns a Logout Response object.
1405 * `getError` - After executing a validation process, if it fails, this method returns the cause.
1406 * `getXML` - Returns the XML that will be sent as part of the response or that was received at the SP.
1407
1408##### OneLogin_Saml2_Settings - `Settings.php` #####
1409
1410Configuration of the OneLogin PHP Toolkit
1411
1412 * `OneLogin_Saml2_Settings` -  Initializes the settings: Sets the paths of
1413   the different folders and Loads settings info from settings file or
1414   array/object provided
1415 * `checkSettings` - Checks the settings info.
1416 * `getBasePath` - Returns base path.
1417 * `getCertPath` - Returns cert path.
1418 * `getLibPath` - Returns lib path.
1419 * `getExtLibPath` - Returns external lib path.
1420 * `getSchemasPath` - Returns schema path.
1421 * `checkSPCerts` - Checks if the x509 certs of the SP exists and are valid.
1422 * `getSPkey` - Returns the x509 private key of the SP.
1423 * `getSPcert` - Returns the x509 public cert of the SP.
1424 * `getSPcertNew` - Returns the future x509 public cert of the SP.
1425 * `getIdPData` - Gets the IdP data.
1426 * `getSPData`Gets the SP data.
1427 * `getSecurityData` - Gets security data.
1428 * `getContacts` - Gets contact data.
1429 * `getOrganization` - Gets organization data.
1430 * `getSPMetadata` - Gets the SP metadata. The XML representation.
1431 * `validateMetadata` - Validates an XML SP Metadata.
1432 * `formatIdPCert` - Formats the IdP cert.
1433 * `formatSPCert` - Formats the SP cert.
1434 * `formatSPCertNew` - Formats the SP cert new.
1435 * `formatSPKey` - Formats the SP private key.
1436 * `getErrors` - Returns an array with the errors, the array is empty when
1437   the settings is ok.
1438 * `getLastErrorReason` - Returns the reason of the last error
1439 * `getBaseURL` -  Returns the baseurl set on the settings if any.
1440 * `setBaseURL` - Set a baseurl value
1441 * `setStrict` - Activates or deactivates the strict mode.
1442 * `isStrict` - Returns if the 'strict' mode is active.
1443 * `isDebugActive` - Returns if the debug is active.
1444
1445##### OneLogin_Saml2_Metadata - `Metadata.php` #####
1446
1447A class that contains functionality related to the metadata of the SP
1448
1449* `builder` - Generates the metadata of the SP based on the settings.
1450* `signmetadata` - Signs the metadata with the key/cert provided
1451* `addX509KeyDescriptors` - Adds the x509 descriptors (sign/encriptation) to
1452  the metadata
1453
1454##### OneLogin_Saml2_Utils - `Utils.php` #####
1455
1456Auxiliary class that contains several methods
1457
1458 * `validateXML` - This function attempts to validate an XML string against
1459   the specified schema.
1460 * `formatCert` - Returns a x509 cert (adding header & footer if required).
1461 * `formatPrivateKey` - returns a RSA private key (adding header & footer if required).
1462 * `redirect` - Executes a redirection to the provided url (or return the
1463   target url).
1464 * `isHTTPS` - Checks if https or http.
1465 * `getSelfHost` - Returns the current host.
1466 * `getSelfURLhost` - Returns the protocol + the current host + the port
1467   (if different than common ports).
1468 * `getSelfURLNoQuery` - Returns the URL of the current host + current view.
1469 * `getSelfURL` - Returns the URL of the current host + current view + query.
1470 * `generateUniqueID` - Generates a unique string (used for example as ID
1471   for assertions).
1472 * `parseTime2SAML` - Converts a UNIX timestamp to SAML2 timestamp on the
1473   form `yyyy-mm-ddThh:mm:ss(\.s+)?Z`.
1474 * `parseSAML2Time` - Converts a SAML2 timestamp on the form
1475   `yyyy-mm-ddThh:mm:ss(\.s+)?Z` to a UNIX timestamp. The sub-second part is
1476   ignored.
1477 * `parseDuration` - Interprets a ISO8601 duration value relative to a given
1478   timestamp.
1479 * `getExpireTime` - Compares two dates and returns the earliest.
1480 * `query` - Extracts nodes from the DOMDocument.
1481 * `isSessionStarted` - Checks if the session is started or not.
1482 * `deleteLocalSession` - Deletes the local session.
1483 * `calculateX509Fingerprint` - Calculates the fingerprint of a x509cert.
1484 * `formatFingerPrint` - Formats a fingerprint.
1485 * `generateNameId` - Generates a `nameID`.
1486 * `getStatus` - Gets Status from a Response.
1487 * `decryptElement` - Decrypts an encrypted element.
1488 * `castKey` - Converts a `XMLSecurityKey` to the correct algorithm.
1489 * `addSign` - Adds signature key and senders certificate to an element
1490   (Message or Assertion).
1491 * `validateSign` - Validates a signature (Message or Assertion).
1492
1493##### OneLogin_Saml2_IdPMetadataParser - `IdPMetadataParser.php` #####
1494
1495Auxiliary class that contains several methods to retrieve and process IdP metadata
1496
1497 * `parseRemoteXML` - Get IdP Metadata Info from URL.
1498 * `parseFileXML` - Get IdP Metadata Info from File.
1499 * `parseXML` - Get IdP Metadata Info from XML.
1500 * `injectIntoSettings` - Inject metadata info into php-saml settings array.
1501
1502
1503For more info, look at the source code; each method is documented and details
1504about what it does and how to use it are provided. Make sure to also check the doc folder where
1505HTML documentation about the classes and methods is provided for SAML and
1506SAML2.
1507
1508
1509Demos included in the toolkit
1510-----------------------------
1511
1512The toolkit includes three demo apps to teach how use the toolkit, take a look on it.
1513
1514Demos require that SP and IdP are well configured before test it.
1515
1516## Demo1 ##
1517
1518### SP setup ###
1519
1520The Onelogin's PHP Toolkit allows you to provide the settings info in two ways:
1521
1522 * Use a `settings.php` file that we should locate at the base folder of the
1523   toolkit.
1524 * Use an array with the setting data.
1525
1526In this demo we provide the data in the second way, using a setting array named
1527`$settingsInfo`. This array users the `settings_example.php` included as a template
1528to create the `settings.php` settings and store it in the `demo1/` folder.
1529Configure the SP part and later review the metadata of the IdP and complete the IdP info.
1530
1531If you check the code of the index.php file you will see that the `settings.php`
1532file is loaded in order to get the `$settingsInfo` var to be used in order to initialize
1533the `Setting` class.
1534
1535Notice that in this demo, the `setting.php` file that could be defined at the base
1536folder of the toolkit is ignored and the libs are loaded using the
1537`_toolkit_loader.php` located at the base folder of the toolkit.
1538
1539
1540### IdP setup ###
1541
1542Once the SP is configured, the metadata of the SP is published at the
1543`metadata.php` file. Configure the IdP based on that information.
1544
1545
1546### How it works ###
1547
1548 1. First time you access to `index.php` view, you can select to login and return
1549    to the same view or login and be redirected to the `attrs.php` view.
1550
1551 2. When you click:
1552
1553    2.1 in the first link, we access to (`index.php?sso`) an `AuthNRequest`
1554    is sent to the IdP, we authenticate at the IdP and then a Response is sent
1555    through the user's client to the SP, specifically the Assertion Consumer Service view: `index.php?acs`.
1556    Notice that a `RelayState` parameter is set to the url that initiated the
1557    process, the `index.php` view.
1558
1559    2.2 in the second link we access to (`attrs.php`) have the same process
1560    described at 2.1 with the difference that as `RelayState` is set the `attrs.php`.
1561
1562 3. The SAML Response is processed in the ACS (`index.php?acs`), if the Response
1563    is not valid, the process stops here and a message is shown. Otherwise we
1564    are redirected to the RelayState view. a) `index.php` or b) `attrs.php`.
1565
1566 4. We are logged in the app and the user attributes are showed.
1567    At this point, we can test the single log out functionality.
1568
1569 5. The single log out functionality could be tested by two ways.
1570
1571    5.1 SLO Initiated by SP. Click on the "logout" link at the SP, after that a
1572    Logout Request is sent to the IdP, the session at the IdP is closed and
1573    replies through the client to the SP with a Logout Response (sent to the
1574    Single Logout Service endpoint). The SLS endpoint (`index.php?sls`) of the SP
1575    process the Logout Response and if is valid, close the user session of the
1576    local app. Notice that the SLO Workflow starts and ends at the SP.
1577
1578    5.2 SLO Initiated by IdP. In this case, the action takes place on the IdP
1579    side, the logout process is initiated at the idP, sends a Logout
1580    Request to the SP (SLS endpoint, `index.php?sls`). The SLS endpoint of the SP
1581    process the Logout Request and if is valid, close the session of the user
1582    at the local app and send a Logout Response to the IdP (to the SLS endpoint
1583    of the IdP). The IdP receives the Logout Response, process it and close the
1584    session at of the IdP. Notice that the SLO Workflow starts and ends at the IdP.
1585
1586Notice that all the SAML Requests and Responses are handled by a unique file,
1587the `index.php` file and how `GET` parameters are used to know the action that
1588must be done.
1589
1590
1591## Demo2 ##
1592
1593### SP setup ###
1594
1595The Onelogin's PHP Toolkit allows you to provide the settings info in two ways:
1596
1597 * Use a `settings.php` file that we should locate at the base folder of the
1598   toolkit.
1599 * Use an array with the setting data.
1600
1601The first is the case of the demo2 app. The `setting.php` file and the
1602`setting_extended.php` file should be defined at the base folder of the toolkit.
1603Review the `setting_example.php` and the `advanced_settings_example.php` to
1604learn how to build them.
1605
1606In this case as Attribute Consume Service and Single Logout Service we are going to
1607use the files located in the endpoint folder (`acs.php` and `sls.php`).
1608
1609
1610### IdP setup ###
1611
1612Once the SP is configured, the metadata of the SP is published at the
1613`metadata.php` file. Based on that info, configure the IdP.
1614
1615
1616### How it works ###
1617
1618In demo1, we saw how all the SAML Request and Responses were handler at an
1619unique file, the `index.php` file. This demo1 uses high-level programming.
1620
1621In demo2, we have several views: `index.php`, `sso.php`, `slo.php`, `consume.php`
1622and `metadata.php`. As we said, we will use the endpoints that are defined
1623in the toolkit (`acs.php`, `sls.php` of the endpoints folder). This demo2 uses
1624low-level programming.
1625
1626Notice that the SSO action can be initiated at `index.php` or `sso.php`.
1627
1628The SAML workflow that take place is similar that the workflow defined in the
1629demo1, only changes the targets.
1630
1631 1. When you access `index.php` or `sso.php` for the first time, an `AuthNRequest` is
1632    sent to the IdP automatically, (as `RelayState` is sent the origin url).
1633    We authenticate at the IdP and then a `Response` is sent to the SP, to the
1634    ACS endpoint, in this case `acs.php` of the endpoints folder.
1635
1636 2. The SAML Response is processed in the ACS, if the `Response` is not valid,
1637    the process stops here and a message is shown. Otherwise we are redirected
1638    to the `RelayState` view (`sso.php` or `index.php`). The `sso.php` detects if the
1639    user is logged and redirects to `index.php`, so we will be in the
1640    `index.php` at the end.
1641
1642 3. We are logged into the app and the user attributes (if any) are shown.
1643    At this point, we can test the single log out functionality.
1644
1645 4. The single log out functionality could be tested by two ways.
1646
1647    4.1 SLO Initiated by SP. Click on the "logout" link at the SP, after that
1648    we are redirected to the `slo.php` view and there a Logout Request is sent
1649    to the IdP, the session at the IdP is closed and replies to the SP a
1650    Logout Response (sent to the Single Logout Service endpoint). In this case
1651    The SLS endpoint of the SP process the Logout Response and if is
1652    valid, close the user session of the local app. Notice that the SLO
1653    Workflow starts and ends at the SP.
1654
1655    4.2 SLO Initiated by IdP. In this case, the action takes place on the IdP
1656    side, the logout process is initiated at the idP, sends a Logout
1657    Request to the SP (SLS endpoint `sls.php` of the endpoint folder).
1658    The SLS endpoint of the SP process the Logout Request and if is valid,
1659    close the session of the user at the local app and sends a Logout Response
1660    to the IdP (to the SLS endpoint of the IdP).The IdP receives the Logout
1661    Response, process it and close the session at of the IdP. Notice that the
1662    SLO Workflow starts and ends at the IdP.
1663
1664
1665## Demo Old ##
1666
1667### SP setup ###
1668
1669This demo uses the old style of the version 1 of the toolkit.
1670An object of the class `OneLogin_Saml_Settings` must be provided to the
1671constructor of the `AuthRequest`.
1672
1673You will find an `example_settings.php` file at the demo-old's folder that
1674could be used as a template for your `settings.php` file.
1675
1676In that template, SAML settings are divided into two parts, the application
1677specific (`const_assertion_consumer_service_url`, `const_issuer`,
1678`const_name_identifier_format`) and the user/account specific
1679`idp_sso_target_url`, `x509certificate`). You'll need to add your own code here
1680to identify the user or user origin (e.g. by `subdomain`, `ip_address` etc.).
1681
1682
1683### IdP setup ###
1684
1685Once the SP is configured, the metadata of the SP is published at the
1686`metadata.php` file. After that, configure the IdP based on that information.
1687
1688
1689### How it works ###
1690
1691At the `metadata.php` view is published the metadata of the SP.
1692
1693The `index.php` file acts as an initiater for the SAML conversation if it should
1694should be initiated by the application. This is called Service Provider
1695Initiated SAML. The service provider creates a SAML Authentication Request and
1696sends it to the identity provider (IdP).
1697
1698The `consume.php` is the ACS endpoint. Receives the SAML assertion. After Response
1699validation, the userdata and the nameID will be available, using `getNameId()` or
1700`getAttributes()` we obtain them.
1701
1702Since the version 1 of the php toolkit does not support SLO we don't show how
1703handle SLO in this demo-old.
1704