Skip to Content

Introduction


In this blog I will try to explain how can SAP Single Sign On be integrated in a PHP application.

At first we need to see what is Single Sign On at all and why do we need that. One business user works with a set of enterprise applications, which generally have different login data. Since it would be very inefficient to enter so many times user ID and password, a Single Sign On technology can be applied in terms of entering a single password and all other systems becomming accessible without further login.

Now let us see what logon options with SAP systems are available:

    • User ID and password
    • Secure Network Communications (SNC)
    • SAP logon tickets
    • SSL and X.509 client certificates
    • Pluggable Authentication Services (PAS)
    • Security Assertion Markup Language (SAML)
    • Java Authentication and Authorization Service (JAAS)

Where the authentication data is stored depends on the (PHP) application. In this blog I will consider SAP logon tickets as authentication option.


Scenario and Application Structure


The following scenario is used to illustrate the concepts: Check Material Availability. The application displays a form with input fields for a specific material number and type. When the form is submitted, a check is performed and the number of available materials is returned. This service is implemented as an ABAP service (through RFC) and as a web service. Single Sign On with SAP logon tickets can be used to authenticate for both of them.

If there is no logon ticket present, the PHP application asks the user for user ID and password. After this it authenticates him to the SAP system and receives a logon ticket. This logon ticket is after that saved to a cookie, called MYSAPSSO2

(this is the standard name, used by SAP Enterprise Portal). On each other start of the application this cookie is read and the login form is skipped. On log out the cookie is deleted. In a more sofisticated application log out should be performed also to the SAP system.</p>


Single Sign On with RFC


For this sample the SAPRFC connector for PHP from Eduard Koucký is used.

The RFC service has the following parameters:

    1. Input: plant (string), material (string), unit (string) – what material we address and in which units is the availability to be returned.
    2. Output: q_av_plt (string) – amount available.

The application consists of the following files:

    1. login.php – the login form and code to optain SAP logon ticket.
    2. logout.php – cleans the MYSAPSSO2 cookie in browser.
    3. index.php – the material check form.
    4. material_check.php – calls the material check RFC service.
    5. login_routines.inc.php – check for login errors.
    6. cookie.inc.php – cookie handling functions.
    7. common.inc.php – contains the RFC calls.

The contents of the source files follows:


login.php


In this example file the most important thing to note is that with opening the SAPRFC connection we set the GETSSO2 parameter to 1, which instructs the R/3 system to create an SAP logon ticket. The created ticket is then retrieved with saprfc_get_ticket().








          
          

Material Check Demo Logon Page


          

RFC and Single Sign On with PHP


          

This demo requires, that cookies in Your browser are enabled.

Login Name:

Password:

function login_to_SAP($login_name, $password) {
$conn = array ( “ASHOST” => “mysapsystem”,
“SYSNR” => “09”,
“CLIENT” => “004”,
“USER” => $login_name,
“PASSWD” => $password,
“GETSSO2” => “1”,
“GWHOST” =>”mysapsystem”,
“R3NAME” =>”MSS”,
“LANG” =>”EN”);

// Initialize SAPRFC library.
$rfc = saprfc_open ($conn);
if (! $rfc )
{
saprfc_close($rfc);
return “ER: reason=” . LOGIN_REASON_FAILED . “&desc=” . saprfc_error();
}

$logon_ticket = saprfc_get_ticket($rfc);

if ($logon_ticket==null) return “ER: reason=” . LOGIN_REASON_CANNOT_GET_TICKET . “&desc=” . saprfc_error();

// Close SAPRFC library.
saprfc_close($rfc);

return “OK: ” . $logon_ticket;
}

?>


logout.php









          
          

Logout


          Logout successful.


          Log In
     </body>
</html></textarea>


index.php









          
          

Check Material Availability


          

RFC and Single Sign On with PHP


          echo “The material you requested is “;
if ($avail>0) {
echo “available.
Amount = ” . $avail . ““;
}
else {
echo “not available.”;
}
?>


          Back to form

          Log Out


material_check.php









          
          

Check Material Availability


          

RFC and Single Sign On with PHP


          echo “The material you requested is “;
if ($avail>0) {
echo “available.
Amount = ” . $avail . ““;
}
else {
echo “not available.”;
}
?>


          View Script


          Back to form

          Back to menu

          Log Out


login_routines.inc.php


     “Cannot get SAP logon ticket. Server error.”,
);


/**
*

  • function check_login();

*

  • Check if user is authorized. If not – redirect to the login page.

*/
function check_login() {
     $ticket = get_cookie_value(SSOCOOKIE);
     if (null==$ticket) {
          if (array_key_exists(‘attempt’, $_GET))
               redirect(“login.php?reason=” . LOGIN_REASON_PASSWORD_NOT_SET);
          else
               redirect(“login.php”);
     }
}


function logout() {
     // Warning!!! In a real implementation only deleting the cookie is not enough.
     // We have also to be sure, that user has logged out from R/3.
     if (!delete_cookie(SSOCOOKIE)) die(“Cannot log out. Cookies not available.”);
}


function get_reason($login_reasons) {
     $app = ” “;
          
     if (!array_key_exists(‘reason’, $_GET)) return $login_reasons[LOGIN_REASON_DEFAULT] . $app;
     
     if (array_key_exists($_GET[‘reason’], $login_reasons)) {
          return “” . $login_reasons[$_GET[‘reason’]] . $app . ““;
}
else {
return “Error code: ” . $_GET[‘reason’] . “. Please, contact your SAP advisor for further details.” . $app . ““;
}
}

?>


cookie.inc.php


<?php


// Constants.
define(“SSOCOOKIE”, “MYSAPSSO2”);


/**
*

  • function get_cookie_value($cookie_name);

*

  • Displays a cookie from user’s browser.

*

  • Provided parameter is cookie name.

*

  • Return value is the cookie value, or null if not found.

*/
function get_cookie_value($cookie_name) {
     if (null==$_COOKIE) return null;
     if (array_key_exists($cookie_name, $_COOKIE)) {
          $val = $_COOKIE[$cookie_name];
          return $val;
     }
     return null;
}


/**
*

  • function set_cookie_value($cookie_name, $cookie_value, $days_valid);

*

  • Saves a cookie in user’s browser.

*

  • Provided parameters are cookie name and value and number of days,

  • the cookie remains valid.

*

  • Return values are true on success and false on failure.

  • Failure normally means, that user has disabled cookies in the browser.

*/
function set_cookie_value($cookie_name, $cookie_value, $days_valid) {
     $expires = time() + ($days_valid * 24 * 60 * 60);
                              // x days; 24 hours; 60 mins; 60 secs


     if (setcookie($cookie_name, $cookie_value, $expires)) {
          return true;
     }
     else {
          return false;
     }
}


/**
*

  • function delete_cookie($cookie_name);

*

  • Delete a cookie in user’s browser.

*

  • Provided parameters are cookie name and value and number of days,

  • the cookie remains valid.

*

  • Return values are true on success and false on failure.

  • Failure normally means, that user has disabled cookies in the browser.

*/
function delete_cookie($cookie_name) {
     return set_cookie_value($cookie_name, null, 0);
}


function redirect($location) {
     Header(“Location: ” . $location);
}


?></textarea>


common.inc.php



Single Sign On with Web Services


In the web service sample the internal web service extension for PHP 5 is used.

The web service has the same parameters like the RFC one:

    1. Input: plant (string), material (string), unit (string) – what material we address and in which units is the availability to be returned.
    2. Output: availability (string) – amount available.


Besides that it is assumed that the web service is configured with basic HTTP security and with option to accept/issue SAP logon ticket. For more information how to do that please follow this link .

Like the RFC one, this application also consists of the following files:

    1. login.php – the login form and code to optain SAP logon ticket.
    2. logout.php – cleans the MYSAPSSO2 cookie in browser.
    3. index.php – the material check form.
    4. material_check.php – calls the material check RFC service.
    5. login_routines.inc.php – check for login errors.
    6. cookie.inc.php – cookie handling functions.
    7. common.inc.php – contains the RFC calls.

The files are very similar, but the only difference is that the RFC call functions are changed with web service call ones.


login.php









          
          

Material Check Demo Logon Page


          

Web Services and Single Sign On with PHP


          


logout.php









          
          

Logout


          Logout successful.


          Log In
     </body>
</html></textarea>


index.php









          
          

Check Material Availability


          

Web Services and Single Sign On with PHP


          You have been logged on via Single Sign On.

Please, enter the check criteria:

PLANT: (Example values: “1000”)
Material: (Example values: “100-100”, “100-200”)
Unit (Example values: “PC”)


          Back


          Log Out


material_check.php









          
          

Check Material Availability


          

RFC and Single Sign On with PHP


          echo “The material you requested is “;
if ($avail>0) {
echo “available.
Amount = ” . $avail . ““;
}
else {
echo “not available.”;
}
?>


          View Script


          Back to form

          Log Out


login_routines.inc.php


     “Cannot get SAP logon ticket. Server error.”,
);


/**
*

  • function check_login();

*

  • Check if user is authorized. If not – redirect to the login page.

*/
function check_login() {
     $ticket = get_cookie_value(SSOCOOKIE);
     if (null==$ticket) {
          if (array_key_exists(‘attempt’, $_GET))
               redirect(“login.php?reason=” . LOGIN_REASON_PASSWORD_NOT_SET);
          else
               redirect(“login.php”);
     }
}


function logout() {
     // Warning!!! In a real implementation only deleting the cookie is not enough.
     // We have also to be sure, that user has logged out from R/3.
     if (!delete_cookie(SSOCOOKIE)) die(“Cannot log out. Cookies not available.”);
}


function get_reason($login_reasons) {
     $app = ” “;
          
     if (!array_key_exists(‘reason’, $_GET)) return $login_reasons[LOGIN_REASON_DEFAULT] . $app;
     
     if (array_key_exists($_GET[‘reason’], $login_reasons)) {
          return “” . $login_reasons[$_GET[‘reason’]] . $app . ““;
}
else {
return “Error code: ” . $_GET[‘reason’] . “. Please, contact your SAP advisor for further details.” . $app . ““;
}
}

?>


cookie.inc.php


<?php


// Constants.
define(“SSOCOOKIE”, “MYSAPSSO2”);
define(“HEADER_NAME”, “Set-Cookie:”);


/**
*

  • function get_cookie_value($cookie_name);

*

  • Displays a cookie from user’s browser.

*

  • Provided parameter is cookie name.

*

  • Return value is the cookie value, or null if not found.

*/
function get_cookie_value($cookie_name) {
     if (null==$_COOKIE) return null;
     if (array_key_exists($cookie_name, $_COOKIE)) {
          $val = $_COOKIE[$cookie_name];
          return $val;
     }
     return null;
}


/**
*

  • function set_cookie_value($cookie_name, $cookie_value, $days_valid);

*

  • Saves a cookie in user’s browser.

*

  • Provided parameters are cookie name and value and number of days,

  • the cookie remains valid.

*

  • Return values are true on success and false on failure.

  • Failure normally means, that user has disabled cookies in the browser.

*/
function set_cookie_value($cookie_name, $cookie_value, $days_valid) {
     $expires = time() + ($days_valid * 24 * 60 * 60);
                              // x days; 24 hours; 60 mins; 60 secs


     if (setcookie($cookie_name, $cookie_value, $expires)) {
          return true;
     }
     else {
          return false;
     }
}


/**
*

  • function delete_cookie($cookie_name);

*

  • Delete a cookie in user’s browser.

*

  • Provided parameters are cookie name and value and number of days,

  • the cookie remains valid.

*

  • Return values are true on success and false on failure.

  • Failure normally means, that user has disabled cookies in the browser.

*/
function delete_cookie($cookie_name) {
     return set_cookie_value($cookie_name, null, 0);
}


function redirect($location) {
     Header(“Location: ” . $location);
}


?></textarea>


common.inc.php



To report this post you need to login first.

5 Comments

You must be Logged on to comment or reply to a post.

  1. Gregor Wolf
    Hello Vasil,

    first of all thank you for this great Blog.

    For the ease of use of your Blog it would be great if you could provide a ZIP Download off all the Files.

    I’ve tried to run your Example on my Debian Linux Box with Apache2, PHP Version 4.3.10-19 and SAPRFC 1.4.1. As soon as I activate the parameter “GETSSO2″=>”1” I’ve got a Segmentation fault message in the Apache Error log. On Windows it seems to work. I’ve also tried PHP 5.2.1-0.dotdeb.1 which also resulted in a Segmentation fault error.

    But for real SSO against external Authentication methods like NTLM or Kerberos PHP has to use the function Module SUSR_CHECK_LOGON_DATA which I’ve described in my Blog Single Sign On with External ID implemented in Ruby. Unfortunately the current version of SAPRFC does not support STRING Import parameters as you can see in my Bug Report: Import Parameter of type STRING not filled.

    I’ve tried to create a Web Service for SUSR_CHECK_LOGON_DATA and connect with HTTPS an X.509 authentication as described in my Blog “Authenticate from PHP to a Web Service using X.509 Certificates” to the Web Service. But here I can’t get the Ticket because SUSR_CHECK_LOGON_DATA does not recognize the HTTPS Connection as equal to SNC. Perhaps you have some suggestions. If we can find a way to utilize SUSR_CHECK_LOGON_DATA via a Web Service all way’s to authenticate are open.

    Regards
    Gregor

    (0) 
    1. Former Member Post author
      Hi, Gregor,

      Glad to hear from you again after TechEd Amsterdam.

      This problem with the segmentation fault should occur, when you call saprfc_get_ticket(), right? I had the same problem on Windows machine and tracked it down. In this proxy function of SAPRFC a string buffer is used, which didn’t have enough storage for the string. I sent a patch to Eduard Koucký. It may be that Mr. Koucký has corrected the error and recompiled for Windows, but in the Linux variant is still the old buffer size.
      So you can take the latest sources and compile them, but before installing, check in the source code where the definition of saprfc_get_ticket() is whether the string buffer for the ticket is enough. In the wrong version it was 1024, but must be higher. I set it to 128*1024 for myself, so I can be sure it is enough.

      Concerning the ZIP file – yes, you’re totally right. I will pack the sources soon.

      And regarding the last X.509 authentication – I wonder why do you need a logon ticket at all. I mean providing the certificate should be equivalent way to authentificate. You don’t need additional tickets.

      Best Regards,
      Vasil

      (0) 
      1. Gregor Wolf
        Hi Vasil,

        thank you for your comprehensive reply. I hope to find the time to test out the Linux version with the corrected buffer size.

        I don’t have a public key infrastructure. I only have a certificate for the server and want to do SSL betewen the Apache with PHP and the Web AS speaking SOAP. The clients should be authenticated by Kerberos or NTLM from the Apache server. I only have _SERVER[“AUTH_USER”] and want to use this to authenticate.

        Regards
        Gregor

        (0) 
        1. Former Member Post author
          Hi, Gregor,

          Without PKI you cannot apply the scheme above. Use logon tickets instead.

          Regarding the ZIP file with the samples – SDN doesn’t provide means for attachments to web logs. But you can copy-paste the code from the text area fields.

          Best Regards,
          Vasil

          (0) 

Leave a Reply