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