215 lines
6.4 KiB
PHP
215 lines
6.4 KiB
PHP
|
<?php
|
||
|
/**
|
||
|
* This file is part of php-saml.
|
||
|
*
|
||
|
* (c) OneLogin Inc
|
||
|
*
|
||
|
* For the full copyright and license information, please view the LICENSE
|
||
|
* file that was distributed with this source code.
|
||
|
*
|
||
|
* @package OneLogin
|
||
|
* @author OneLogin Inc <saml-info@onelogin.com>
|
||
|
* @license MIT https://github.com/onelogin/php-saml/blob/master/LICENSE
|
||
|
* @link https://github.com/onelogin/php-saml
|
||
|
*/
|
||
|
|
||
|
namespace OneLogin\Saml2;
|
||
|
|
||
|
/**
|
||
|
* SAML 2 Authentication Request
|
||
|
*/
|
||
|
class AuthnRequest
|
||
|
{
|
||
|
/**
|
||
|
* Object that represents the setting info
|
||
|
*
|
||
|
* @var Settings
|
||
|
*/
|
||
|
protected $_settings;
|
||
|
|
||
|
/**
|
||
|
* SAML AuthNRequest string
|
||
|
*
|
||
|
* @var string
|
||
|
*/
|
||
|
private $_authnRequest;
|
||
|
|
||
|
/**
|
||
|
* SAML AuthNRequest ID.
|
||
|
*
|
||
|
* @var string
|
||
|
*/
|
||
|
private $_id;
|
||
|
|
||
|
/**
|
||
|
* Constructs the AuthnRequest object.
|
||
|
*
|
||
|
* @param Settings $settings SAML Toolkit Settings
|
||
|
* @param bool $forceAuthn When true the AuthNReuqest will set the ForceAuthn='true'
|
||
|
* @param bool $isPassive When true the AuthNReuqest will set the Ispassive='true'
|
||
|
* @param bool $setNameIdPolicy When true the AuthNReuqest will set a nameIdPolicy
|
||
|
* @param string $nameIdValueReq Indicates to the IdP the subject that should be authenticated
|
||
|
*/
|
||
|
public function __construct(\OneLogin\Saml2\Settings $settings, $forceAuthn = false, $isPassive = false, $setNameIdPolicy = true, $nameIdValueReq = null)
|
||
|
{
|
||
|
$this->_settings = $settings;
|
||
|
|
||
|
$spData = $this->_settings->getSPData();
|
||
|
$security = $this->_settings->getSecurityData();
|
||
|
|
||
|
$id = Utils::generateUniqueID();
|
||
|
$issueInstant = Utils::parseTime2SAML(time());
|
||
|
|
||
|
$subjectStr = "";
|
||
|
if (isset($nameIdValueReq)) {
|
||
|
$subjectStr = <<<SUBJECT
|
||
|
|
||
|
<saml:Subject>
|
||
|
<saml:NameID Format="{$spData['NameIDFormat']}">{$nameIdValueReq}</saml:NameID>
|
||
|
<saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"></saml:SubjectConfirmation>
|
||
|
</saml:Subject>
|
||
|
SUBJECT;
|
||
|
}
|
||
|
|
||
|
$nameIdPolicyStr = '';
|
||
|
if ($setNameIdPolicy) {
|
||
|
$nameIDPolicyFormat = $spData['NameIDFormat'];
|
||
|
if (isset($security['wantNameIdEncrypted']) && $security['wantNameIdEncrypted']) {
|
||
|
$nameIDPolicyFormat = Constants::NAMEID_ENCRYPTED;
|
||
|
}
|
||
|
|
||
|
$nameIdPolicyStr = <<<NAMEIDPOLICY
|
||
|
|
||
|
<samlp:NameIDPolicy
|
||
|
Format="{$nameIDPolicyFormat}"
|
||
|
AllowCreate="true" />
|
||
|
NAMEIDPOLICY;
|
||
|
}
|
||
|
|
||
|
|
||
|
$providerNameStr = '';
|
||
|
$organizationData = $settings->getOrganization();
|
||
|
if (!empty($organizationData)) {
|
||
|
$langs = array_keys($organizationData);
|
||
|
if (in_array('en-US', $langs)) {
|
||
|
$lang = 'en-US';
|
||
|
} else {
|
||
|
$lang = $langs[0];
|
||
|
}
|
||
|
if (isset($organizationData[$lang]['displayname']) && !empty($organizationData[$lang]['displayname'])) {
|
||
|
$providerNameStr = <<<PROVIDERNAME
|
||
|
ProviderName="{$organizationData[$lang]['displayname']}"
|
||
|
PROVIDERNAME;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
$forceAuthnStr = '';
|
||
|
if ($forceAuthn) {
|
||
|
$forceAuthnStr = <<<FORCEAUTHN
|
||
|
|
||
|
ForceAuthn="true"
|
||
|
FORCEAUTHN;
|
||
|
}
|
||
|
|
||
|
$isPassiveStr = '';
|
||
|
if ($isPassive) {
|
||
|
$isPassiveStr = <<<ISPASSIVE
|
||
|
|
||
|
IsPassive="true"
|
||
|
ISPASSIVE;
|
||
|
}
|
||
|
|
||
|
$requestedAuthnStr = '';
|
||
|
if (isset($security['requestedAuthnContext']) && $security['requestedAuthnContext'] !== false) {
|
||
|
$authnComparison = 'exact';
|
||
|
if (isset($security['requestedAuthnContextComparison'])) {
|
||
|
$authnComparison = $security['requestedAuthnContextComparison'];
|
||
|
}
|
||
|
|
||
|
$authnComparisonAttr = '';
|
||
|
if (!empty($authnComparison)) {
|
||
|
$authnComparisonAttr = sprintf('Comparison="%s"', $authnComparison);
|
||
|
}
|
||
|
|
||
|
if ($security['requestedAuthnContext'] === true) {
|
||
|
$requestedAuthnStr = <<<REQUESTEDAUTHN
|
||
|
|
||
|
<samlp:RequestedAuthnContext $authnComparisonAttr>
|
||
|
<saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml:AuthnContextClassRef>
|
||
|
</samlp:RequestedAuthnContext>
|
||
|
REQUESTEDAUTHN;
|
||
|
} else {
|
||
|
$requestedAuthnStr .= " <samlp:RequestedAuthnContext $authnComparisonAttr>\n";
|
||
|
foreach ($security['requestedAuthnContext'] as $contextValue) {
|
||
|
$requestedAuthnStr .= " <saml:AuthnContextClassRef>".$contextValue."</saml:AuthnContextClassRef>\n";
|
||
|
}
|
||
|
$requestedAuthnStr .= ' </samlp:RequestedAuthnContext>';
|
||
|
}
|
||
|
}
|
||
|
|
||
|
$spEntityId = htmlspecialchars($spData['entityId'], ENT_QUOTES);
|
||
|
$acsUrl = htmlspecialchars($spData['assertionConsumerService']['url'], ENT_QUOTES);
|
||
|
$destination = $this->_settings->getIdPSSOUrl();
|
||
|
$request = <<<AUTHNREQUEST
|
||
|
<samlp:AuthnRequest
|
||
|
xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
|
||
|
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
|
||
|
ID="$id"
|
||
|
Version="2.0"
|
||
|
{$providerNameStr}{$forceAuthnStr}{$isPassiveStr}
|
||
|
IssueInstant="{$issueInstant}"
|
||
|
Destination="{$destination}"
|
||
|
ProtocolBinding="{$spData['assertionConsumerService']['binding']}"
|
||
|
AssertionConsumerServiceURL="{$acsUrl}">
|
||
|
<saml:Issuer>{$spEntityId}</saml:Issuer>{$subjectStr}{$nameIdPolicyStr}{$requestedAuthnStr}
|
||
|
</samlp:AuthnRequest>
|
||
|
AUTHNREQUEST;
|
||
|
|
||
|
$this->_id = $id;
|
||
|
$this->_authnRequest = $request;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns deflated, base64 encoded, unsigned AuthnRequest.
|
||
|
*
|
||
|
* @param bool|null $deflate Whether or not we should 'gzdeflate' the request body before we return it.
|
||
|
*
|
||
|
* @return string
|
||
|
*/
|
||
|
public function getRequest($deflate = null)
|
||
|
{
|
||
|
$subject = $this->_authnRequest;
|
||
|
|
||
|
if (is_null($deflate)) {
|
||
|
$deflate = $this->_settings->shouldCompressRequests();
|
||
|
}
|
||
|
|
||
|
if ($deflate) {
|
||
|
$subject = gzdeflate($this->_authnRequest);
|
||
|
}
|
||
|
|
||
|
$base64Request = base64_encode($subject);
|
||
|
return $base64Request;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the AuthNRequest ID.
|
||
|
*
|
||
|
* @return string
|
||
|
*/
|
||
|
public function getId()
|
||
|
{
|
||
|
return $this->_id;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the XML that will be sent as part of the request
|
||
|
*
|
||
|
* @return string
|
||
|
*/
|
||
|
public function getXML()
|
||
|
{
|
||
|
return $this->_authnRequest;
|
||
|
}
|
||
|
}
|