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