Back to blog home

Session Sharing via API

Magento already ships with a rich API of functions for external client applications, and some of them even work as documented. When coming to implement session sharing for a client, there is a crucial omission - no way to log the customer in.

Normally, when a customer logs into a website, they are identified to the server by a session ID stored in a cookie. Every time the browser makes a new page request, the session ID is provided to the server so it can load the appropriate details for the logged-in customer. These cookies are only made available to sites within a certain domain, and rightly so, since this prevents mynewdietplan.com knowing just how often you've been to beerandwurst.com.

Before cookie saving became standard, websites that required login sessions (advanced websites at the time) would pass the session identifier as a URL parameter. Aside from making for unattractive URLs, this may present a security risk since anyone with the URL can "be" the customer. Thus, session sharing is a bit of a naughty word for developers. Despite the proliferation of various technologies to work around this (obligatory xkcd), using a session ID as a URL parameter remains one of the simplest and most common methods to share sessions between domains.

Magento accepts session IDs as URL parameters by default; this can be changed in System -> Configuration -> Web -> Session Validation Settings -> Use SID on Frontend. So for a client application using the Magento API, a customer can continue to be logged in after being linked to the store website if this parameter is set based on the session ID generated when the customer logged into the client app. Creating a customer login API is simple in Magento:

<?php
public function login($email, $password) {
$session = Mage::getSingleton('customer/session');
if($session->login($email, $password))
return $session->getSessionId();
else
return false;
}

Now the client application is logged in, how does it pass the session ID through the API for subsequent requests, for example checking order status? Passing the session ID as a _GET parameter is not trivial with PHP's SoapClient. But if we pass it as a parameter, how to force Magento to use it?

Mage_Core_Model_Session_Abstract_Varien provides a hint in the start() method:

<?php
    // potential custom logic for session id (ex. switching between hosts)
    $this->setSessionId();

 

Overriding this method to pass the session ID parameter given by the API instead of null, the customer's login session can be preserved between API calls. Caveat scriptor: whichever session is loaded first will be the one that sets the session ID for that request. So if you make this change in customer/session, it won't work for requests that first load core/session. Magento frontend pages seem to load core/session first, so to enable this behaviour for the frontend, make sure the tweak is done here, then make sure your API loads core/session before other sessions. If you want to restrict the login session persistence to the API, judicious selection of the session model will achieve this.

As a side note, you can change the name of the _GET parameter from which magento pulls the session ID, the config parameter is frontend/session/query_param.