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.

Recommended Answers

All 2 Replies

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.

No need to its mimeo.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.