1<?php 2 3/** 4 * SAML 2 Authentication Request 5 * 6 */ 7class OneLogin_Saml2_AuthnRequest 8{ 9 10 /** 11 * Object that represents the setting info 12 * @var OneLogin_Saml2_Settings 13 */ 14 protected $_settings; 15 16 /** 17 * SAML AuthNRequest string 18 * @var string 19 */ 20 private $_authnRequest; 21 22 /** 23 * SAML AuthNRequest ID. 24 * @var string 25 */ 26 private $_id; 27 28 /** 29 * Constructs the AuthnRequest object. 30 * 31 * @param OneLogin_Saml2_Settings $settings Settings 32 * @param bool $forceAuthn When true the AuthNReuqest will set the ForceAuthn='true' 33 * @param bool $isPassive When true the AuthNReuqest will set the Ispassive='true' 34 * @param bool $setNameIdPolicy When true the AuthNReuqest will set a nameIdPolicy 35 * @param string $nameIdValueReq Indicates to the IdP the subject that should be authenticated 36 */ 37 public function __construct(OneLogin_Saml2_Settings $settings, $forceAuthn = false, $isPassive = false, $setNameIdPolicy = true, $nameIdValueReq = null) 38 { 39 $this->_settings = $settings; 40 41 $spData = $this->_settings->getSPData(); 42 $idpData = $this->_settings->getIdPData(); 43 $security = $this->_settings->getSecurityData(); 44 45 $id = OneLogin_Saml2_Utils::generateUniqueID(); 46 $issueInstant = OneLogin_Saml2_Utils::parseTime2SAML(time()); 47 48 $subjectStr = ""; 49 if (isset($nameIdValueReq)) { 50 $subjectStr = <<<SUBJECT 51 52 <saml:Subject> 53 <saml:NameID Format="{$spData['NameIDFormat']}">{$nameIdValueReq}</saml:NameID> 54 <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"></saml:SubjectConfirmation> 55 </saml:Subject> 56SUBJECT; 57 } 58 59 $nameIdPolicyStr = ''; 60 if ($setNameIdPolicy) { 61 $nameIDPolicyFormat = $spData['NameIDFormat']; 62 if (isset($security['wantNameIdEncrypted']) && $security['wantNameIdEncrypted']) { 63 $nameIDPolicyFormat = OneLogin_Saml2_Constants::NAMEID_ENCRYPTED; 64 } 65 66 $nameIdPolicyStr = <<<NAMEIDPOLICY 67 68 <samlp:NameIDPolicy 69 Format="{$nameIDPolicyFormat}" 70 AllowCreate="true" /> 71NAMEIDPOLICY; 72 } 73 74 75 $providerNameStr = ''; 76 $organizationData = $settings->getOrganization(); 77 if (!empty($organizationData)) { 78 $langs = array_keys($organizationData); 79 if (in_array('en-US', $langs)) { 80 $lang = 'en-US'; 81 } else { 82 $lang = $langs[0]; 83 } 84 if (isset($organizationData[$lang]['displayname']) && !empty($organizationData[$lang]['displayname'])) { 85 $providerNameStr = <<<PROVIDERNAME 86 ProviderName="{$organizationData[$lang]['displayname']}" 87PROVIDERNAME; 88 } 89 } 90 91 $forceAuthnStr = ''; 92 if ($forceAuthn) { 93 $forceAuthnStr = <<<FORCEAUTHN 94 95 ForceAuthn="true" 96FORCEAUTHN; 97 } 98 99 $isPassiveStr = ''; 100 if ($isPassive) { 101 $isPassiveStr = <<<ISPASSIVE 102 103 IsPassive="true" 104ISPASSIVE; 105 } 106 107 $requestedAuthnStr = ''; 108 if (isset($security['requestedAuthnContext']) && $security['requestedAuthnContext'] !== false) { 109 $authnComparison = 'exact'; 110 if (isset($security['requestedAuthnContextComparison'])) { 111 $authnComparison = $security['requestedAuthnContextComparison']; 112 } 113 114 $authnComparisonAttr = ''; 115 if (!empty($authnComparison)) { 116 $authnComparisonAttr = sprintf('Comparison="%s"', $authnComparison); 117 } 118 119 if ($security['requestedAuthnContext'] === true) { 120 $requestedAuthnStr = <<<REQUESTEDAUTHN 121 122 <samlp:RequestedAuthnContext $authnComparisonAttr> 123 <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml:AuthnContextClassRef> 124 </samlp:RequestedAuthnContext> 125REQUESTEDAUTHN; 126 } else { 127 $requestedAuthnStr .= " <samlp:RequestedAuthnContext $authnComparisonAttr>\n"; 128 foreach ($security['requestedAuthnContext'] as $contextValue) { 129 $requestedAuthnStr .= " <saml:AuthnContextClassRef>".$contextValue."</saml:AuthnContextClassRef>\n"; 130 } 131 $requestedAuthnStr .= ' </samlp:RequestedAuthnContext>'; 132 } 133 } 134 135 $spEntityId = htmlspecialchars($spData['entityId'], ENT_QUOTES); 136 $acsUrl = htmlspecialchars($spData['assertionConsumerService']['url'], ENT_QUOTES); 137 $request = <<<AUTHNREQUEST 138<samlp:AuthnRequest 139 xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" 140 xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" 141 ID="$id" 142 Version="2.0" 143{$providerNameStr}{$forceAuthnStr}{$isPassiveStr} 144 IssueInstant="$issueInstant" 145 Destination="{$idpData['singleSignOnService']['url']}" 146 ProtocolBinding="{$spData['assertionConsumerService']['binding']}" 147 AssertionConsumerServiceURL="{$acsUrl}"> 148 <saml:Issuer>{$spEntityId}</saml:Issuer>{$subjectStr}{$nameIdPolicyStr}{$requestedAuthnStr} 149</samlp:AuthnRequest> 150AUTHNREQUEST; 151 152 $this->_id = $id; 153 $this->_authnRequest = $request; 154 } 155 156 /** 157 * Returns deflated, base64 encoded, unsigned AuthnRequest. 158 * 159 * @param bool|null $deflate Whether or not we should 'gzdeflate' the request body before we return it. 160 * 161 * @return string 162 */ 163 public function getRequest($deflate = null) 164 { 165 $subject = $this->_authnRequest; 166 167 if (is_null($deflate)) { 168 $deflate = $this->_settings->shouldCompressRequests(); 169 } 170 171 if ($deflate) { 172 $subject = gzdeflate($this->_authnRequest); 173 } 174 175 $base64Request = base64_encode($subject); 176 return $base64Request; 177 } 178 179 /** 180 * Returns the AuthNRequest ID. 181 * 182 * @return string 183 */ 184 public function getId() 185 { 186 return $this->_id; 187 } 188 189 /** 190 * Returns the XML that will be sent as part of the request 191 * 192 * @return string 193 */ 194 public function getXML() 195 { 196 return $this->_authnRequest; 197 } 198} 199