In this post I will provide a simple solution to adding customer authentication to the Magento API. How to add functionality to the Magento API has already been properly documented in the Magento wiki page Creating a custom API or extending the Core API, so we will not dive into that.
The idea is to simply call the same function for login() which would be used in the frontend and then check for customer authentication in every API call that requires customer authentication.
NB: Please note that this post is a work-in-progress, your mileage may vary, so please test thorougly before using this solution in a production environment.
Update: changed to use customer session for storing current website and store.
Please let me know if you find any problems with this solution. Thanks!
Don't forget that you also have to setup API access in the Magento administration area.
First you need to define a function in your API class to handle the customer login:
<?php
/**
* Custom API model
*/
class MyCompany_MyModule_Model_Api extends Mage_Api_Model_Resource_Abstract
{
/** @var Mage_Customer_Model_Session */
protected $_customerSession = null;
/**
* Customer authentication.
*
* @param string $website Website code of website to authenticate customer against
* @param string $username Username of customer to authenticate
* @param string $password Password of customer to authenticate
* @return boolean True, if successfully authenticated customer for supplied website; false, otherwise.
*/
public function login( $website, $email, $password )
{
// determine store to login to
$store = $this->_getStore($website);
// get customer session object
$session = $this->_getCustomerSession();
// authenticate customer
$authenticated = $session->login($email, $password);
// return authentication result
return $authenticated;
}
/**
* Logout authenticated customer, if any.
* @return boolean True.
*/
public function logout()
{
// get customer session object
$session = $this->_getCustomerSession();
// logout customer
$session->logout();
return true;
}
Next, you have to check for an authenticated customer in your API functions that require this:
/**
* Do something for an authenticated customer.
*/
public function doSomethingThatRequiresCustomerAuthentication()
{
// check whether customer is actually authenticated
$this->_checkCustomerAuthentication();
// retrieve customer object
$customer = $this->_getAuthenticatedCustomer()
// do something for authenticated customer
...
}
Finally, you have to define the helper functions we have used:
/**
* Check whether a customer has been authenticated in this session.
*
* @return void
* @throws Mage_Core_Exception If customer is not authenticated.
*/
protected function _checkCustomerAuthentication()
{
// get customer session object
$session = $this->_getCustomerSession();
// check whether customer is logged in
if ( !$session->isLoggedIn() ) {
// if customer is not logged in throw an exception
Mage::throwException(Mage::helper('mymodule')->__('Not logged in'));
}
}
/**
* Get authenticated customer object.
*
* @return Mage_Customer_Model_Customer Authenticated customer object.
* @throws Mage_Core_Exception If customer is not authenticated or does not exist.
*/
protected function _getAuthenticatedCustomer()
{
// retrieve authenticated customer ID
$customerId = $this->_getAuthenticatedCustomerId();
if ( $customerId )
{
// load customer
/** @var Mage_Customer_Model_Customer $customer */
$customer = Mage::getModel('customer/customer')
->load($customerId);
if ( $customer->getId() ) {
// if customer exists, return customer object
return $customer;
}
}
// customer not authenticated or does not exist, so throw exception
Mage::throwException(Mage::helper('mymodule')->__('Unknown Customer'));
}
/**
* Get authenticated customer ID.
*
* @return integer Authenticated customer ID, if any; null, otherwise.
*/
protected function _getAuthenticatedCustomerId()
{
// get customer session object
$session = $this->_getCustomerSession();
// return authenticated customer ID, if any
return $session->getCustomerId();
}
/**
* Get store object from supplied website code or from register or session.
*
* @param string $code Code
*/
protected function _getStore( $code = null )
{
// get customer session
$session = $this->_getCustomerSession();
// if website code not supplied, check for selected store in register or selected website in session
if ( null === $code ) {
// try to get selected store from register
$store = Mage::registry('current_store');
if ( $store ) {
return $store;
}
// try to get selected website code from session
$code = $session->getCurrentWebsiteCode();
if ( !$code ) {
// if no store in register or website code in session, throw an exception
Mage::throwException(Mage::helper('mymodule')->__('No Store set'));
}
}
// load website from code
/** @var Mage_Core_Model_Website $website */
$website = Mage::getModel('core/website')
->load($code, 'code');
if ( !$website->getId() ) {
// if unknown website, throw an exception
Mage::throwException(Mage::helper('mymodule')->__('Invalid Store') . $code);
}
// get the default store of the website
$store = $website->getDefaultStore();
// register the current store
Mage::app()->setCurrentStore($store);
Mage::register('current_store', $store, true);
// set the current website code in the session
$session->setCurrentWebsiteCode($website->getCode());
// return store object
return $store;
}
/**
* @return Mage_Customer_Model_Session
*/
protected function _getCustomerSession()
{
if ( !$this->_customerSession ) {
$this->_customerSession = Mage::getSingleton('customer/session');
}
return $this->_customerSession;
}
...
}
Please let me know if this works for you or not!