Kevin Schroeder writes; I forget why, but a few days ago I started doing some digging around with authentication in Zend_Amf_Server. I had figured that I would add an adapter to the Zend_Amf_Server::setAuth() method and that would be it.
But I was wrong.
AMF allows for multiple request bodies to be sent at the same time. Of those there are several “special” types of commands. One of those commands is logging in. What this means is that you don’t need a method that logs someone in for you. Zend_Amf_Server handles authentication separately from your service classes.
Authentication for Zend_Amf_Server will generally use a combination of Zend_Auth and Zend_Acl components. Zend_Auth is used to provide the credential verification while Zend_Acl is used to validate that the current user user can access the requested service method. It is actually a relatively trivial task to restrict access to non-logged in users using the method that I will describe here.
The first step in the process is to create an authentication adapter. It really doesn’t matter what you’re using. What matters is that the adapter returns an identity object with a property called “role”. The built in ACL handle expects this to be part of the identity object.
class Auth extends Zend_Amf_Auth_Abstract
{
const LOGGEDIN_ROLE = 'loggedin';
public function authenticate()
{
$identity = new stdClass();
$result = Zend_Auth_Result::FAILURE;
// Do a proper login, y'all
if ($this->_username == 'test' && $this->_password == 'test') {
$identity->role = self::LOGGEDIN_ROLE;
$result = Zend_Auth_Result::SUCCESS;
} else {
$identity->role = Zend_Amf_Constants::GUEST_ROLE;
}
return new Zend_Auth_Result($result, $identity);
}
}
The Auth class extends Zend_Amf_Auth_Abstract because Flex seems to require username and passwords as being the only mechanism for passing credentials. The abstract class defines a method that hooks in with the special commands and passes the special credentials to the special adapter. Clearly your authentication mechanism should be better than the one that I put in here, but you’ll get the idea. The most important part is adding the role property to the identity object and passing it to the Zend_Auth_Result object.
Then in your gateway you need to add this adapter as well as create an simple ACL.
$server = new Zend_Amf_Server();
$server->addDirectory(realpath(__DIR__.'/../services'));
$acl = new Zend_Acl();
$acl->addRole(Auth::LOGGEDIN_ROLE);
$acl->allow(Auth::LOGGEDIN_ROLE);
$server->setAcl($acl);
$auth = new Auth();
$server->setAuth($auth);
echo $server->handle();
This adds the new Auth role to the ACL and says that it has access to everything. Since there is no place where I allow guest access (denoted by Zend_Amf_Constants::GUEST_ROLE in the adapter) guest requests will be denied.
With just this little bit of code you now have a mechanism that will provide restricted access to all of your service objects.