SAML SSO curl php

 
0
 

Hello,

I am trying to use sso login on my website where my clients can login to a certain company X without signing in again. I spoke to the developers at the company X. they told me that they are using SAML 2.0 for exchanging authentication and authorization.

I was asked to purchase a certificate and submit it to them so they can generate a saml with the private key and all the attributes names i need to post. So they gave me the SAML file and url so i can post the data.

They have also told me that i need to do some encoding from utf8 to base64 before posting the saml for authentication and they gave me this snippet of C# code as an example.

string responseStr = doc.OuterXml;
byte[] base64EncodedBytes = Encoding.UTF8.GetBytes(responseStr);
string returnValue = System.Convert.ToBase64String(base64EncodedBytes);

After looking and researching i found that i can post xml file using curl so i start putting all codes together and this is what i came up with.

<?php $url = "https://my.sandbox.CompanyX.com/sso/authenticate.ashx";

$filename = "new.xml";
$handle = fopen($filename, "r");
$XPost = fread($handle, filesize($filename));

$XPost_utf8 = utf8_encode($XPost);  //Encode to utf8
$XPost_base64 = base64_encode($XPost_utf8); //Encode to base64

fclose($handle);

$ch = curl_init(); // initialize curl handle

////////////////////added otpion////////////////
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, TRUE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, TURE);
//curl_setopt($ch, CURLOPT_CAINFO,$_SERVER['DOCUMENT_ROOT']."/cacert.pem");
////////////////////////////////////////////

curl_setopt($ch, CURLOPT_VERBOSE, 1); // set url to post to
curl_setopt($ch, CURLOPT_URL, $url); // set url to post to
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // return into a variable
//curl_setopt($ch, CURLOPT_HTTPHEADER, Array("Content-Type: text/xml"));
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 40); // times out after 4s
curl_setopt($ch, CURLOPT_POSTFIELDS, $XPost_base64); // add POST fields
curl_setopt($ch, CURLOPT_POST, 1);

$result = curl_exec($ch); // run the whole process
if (empty($result)) {
// some kind of an error happened
die(curl_error($ch));
curl_close($ch); // close cURL handler
} else {
$info = curl_getinfo($ch);
curl_close($ch); // close cURL handler

if (empty($info['http_code'])) {
die("No HTTP code was returned");
} 

else {
// load the HTTP codes
//$http_codes = parse_ini_file("response.inc");

// echo results
echo "The server responded: \n";
echo $info['http_code'] . " " . $http_codes[$info['http_code']];
}
}

echo "RESULT: $result"; //contains response from server

?>

My code is generating this error when i post:


The server responded: 302 RESULT: HTTP/1.1 100 Continue HTTP/1.1 302 Found Cache-Control: private Content-Type: text/html; charset=utf-8 Location: http://my.sandbox.companyx.com/SignUpNow.aspx?err=The+lenght+of+CompanyId+and+encryptedUserData+can%27t+be+zero. Server: Microsoft-IIS/7.5 X-AspNet-Version: 4.0.30319 X-Powered-By: ASP.NET Date: Wed, 17 Jul 2013 18:48:51 GMT Content-Length: 226 P3P: CP=OUR CUR DEV IVAi IVDi HIS IND UNI PUR NAV INT DEM CNT PRE
Object moved to here. <---- thats a link that takes me to their signup page

The developer at companyx told me that i need to use SAMLResponse as the name of the form value, I am passing in which is in my situation is $XPost_base64 ( i think )

I don't if i am on the right track or the whole approach i am using is wrong.

Note: i attached a sample SAML file

I really appreciate any help.

Thank you in advance.

Attachments SAML2.0-Example_.txt (6.37 KB)
<samlp:Response IssueInstant="2012-01-13T15:37:01.358Z" ID="doOlI8jnuKrY5rDHmmSIOqQm2Bx" Version="2.0" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">
	<saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">company:federation:saml2</saml:Issuer>
	<samlp:Status>
		<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
	</samlp:Status>
	<saml:Assertion Version="2.0" IssueInstant="2012-01-13T15:37:01.630Z" ID="S1gGugY4t9YRH8ISyHcTn6WPjtF" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">
		<saml:Issuer>company:federation:saml2</saml:Issuer>
		<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
			<ds:SignedInfo>
				<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
				<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
				<ds:Reference URI="#S1gGugY4t9YRH8ISyHcTn6WPjtF">
					<ds:Transforms>
						<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
						<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
					</ds:Transforms>
					<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
					<ds:DigestValue>4C9d6uWz5hyGEsCvqTAs06q15Es=</ds:DigestValue>
				</ds:Reference>
			</ds:SignedInfo>
			<ds:SignatureValue> TfgVsAM0tN88999bixGzxw2AyPCXvwi74Js0KUVFpFJItIeID99898987yyjkU9zdPRmuhrL Cz/Keo9dBEGdQbWq4SkdhsK9du4FzlwN3kKyFUWfXznrIaN2yPdVUBbyDTOwomBvuYsBQnrcG0kh zTGiwPcy01P7O4kBA88= </ds:SignatureValue>
			<ds:KeyInfo>
				<ds:X509Data>
					<ds:X509Certificate> MIICQTCCAaqgAwIBAgIG9898SIb3DQEBBQUAMGQxCzAJBgNVBAYTAlVTMQswCQYD VQQIEwJJTDEUMBIGA1UEBxMLZWFzdCBwZW9yaWExDDAKBgNVBAoTA3NwZDEMMAoGA1UECxMDc3Bk MRYwFAYDVQQDEw1uMWZlZHNpZ25jZXJ0MB4XDTA4MDIxODE1MzIzN1oXDTEzMDIxNjE1MzIzN1ow ZDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklMMRQwEgYDVQQHEwtlYXN0IHBlb3JpYTEMMAoGA1UE ChMDc3BkMQwwCgYDVQQLEwNzcGQxFjAUBgNVBAMTDW4xZmVkc2lnbmNlcnQwgZ8wDQYJKoZIhvcN AQEBBQADgY0AMIGJAoGBAIIuHvtIcc+bHJeZBBCfBOFSO/UKHmgzQ2/fVhNXImemll2kZSt1wijP kJRaV/dqAcs4ZUtQ5Jc02dth4tgH6Y//95oscSc0ErXQ+9MkzxoK/ampMF4XqJ41iHxoD52DubrZ XFuk2OKmYXbJTkfUsWJJ0S7My/2IzV9TxRdB9PQbAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAImZT 1Dc1mOapYlIzqtU3zO8QKbMWBKCKQlFLCcXu+fv1b7kLiGQKJKhfC6EmDcURT7tTjgsFSfl2Vb8f Tm0DgC3ORcq9xSqzME3Vei80oKKEF5RkulYRe79oScatTBY9T8N01+1BsMmvn+QglAn4x1nLQRMb rpIE2a6CXi3S0qQ= </ds:X509Certificate>
				</ds:X509Data>
				<ds:KeyValue>
					<ds:RSAKeyValue>
						<ds:Modulus> gi4e+0hxz5scl5kEEJ8E4VI9898XaRlK3XCKM+QlFpX92oByzhlS1DklzTZ 22Hi2Afpj//3mixxJzQStdD70yTPGgr9qakwXheonjWIfGgPnYO5utlcW6TY4qZhdslOR9SxYknR LszL/YjNX1PFF0H09Bs= </ds:Modulus>
						<ds:Exponent>AQAB</ds:Exponent>
					</ds:RSAKeyValue>
				</ds:KeyValue>
			</ds:KeyInfo>
		</ds:Signature>
		<saml:Subject>
			<saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">catrecid=PPS-000A0E3A,OU=People,dc=cat,dc=com</saml:NameID>
			<saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
				<saml:SubjectConfirmationData NotOnOrAfter="2012-01-13T15:42:01.630Z" Recipient="https://my.company.com/sso/authenticate.ashx"/>
			</saml:SubjectConfirmation>
		</saml:Subject>
		<saml:Conditions NotOnOrAfter="2012-01-13T15:42:01.630Z" NotBefore="2012-01-13T15:32:01.630Z">
			<saml:AudienceRestriction>
				<saml:Audience>company-Salepublications</saml:Audience>
			</saml:AudienceRestriction>
		</saml:Conditions>
		<saml:AuthnStatement AuthnInstant="2012-01-13T15:37:01.630Z" SessionIndex="S1gGugY4t9YRH8ISyHcTn6WPjtF">
			<saml:AuthnContext>
				<saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml:AuthnContextClassRef>
			</saml:AuthnContext>
		</saml:AuthnStatement>
		<saml:AttributeStatement xmlns:xs="http://www.w3.org/2001/XMLSchema">
			<saml:Attribute NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" Name="lastName">
				<saml:AttributeValue xsi:type="xs:string" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Smith</saml:AttributeValue>
			</saml:Attribute>
			<saml:Attribute NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" Name="errorUrl">
				<saml:AttributeValue xsi:type="xs:string" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">http://google.com</saml:AttributeValue>
			</saml:Attribute>
			<saml:Attribute NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" Name="organizationId">
				<saml:AttributeValue xsi:type="xs:string" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">{5EDF3381-6EEA-40C9-8A1A-01C672B2B1C9}</saml:AttributeValue>
			</saml:Attribute>
			<saml:Attribute NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" Name="companyName">
				<saml:AttributeValue xsi:type="xs:string" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">company Inc.</saml:AttributeValue>
			</saml:Attribute>
			<saml:Attribute NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" Name="authorizedMarketPlaceUrl">
				<saml:AttributeValue xsi:type="xs:string" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Sales,Developers</saml:AttributeValue>
			</saml:Attribute>
			<saml:Attribute NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" Name="email">
				<saml:AttributeValue xsi:type="xs:string" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">jsmith@company.com</saml:AttributeValue>
			</saml:Attribute>
			<saml:Attribute NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" Name="initialCredit">
				<saml:AttributeValue xsi:type="xs:string" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">300.00</saml:AttributeValue>
			</saml:Attribute>
			<saml:Attribute NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" Name="companyId">
				<saml:AttributeValue xsi:type="xs:string" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">{79C3920B-CC06-4A96-9540-C4C45F172998}</saml:AttributeValue>
			</saml:Attribute>
			<saml:Attribute NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" Name="firstName">
				<saml:AttributeValue xsi:type="xs:string" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">John</saml:AttributeValue>
			</saml:Attribute>
			<saml:Attribute NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" Name="redirectUrl">
				<saml:AttributeValue xsi:type="xs:string" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">https://marketplace.company.com/Sales</saml:AttributeValue>
			</saml:Attribute>
		</saml:AttributeStatement>
	</saml:Assertion>
</samlp:Response>
 
0
 

Hi,

You need to ask company x what are the form attributes that are needing response. Plus, I honestly believe thay you should iterate through the xml file items and then apply base64_encode on them..

I am really surprised by no support from company X, it is their API and not yours.. Giving you the C# codes does not equate to implementation in PHP. Not all PHP programmers codes in C#..

In C#, this code right here is un-instantiated array

byte[];

then they iterated the items in xml file, cast items to string, convert them to utf8, and lastly encode to base64.

How are we going to implement the same logic in PHP programming? The answer is pretty simple. Take my sample codes below for example. I don't like the pre-mature foreach loop within the function. However, that leaves me choice. We cannot apply casting, encryption, to any existing array, without serializing them. I am not to implement serialization in my example, because Company X never told you that.

So, here we go. Suppose, we have an xml file... NOTE: I will be using xml_load string here instead of xml load file to make the example a lot clearer..In this example, only the values are encoded..

XML is just an example, use your own, fruits is a lot easier to digest than using a different example..

 <?php

    $xml = '<?xml version="1.0" encoding="UTF-8"?>

    <fruits>
    <item>
    <title>Orange</title>
    <color>it is orange</color>
    <taste>Sweet, sour, and tangy</taste>
    <price>1.00</price>
    </item>
    <item>
    <title>Pear</title>
    <color>Yellow Green</color>
    <taste>Sweet and grainy</taste>
    <price>2.00</price>
    </item>
    <item>
    <title>Banana</title>
    <color>Yellow</color>
    <taste>Sweet,bland aftertaste</taste>
    <price>0.50</price>
    </item>
    </fruits>';

    $fruits = simplexml_load_string($xml);
    //print_r($fruits);
    //echo '<br/>';

    function encode_items($xml=array()){
     $out = array();
    foreach ($xml->item as $fruit) {
        $out['title']= (string) base64_encode(utf8_encode($fruit->title));
        $out['color']= (string)base64_encode(utf8_encode($fruit->color));
        $out['taste']= (string)base64_encode(utf8_encode($fruit->taste));
        $out['price']= (string)base64_encode(utf8_encode($fruit->price));
        $data[] = $out;
    }
    return $data;
    }

    $post_data = (encode_items($fruits));

    print_r($post_data);

You can change the simplexml_load_string($xml) to simplexml_load_file($url_of_your_xml). Please observe how I indexed the xml string line by line.

Your cURL post field should send the output of the function encode_items(). Something like this

curl_setopt($ch, CURLOPT_POSTFIELDS, (encode_items($fruits))); // add POST fields

One last thought, why do you have to describe the API owner as company X. Don't you think it would not help if we found out which one. I have more than 15 API applications under my belt e.g. evernote, youtube, paypal,google,soundcloud,mandrill,easypost,dwolla,NHTSA,APIGEE,SUNLIGHT FOUNDATION, NPR (python),wepay,GILT, and many more, and who knows Company X maybe just one of them.. just saying.

 
0
 

No need to its mimeo.

You
This article has been dead for over six months: Start a new discussion instead
Post:
Start New Discussion
Tags Related to this Article