Skip to content

Commit 35bc67e

Browse files
author
christianbpedersen
committed
Merge pull request SAML-Toolkits#2 from merlinofchaos/master
Updates per our email
2 parents 5415ac5 + 12d543e commit 35bc67e

File tree

8 files changed

+226
-65
lines changed

8 files changed

+226
-65
lines changed

README

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
The files index.php, consume.php and settings.php are sample code to help
2+
demonstrate how this library should work. In order to use them, you can
3+
unpack this library in your website directory.
4+
5+
You will need to modify the settings.php file to set the proper URLs and
6+
x509 certificate.
7+
8+
There is more information in this post:
9+
http://support.onelogin.com/entries/268420-saml-toolkit-for-php

consume.php

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,28 @@
11
<?php
2+
/**
3+
* SAMPLE Code to demonstrate how to handle a SAML assertion response.
4+
*
5+
* The URL of this file will have been given during the SAML authorization.
6+
* After a successful authorization, the browser will be directed to this
7+
* link where it will send a certified response via $_POST.
8+
*/
29

3-
error_reporting(E_ALL);
10+
error_reporting(E_ALL);
411

512
require 'settings.php';
613

714
require 'lib/onelogin/saml.php';
815

9-
$samlresponse = new SamlResponse($_POST['SAMLResponse']);
10-
$samlresponse->user_settings = get_user_settings();
11-
12-
if ($samlresponse->is_valid())
13-
echo "You are: ".$samlresponse->get_nameid();
14-
else
15-
echo "Invalid SAML response.";
16+
$samlresponse = new SamlResponse(saml_get_settings(), $_POST['SAMLResponse']);
17+
18+
try {
19+
if ($samlresponse->is_valid())
20+
echo "You are: ".$samlresponse->get_nameid();
21+
else
22+
echo "Invalid SAML response.";
23+
}
24+
catch (Exception $e) {
25+
echo "Invalid SAML response: " . $e->getMessage();
26+
}
1627

1728
?>

index.php

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,20 @@
11
<?php
2-
error_reporting(E_ALL);
3-
2+
/**
3+
* SAMPLE Code to demonstrate how to initiate a SAML Authorization request
4+
*
5+
* When the user visits this URL, the browser will be redirected to the SSO
6+
* IdP with an authorization request. If successful, it will then be
7+
* redirected to the consume URL (specified in settings) with the auth
8+
* details.
9+
*/
10+
11+
error_reporting(E_ALL);
12+
413
require 'settings.php';
514

615
require 'lib/onelogin/saml.php';
7-
8-
$authrequest = new AuthRequest();
9-
$authrequest->user_settings = get_user_settings();
16+
17+
$authrequest = new SamlAuthRequest(saml_get_settings());
1018
$url = $authrequest->create();
1119

1220
header("Location: $url");

lib/onelogin/saml/authrequest.php

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,39 @@
11
<?php
2-
class authrequest {
3-
public $user_settings;
2+
/**
3+
* Create a SAML authorization request.
4+
*/
5+
class SamlAuthRequest {
6+
/**
7+
* A SamlResponse class provided to the constructor.
8+
*/
9+
private $settings;
410

11+
/**
12+
* Construct the response object.
13+
*
14+
* @param SamlResponse $settings
15+
* A SamlResponse settings object containing the necessary
16+
* x509 certicate to decode the XML.
17+
*/
18+
function __construct($settings) {
19+
$this->settings = $settings;
20+
}
21+
22+
/**
23+
* Generate the request.
24+
*
25+
* @return
26+
* A fully qualified URL that can be redirected to in order to process
27+
* the authorization request.
28+
*/
529
public function create() {
630
$id = $this->generateUniqueID(20);
731
$issue_instant = $this->getTimestamp();
832

9-
global $const_assertion_consumer_service_url;
10-
global $const_issuer;
11-
global $const_name_identifier_format;
1233
$request =
13-
"<samlp:AuthnRequest xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" ID=\"$id\" Version=\"2.0\" IssueInstant=\"$issue_instant\" ProtocolBinding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST\" AssertionConsumerServiceURL=\"".$const_assertion_consumer_service_url."\">".
14-
"<saml:Issuer xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">".$const_issuer."</saml:Issuer>\n".
15-
"<samlp:NameIDPolicy xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" Format=\"".$const_name_identifier_format."\" AllowCreate=\"true\"></samlp:NameIDPolicy>\n".
34+
"<samlp:AuthnRequest xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" ID=\"$id\" Version=\"2.0\" IssueInstant=\"$issue_instant\" ProtocolBinding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST\" AssertionConsumerServiceURL=\"".$this->settings->assertion_consumer_service_url."\">".
35+
"<saml:Issuer xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">".$this->settings->issuer."</saml:Issuer>\n".
36+
"<samlp:NameIDPolicy xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" Format=\"".$this->settings->name_identifier_format."\" AllowCreate=\"true\"></samlp:NameIDPolicy>\n".
1637
"<samlp:RequestedAuthnContext xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" Comparison=\"exact\">".
1738
"<saml:AuthnContextClassRef xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml:AuthnContextClassRef></samlp:RequestedAuthnContext>\n".
1839
"</samlp:AuthnRequest>";
@@ -21,7 +42,7 @@ public function create() {
2142
$base64_request = base64_encode($deflated_request);
2243
$encoded_request = urlencode($base64_request);
2344

24-
return $this->user_settings->idp_sso_target_url."?SAMLRequest=".$encoded_request;
45+
return $this->settings->idp_sso_target_url."?SAMLRequest=".$encoded_request;
2546
}
2647

2748
private function generateUniqueID($length) {

lib/onelogin/saml/response.php

Lines changed: 47 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,66 @@
11
<?php
22
require 'xmlsec.php';
33

4+
/**
5+
* Parse the SAML response and maintain the XML for it.
6+
*/
47
class SamlResponse {
8+
/**
9+
* A SamlResponse class provided to the constructor.
10+
*/
11+
private $settings;
12+
13+
/**
14+
* The decoded, unprocessed XML assertion provided to the constructor.
15+
*/
16+
public $assertion;
17+
18+
/**
19+
* A DOMDocument class loaded from the $assertion.
20+
*/
21+
public $xml;
22+
23+
// At this time these private members are unused.
524
private $nameid;
6-
private $xml;
725
private $xpath;
8-
9-
public $user_settings;
10-
11-
function __construct($val) {
12-
// $this->xml = new SimpleXMLElement(base64_decode($val));
13-
$this->xml = new DOMDocument();
1426

15-
$this->xml->loadXML(base64_decode($val));
27+
/**
28+
* Construct the response object.
29+
*
30+
* @param SamlResponse $settings
31+
* A SamlResponse settings object containing the necessary
32+
* x509 certicate to decode the XML.
33+
* @param string $assertion
34+
* A UUEncoded SAML assertion from the IdP.
35+
*/
36+
function __construct($settings, $assertion) {
37+
$this->settings = $settings;
38+
$this->assertion = base64_decode($assertion);
39+
$this->xml = new DOMDocument();
40+
$this->xml->loadXML($this->assertion);
1641
}
17-
42+
43+
/**
44+
* Determine if the SAML Response is valid using the certificate.
45+
*
46+
* @return
47+
* TRUE if the document passes. This could throw a generic Exception
48+
* if the document or key cannot be found.
49+
*/
1850
function is_valid() {
19-
$xmlsec = new XmlSec($this->xml);
20-
$xmlsec->x509certificate = $this->user_settings->x509certificate;
51+
$xmlsec = new SamlXmlSec($this->settings, $this->xml);
2152
return $xmlsec->is_valid();
2253
}
23-
54+
55+
/**
56+
* Get the NameID provided by the SAML response from the IdP.
57+
*/
2458
function get_nameid() {
2559
$xpath = new DOMXPath($this->xml);
2660
$xpath->registerNamespace("samlp","urn:oasis:names:tc:SAML:2.0:protocol");
2761
$xpath->registerNamespace("saml","urn:oasis:names:tc:SAML:2.0:assertion");
2862
$query = "/samlp:Response/saml:Assertion/saml:Subject/saml:NameID";
29-
63+
3064
$entries = $xpath->query($query);
3165
return $entries->item(0)->nodeValue;
3266
}

lib/onelogin/saml/settings.php

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,35 @@
11
<?php
22

3-
class settings {
3+
/**
4+
* Holds SAML settings for the SamlResponse and SamlAuthRequest classes.
5+
*
6+
* These settings need to be filled in by the user prior to being used.
7+
*/
8+
class SamlSettings {
9+
/**
10+
* The URL to submit SAML authentication requests to.
11+
*/
12+
var $idp_sso_target_url = '';
13+
14+
/**
15+
* The x509 certificate used to authenticate the request.
16+
*/
17+
var $x509certificate = '';
18+
19+
/**
20+
* The URL where to the SAML Response/SAML Assertion will be posted.
21+
*/
22+
var $assertion_consumer_service_url = '';
23+
24+
/**
25+
* The name of the application.
26+
*/
27+
var $issuer = "php-saml";
28+
29+
/**
30+
* Specifies what format to return the authentication token, i.e, the email address.
31+
*/
32+
var $name_identifier_format = "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress";
433
}
534

635
?>

lib/onelogin/saml/xmlsec.php

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,45 @@
11
<?php
22
require(dirname(__FILE__) . '/../../xmlseclibs/xmlseclibs.php');
33

4-
class XmlSec {
5-
public $x509certificate;
6-
private $doc;
7-
8-
function __construct($val) {
9-
$this->doc = $val;
4+
/**
5+
* Determine if the SAML response is valid using a provided x509 certificate.
6+
*/
7+
class SamlXmlSec {
8+
/**
9+
* A SamlResponse class provided to the constructor.
10+
*/
11+
private $settings;
12+
13+
/**
14+
* The documentument to be tested.
15+
*/
16+
private $document;
17+
18+
/**
19+
* Construct the SamlXmlSec object.
20+
*
21+
* @param SamlResponse $settings
22+
* A SamlResponse settings object containing the necessary
23+
* x509 certicate to test the document.
24+
* @param string $document
25+
* The document to test.
26+
*/
27+
function __construct($settings, $document) {
28+
$this->settings = $settings;
29+
$this->document = $document;
1030
}
11-
31+
32+
/**
33+
* Determine if the document passes the security test.
34+
*
35+
* @return
36+
* TRUE if the document passes. This could throw a generic Exception
37+
* if the document or key cannot be found.
38+
*/
1239
function is_valid() {
1340
$objXMLSecDSig = new XMLSecurityDSig();
1441

15-
$objDSig = $objXMLSecDSig->locateSignature($this->doc);
42+
$objDSig = $objXMLSecDSig->locateSignature($this->document);
1643
if (! $objDSig) {
1744
throw new Exception("Cannot locate Signature Node");
1845
}
@@ -33,8 +60,8 @@ function is_valid() {
3360

3461
$objKeyInfo = XMLSecEnc::staticLocateKeyInfo($objKey, $objDSig);
3562

36-
$objKey->loadKey($this->x509certificate, FALSE, true);
37-
63+
$objKey->loadKey($this->settings->x509certificate, FALSE, true);
64+
3865
$result = $objXMLSecDSig->verify($objKey);
3966
return $result;
4067
}

settings.php

Lines changed: 41 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,32 @@
11
<?php
2-
// these are account wide configuration settings
3-
4-
// the URL where to the SAML Response/SAML Assertion will be posted
5-
$const_assertion_consumer_service_url = "http://localhost/php-saml/consume.php";
6-
// name of this application
7-
$const_issuer = "php-saml";
8-
// tells the IdP to return the email address of the current user
9-
$const_name_identifier_format = "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress";
10-
11-
function get_user_settings() {
12-
// this function should be modified to return the SAML settings for the current user
13-
14-
$settings = new Settings();
15-
// when using Service Provider Initiated SSO (starting at index.php), this URL asks the IdP to authenticate the user.
16-
$settings->idp_sso_target_url = "https://app.onelogin.com/saml/signon/6171";
17-
// the certificate for the users account in the IdP
18-
$settings->x509certificate = "-----BEGIN CERTIFICATE-----
2+
/**
3+
* SAMPLE Code to demonstrate how provide SAML settings.
4+
*
5+
* The settings are contained within a SamlSettings object. You need to
6+
* provide, at a minimum, the following things:
7+
* - idp_sso_target_url: This is the URL to forward to for auth requests.
8+
* It will be provided by your IdP.
9+
* - x509certificate: This is a certificate required to authenticate your
10+
* request. This certificate should be provided by your IdP.
11+
* - assertion_consumer_service_url: The URL that the IdP should redirect
12+
* to once the authorization is complete. You must provide this, and it
13+
* should point to the consume.php script or its equivalent.
14+
*/
15+
16+
/**
17+
* Return a SamlSettings object with user settings.
18+
*/
19+
function saml_get_settings() {
20+
// This function should be modified to return the SAML settings for the current user
21+
22+
$settings = new SamlSettings();
23+
24+
// When using Service Provider Initiated SSO (starting at index.php), this URL asks the IdP to authenticate the user.
25+
$settings->idp_sso_target_url = "https://app.onelogin.com/saml/signon/6171";
26+
27+
// The certificate for the users account in the IdP
28+
$settings->x509certificate = <<<ENDCERTIFICATE
29+
-----BEGIN CERTIFICATE-----
1930
MIIBrTCCAaGgAwIBAgIBATADBgEAMGcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApD
2031
YWxpZm9ybmlhMRUwEwYDVQQHDAxTYW50YSBNb25pY2ExETAPBgNVBAoMCE9uZUxv
2132
Z2luMRkwFwYDVQQDDBBhcHAub25lbG9naW4uY29tMB4XDTEwMDMwOTA5NTgzNFoX
@@ -26,9 +37,20 @@ function get_user_settings() {
2637
kJNHYAAQ9egLGWQ8/1atkPBye5s9fxROtf8VO3uk/x/X5VSRODIrhFISGmKUnVXa
2738
UhLFIXkGSCAIVfoR5S2ggdfpINKUWGsWS/lEzLNYMBkURXuVAgMBAAEwAwYBAAMB
2839
AA==
29-
-----END CERTIFICATE-----";
40+
-----END CERTIFICATE-----
41+
ENDCERTIFICATE;
42+
43+
// The URL where to the SAML Response/SAML Assertion will be posted
44+
$settings->assertion_consumer_service_url = "http://localhost/php-saml/consume.php";
45+
46+
// Name of this application
47+
$settings->issuer = "php-saml";
48+
49+
// Tells the IdP to return the email address of the current user
50+
$settings->name_identifier_format = "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress";
51+
3052

3153
return $settings;
3254
}
33-
55+
3456
?>

0 commit comments

Comments
 (0)