<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Tom&#039;s Blog &#187; air</title>
	<atom:link href="http://www.encapsulated.org/blog/tag/air/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.encapsulated.org/blog</link>
	<description>An analog guy in a digital world</description>
	<lastBuildDate>Tue, 15 Dec 2009 20:46:04 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Security with Zend_AMF and Flex &#8211; Part 2: Practise</title>
		<link>http://www.encapsulated.org/blog/2009/04/15/security-with-zend_amf-and-flex-part-2-practise/</link>
		<comments>http://www.encapsulated.org/blog/2009/04/15/security-with-zend_amf-and-flex-part-2-practise/#comments</comments>
		<pubDate>Wed, 15 Apr 2009 21:58:45 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[air]]></category>
		<category><![CDATA[flex]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[zend_amf]]></category>

		<guid isPermaLink="false">http://www.encapsulated.org/blog/?p=31</guid>
		<description><![CDATA[In my previous post &#8220;Security with Zend_AMF and Flex &#8211; Part 1: Theory&#8220;, I explained the theory behind securing your Flex-PHP calls. After the theory comes the practise. I will only provide snippets for the PHP side of this story, as I&#8217;m totally ignorant about Flex and ActionScript. I used Zend_AMF, written by Wade Arnold, [...]]]></description>
			<content:encoded><![CDATA[<p>In my previous post &#8220;<a title="Security with Zend_AMF and Flex - Part 1: Theory" href="http://www.encapsulated.org/blog/2009/04/05/security-with-zend_amf-and-flex-part-1-theory/">Security with Zend_AMF and Flex &#8211; Part 1: Theory</a>&#8220;, I explained the theory behind securing your Flex-PHP calls. After the theory comes the practise. I will only provide snippets for the PHP side of this story, as I&#8217;m totally ignorant about Flex and ActionScript. I used Zend_AMF, written by <a title="Wade Arnold" href="http://wadearnold.com/blog/">Wade Arnold</a>, to handle all the communications between Flex and PHP. If you need to know the basics, please <a href="http://framework.zend.com/manual/en/zend.amf.html">read the documentation</a> first.<br />
<span id="more-31"></span></p>
<p><strong>Project structure</strong></p>
<p>For the project, I used a slightly modified <a title="Application layout" href="http://framework.zend.com/wiki/display/ZFDEV/Choosing+Your+Application%27s+Directory+Layout#ChoosingYourApplication%27sDirectoryLayout-ConventionalModular">Conventional Modular</a> layout. The basics remains the same, but I have added support for so called versions of the application. The layout I maintain is not really important for the project. However, at the end of the article, you&#8217;ll be able to download everything, and I thought it necessary to explain the structure first. All code is part of the default module, and all classes are located in the &#8220;models&#8221; directory.</p>
<div id="attachment_51" class="wp-caption alignnone" style="width: 486px"><img class="size-full wp-image-51" src="http://www.encapsulated.org/blog/wp-content/uploads/2009/04/screenshot.png" alt="Application layout" width="476" height="729" /><p class="wp-caption-text">Application layout</p></div>
<p><strong>The remoting endpoint</strong></p>
<p>Flex and AIR need to connect to an endpoint. A URL you provide, the point of access to your API. I have created only 1 endpoint. Ideally, you should make 2 endpoints: one for logging in, and one for the rest of the calls. That way, in the future, you could do the login process via an SSL secured line. The remoting endpoint is located in the <em>IndexController.php</em>, since that file is the door to the outside world for the project.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
</pre></td><td class="code"><pre class="php" style="font-family:monospace;">	<span style="color: #666666; font-style: italic;">// Explicitly loading dependencies</span>
	Zend_Loader<span style="color: #339933;">::</span><span style="color: #004000;">loadClass</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Proxies_AMF_System&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	Zend_Loader<span style="color: #339933;">::</span><span style="color: #004000;">loadClass</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Proxies_AMF_Login&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	Zend_Loader<span style="color: #339933;">::</span><span style="color: #004000;">loadClass</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;AMF_VO_Error&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	Zend_Loader<span style="color: #339933;">::</span><span style="color: #004000;">loadClass</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;AMF_VO_Message&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">class</span> IndexController <span style="color: #000000; font-weight: bold;">extends</span> Zend_Controller_Action<span style="color: #009900;">&#123;</span>
		<span style="color: #009933; font-style: italic;">/**
		 * Everything to handle the rest of the API requests
		 */</span>
		<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> indexAction<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
			<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getHelper</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Layout&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">disableLayout</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getHelper</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;ViewRenderer&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setNoRender</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
			<span style="color: #000088;">$server</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Zend_Amf_Server<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			<span style="color: #000088;">$server</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addDirectory</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">dirname</span><span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">__FILE__</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot;../models/&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			<span style="color: #000088;">$server</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setClassMap</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;MessageVO&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;AMF_VO_Message&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			<span style="color: #000088;">$server</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setClassMap</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;ErrorVO&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;AMF_VO_Error&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			<span style="color: #000088;">$server</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setProduction</span><span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			<span style="color: #000088;">$response</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$server</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">handle</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			<span style="color: #b1b100;">echo</span> <span style="color: #000088;">$response</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
	<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Basically, the indexAction is where my endpoints is. There I set up the Zend_AMF server. After setting it up, the server is ready to listen to requests. All requests are handled by the classes from the folder specified with <em>addDirectory()</em>. In our case, the Proxy classes will handle all the requests. After specifying the directory of the classes, we set up the class mapping. Here, we tell Zend_AMF, how the mapping should be between our PHP classes on the server side, and the Flex classes on the client side. In my case, all Flex classes end with &#8220;VO&#8221;. Once the mapping is complete, our server is ready to give a response to the client. Note that I explicitly load every class in IndexController.php. For some reason, Zend_AMF isn&#8217;t able to use autoloading, which is a too bad.</p>
<p><strong>Responses to the client</strong></p>
<p>To have a cleaner interface, I have opted to return structured responses to the Flex client. When the client makes a call, there are only 2 kind of responses he can expect. When the call is successful, the response will be an object of the type <em>AMF_VO_Message</em> that&#8217;s being mapped to a <em>MessageVO</em> in Flex. Or it will be an object of the type <em>AMF_VO_Error</em>, mapped to <em>ErrorVO</em>, when an exception is thrown. This is very easy for the client side coder. All other data is encapsulated in the <em>AMF_VO_Message</em> object, and that makes it easy to process everything. It&#8217;s also easier for the PHP developer, since it is now possible to return a lot more information to the client. If you decide to use caching, then the <em>AMF_VO_Message</em> response can contain information about that; timestamps; transaction id&#8217;s; &#8230; Anything you would expect an API to return.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
</pre></td><td class="code"><pre class="php" style="font-family:monospace;">    <span style="color: #009933; font-style: italic;">/**
     * This class is used to wrap data for output to the AMF adapter
     *
     */</span>
    <span style="color: #000000; font-weight: bold;">class</span> AMF_VO_Message <span style="color: #009900;">&#123;</span>
        <span style="color: #666666; font-style: italic;">// Properties:</span>
        <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000088;">$status</span>		<span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// string</span>
        <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000088;">$timestamp</span>	<span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// string</span>
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000088;">$transaction</span>	<span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// string</span>
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000088;">$data</span>		<span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// mixed</span>
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000088;">$cachehit</span>	<span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// boolean</span>
    <span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>The class is basically a collection of public properties, where I can add data that is useful for the client, like timestamps, transaction-id&#8217;s, &#8230;</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
</pre></td><td class="code"><pre class="php" style="font-family:monospace;">    <span style="color: #009933; font-style: italic;">/**
     * This class is used to wrap data for output to the AMF adapter
     *
     */</span>
    <span style="color: #000000; font-weight: bold;">class</span> AMF_VO_Error <span style="color: #009900;">&#123;</span>
        <span style="color: #666666; font-style: italic;">// Properties:</span>
        <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000088;">$timestamp</span>	<span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// string</span>
        <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000088;">$errorCode</span>	<span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// string</span>
        <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000088;">$file</span>		<span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// string</span>
        <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000088;">$linenumber</span>	<span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// integer</span>
        <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000088;">$messages</span>	<span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// string</span>
    <span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Again, some properties that are useful for error tracking.</p>
<p><strong>First phase: login security</strong></p>
<p>In the first part of this series, I explained how securing the login process works. To initialize a login procedure, the client first needs to notify the server that an authentication attempt will be made. This is done by means of the<em> challenge()</em> function from the <em>Proxies_AMF_Login</em> class. Remember, all available calls are exposed via my so called Proxy classes. This is not mandatory, but a convention I want to impose on the users of the API I&#8217;m going to write. In Flex, the front-end developer can specify the class (proxy) and method (API call) to invoke.</p>
<p>When a client request a challenge from the server, I don&#8217;t necessarily want to know. Therefore, I can keep this function clean and simple. All code is explained with in-line comments.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #009933; font-style: italic;">/**
 * Login proxy class to expose classes to AMF
 *
 */</span>
<span style="color: #000000; font-weight: bold;">class</span> Proxies_AMF_Login <span style="color: #000000; font-weight: bold;">extends</span> Proxies_AMF <span style="color: #009900;">&#123;</span>
        <span style="color: #009933; font-style: italic;">/**
         * Start the authentication session, by requesting a challenge.
         * The client then uses this challenge to calculate a signature (or digest)
         * When signing on, the username &amp;amp; signature is used, instead of the password
         *
         * @return AMF_VO_Message
         */</span>
        <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> challenge<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$arguments</span> <span style="color: #339933;">=</span> <span style="color: #990000;">func_get_args</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">processRequest</span><span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">__FUNCTION__</span><span style="color: #339933;">,</span><span style="color: #000088;">$arguments</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
        protected <span style="color: #000000; font-weight: bold;">function</span> _challenge<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
            <span style="color: #666666; font-style: italic;">// 1. generate the challenge</span>
            <span style="color: #000088;">$challengeString</span> <span style="color: #339933;">=</span> AMF_Login<span style="color: #339933;">::</span><span style="color: #004000;">generateChallenge</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #666666; font-style: italic;">// 2. remember the challenge !</span>
            <span style="color: #000088;">$amfNamespace</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Zend_Session_Namespace<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'AMF_Auth'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #000088;">$amfNamespace</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">challenge</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$challengeString</span><span style="color: #339933;">;</span>
            <span style="color: #666666; font-style: italic;">// 3. return the challenge to the client</span>
            <span style="color: #b1b100;">return</span> <span style="color: #000088;">$challengeString</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #009933; font-style: italic;">/**
         * Authenticate the user
         *
         * @param string $username
         * @param string $signature
         * @return bool|AMF_VO_Error
         */</span>
        <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> signOn<span style="color: #009900;">&#40;</span><span style="color: #000088;">$username</span><span style="color: #339933;">,</span><span style="color: #000088;">$signature</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
			<span style="color: #000088;">$arguments</span> <span style="color: #339933;">=</span> <span style="color: #990000;">func_get_args</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			<span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">processRequest</span><span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">__FUNCTION__</span><span style="color: #339933;">,</span><span style="color: #000088;">$arguments</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	protected <span style="color: #000000; font-weight: bold;">function</span> _signOn<span style="color: #009900;">&#40;</span><span style="color: #000088;">$username</span><span style="color: #339933;">,</span><span style="color: #000088;">$signature</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
            <span style="color: #666666; font-style: italic;">// 1. Digg up the challenge from our memory:</span>
            <span style="color: #000088;">$amfNamespace</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Zend_Session_Namespace<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'AMF_Auth'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #000088;">$challenge</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$amfNamespace</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">challenge</span><span style="color: #339933;">;</span>
&nbsp;
            <span style="color: #666666; font-style: italic;">// 2. Verify if we can authenticate the user</span>
            <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>AMF_Login<span style="color: #339933;">::</span><span style="color: #004000;">signOn</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$username</span><span style="color: #339933;">,</span><span style="color: #000088;">$challenge</span><span style="color: #339933;">,</span><span style="color: #000088;">$signature</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
            	<span style="color: #666666; font-style: italic;">// User authenticated, let's forget the challenge</span>
                <span style="color: #990000;">unset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$amfNamespace</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">challenge</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
            	<span style="color: #666666; font-style: italic;">// Failed to authenticate the user</span>
            	<span style="color: #990000;">unset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$amfNamespace</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">challenge</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		Zend_Auth<span style="color: #339933;">::</span><span style="color: #004000;">getInstance</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">clearIdentity</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                throw <span style="color: #000000; font-weight: bold;">new</span> Exception<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Could not authenticate the user&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>A <em>challenge()</em> call is logically followed by a <em>signOn()</em> request (<em>verifySignature()</em> will be explained later on) to complete the login process. As you can see, for both <em>challenge()</em> and <em>signOn()</em>, there is a protected counterpart <em>_challenge()</em> and <em>_signOn()</em>. This has to do with the <em>processRequest()</em> call in both of the methods. More about that call later on, but for now, you only need to know that <em>processRequest()</em> does some administrative tasks, and wraps the responses for Zend_AMF server in a structured response.</p>
<p>An attentive reader will have noticed that I make use of an AMF_Login class, and I forgot to explain what and how. No wories, it&#8217;s not very mystical. I have just created that class to bundle some functionality. However, it does use some functionality from classes I have not written myself. They fall under the copyright of my employer, and I don&#8217;t want to infringe on that. So I won&#8217;t show you how AMF_User is written, but from the comments, it should be obvious what the purpose is. In the downloadable source, you&#8217;ll find a simplified version of AMF_User, which doesn&#8217;t really do anything, except illustrating the purpose.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> AMF_Login <span style="color: #009900;">&#123;</span>
	<span style="color: #009933; font-style: italic;">/**
	 * Returns a random string, that is used as Challenge for the sign-on
	 * procedure
	 *
	 * @return string
	 */</span>
	<span style="color: #000000; font-weight: bold;">public</span> static <span style="color: #000000; font-weight: bold;">function</span> generateChallenge<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
		<span style="color: #b1b100;">return</span> <span style="color: #990000;">uniqid</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">rand</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">+</span><span style="color: #990000;">time</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> static <span style="color: #000000; font-weight: bold;">function</span> signOn<span style="color: #009900;">&#40;</span><span style="color: #000088;">$username</span><span style="color: #339933;">,</span><span style="color: #000088;">$challenge</span><span style="color: #339933;">,</span><span style="color: #000088;">$signature</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$user</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> AMF_User<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$result</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$user</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">authenticate</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$username</span><span style="color: #339933;">,</span> <span style="color: #000088;">$challenge</span><span style="color: #339933;">,</span> <span style="color: #000088;">$signature</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #b1b100;">return</span> <span style="color: #000088;">$result</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #009933; font-style: italic;">/**
	 * Method to verify if each signature for an API call is valid
	 */</span>
	<span style="color: #000000; font-weight: bold;">public</span> static <span style="color: #000000; font-weight: bold;">function</span> verifySignature<span style="color: #009900;">&#40;</span><span style="color: #000088;">$challenge</span><span style="color: #339933;">,</span><span style="color: #000088;">$signature</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
		<span style="color: #666666; font-style: italic;">// 1. get the password from the session (it was put there during authentication)</span>
		<span style="color: #000088;">$amfNamespace</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Zend_Session_Namespace<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'AMF_Auth'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #666666; font-style: italic;">// 2. calculate signature with given $challenge</span>
		<span style="color: #000088;">$calcSignature</span> <span style="color: #339933;">=</span> <span style="color: #990000;">md5</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">md5</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$amfNamespace</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">password</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$challenge</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #666666; font-style: italic;">// 3. compare calculated signature, with given signature</span>
		<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$calcSignature</span> <span style="color: #339933;">==</span> <span style="color: #000088;">$signature</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
			<span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
		throw <span style="color: #000000; font-weight: bold;">new</span> Exception<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Incorrect signature given&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>This concludes the first part of the security measures: logging in. By now, a user can be logged in, and stay logged in, by means of the browser session.</p>
<p><strong>Second phase: API call security</strong></p>
<p>In the second phase, I want to verify all API calls. What we need, is a way to process every API call, and do a number of actions for each of those call. I want to be able to:</p>
<ul>
<li>Log what calls were made, by what user, what arguments, and what was the response</li>
<li>Have the possibility to cache certain calls</li>
<li>Use Zend_ACL to verify if a certain user has access to certain functionality</li>
<li>Create my structured response</li>
<li>Trap errors (yes, they should be trapped in the <em>ErrorController.php</em>, but I haven&#8217;t fully investigated that option yet)</li>
<li>Write code once, use it multiple times</li>
</ul>
<p>As you can see, there are plenty of requirements. There is one option to fulfil them all: Make sure all calls invoke 1 function that handles all the &#8220;administration&#8221;. The perfect solution exists, and is named <em>__call()</em> in PHP5. If a method does not exist in a class, then the <em>__call()</em> magic function is called with the exact same arguments. There, you can create all functionality for the administration, and then request another function that will do the real work. I know, quite the abstract explanation, but I won&#8217;t go any further on that road because using <em>__call()</em> fails. Zend_AMF uses Zend_Reflection, a <a title="PHP Reflection" href="http://us3.php.net/reflection">PHP reflection class</a>. Simply put, a reflection calls detects all publicly accessible methods and properties of a given class. Since <em>__call()</em> is a magic function, it isn&#8217;t publicly accessible. Hence, it won&#8217;t be discovered by Zend_Reflection, and consequently, Zend_AMF will not be able to make use of your functionality if you rely on <em>__call()</em>. That took me a while to discover, but if you think about it, it&#8217;s quite logical.</p>
<p>To work around this problem, I have decided to create my own <em>__call()</em> method, and I have named it <em>processRequest()</em>. This will do the exact same as I have explained in the paragraph above: handle the administration (logging, caching, &#8230;). The diagram below will immediately shine a light on the working.</p>
<div id="attachment_49" class="wp-caption alignnone" style="width: 398px"><img class="size-full wp-image-49" src="http://www.encapsulated.org/blog/wp-content/uploads/2009/04/diagram12.png" alt="Diagram: handle requests" width="388" height="102" /><p class="wp-caption-text">Diagram: handle requests</p></div>
<p>A request comes in via <em>helloWorld()</em>. It then travels to <em>processRequest()</em> for the administrative tasks. Next it travels to<em> _helloWorld()</em> that will do what needs to be done and give a response. The response then will travel back from <em>_helloWorld()</em> to <em>processRequest()</em>. There, the response is packed in the structured response, and then that structured response is sent back to <em>helloWorld()</em>. There, it is delivered to the Zend_AMF server, and ultimately, to the Flex client.</p>
<p>To write the code only once and use it many times, the only option is to place the <em>processRequest()</em> function in the parent of our Proxy classes: <em>Proxies_AMF.php</em>. Below, you will find a simplified version of the code I have written for a recent project. Everything is explained in in-line comments.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #009933; font-style: italic;">/**
 * AMF proxy class to expose classes to AMF
 *
 */</span>
<span style="color: #000000; font-weight: bold;">class</span> Proxies_AMF <span style="color: #009900;">&#123;</span>
	<span style="color: #666666; font-style: italic;">// Some classes do not need verification, like Login. Only the other API calls should be verified</span>
	<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$exemptVerification</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Proxies_AMF_Login&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	protected <span style="color: #000000; font-weight: bold;">function</span> processRequest<span style="color: #009900;">&#40;</span><span style="color: #000088;">$method</span><span style="color: #339933;">,</span><span style="color: #000088;">$arrArguments</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
		try <span style="color: #009900;">&#123;</span>
			<span style="color: #000088;">$className</span> <span style="color: #339933;">=</span> <span style="color: #990000;">get_class</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
			<span style="color: #666666; font-style: italic;">// Retrieve the parameters to verify the identiy of the requesting party:</span>
			<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">in_array</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$className</span><span style="color: #339933;">,</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">exemptVerification</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
				<span style="color: #000088;">$challenge</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array_shift</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$arrArguments</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
				<span style="color: #000088;">$signature</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array_shift</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$arrArguments</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			<span style="color: #009900;">&#125;</span>
&nbsp;
			<span style="color: #666666; font-style: italic;">// Verify the given signature, before executing the call, unless the request is to a method from an exempt class:</span>
			<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">in_array</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$className</span><span style="color: #339933;">,</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">exemptVerification</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">||</span> AMF_Login<span style="color: #339933;">::</span><span style="color: #004000;">verifySignature</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$challenge</span><span style="color: #339933;">,</span><span style="color: #000088;">$signature</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
				<span style="color: #666666; font-style: italic;">// Verify if the requested method actually exists:</span>
				<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">method_exists</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;_<span style="color: #006699; font-weight: bold;">{$method}</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
					<span style="color: #000088;">$cachehit</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// support for caching could be added, but not now.</span>
					<span style="color: #000088;">$returnValue</span> <span style="color: #339933;">=</span> <span style="color: #990000;">call_user_func_array</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;_<span style="color: #006699; font-weight: bold;">{$method}</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><span style="color: #000088;">$arrArguments</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
					<span style="color: #666666; font-style: italic;">// wrap the response of the API call in an AMF_VO_Message object, and return it:</span>
					<span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">wrapOutput</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$returnValue</span><span style="color: #339933;">,</span><span style="color: #000088;">$signature</span><span style="color: #339933;">,</span><span style="color: #000088;">$cachehit</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
				<span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
					throw <span style="color: #000000; font-weight: bold;">new</span> Exception<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;The method '<span style="color: #006699; font-weight: bold;">{$method}</span>' does not exist.&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
				<span style="color: #009900;">&#125;</span>
			<span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
				<span style="color: #666666; font-style: italic;">// An exception is already thrown in AMF::Login::verifySignature()</span>
			<span style="color: #009900;">&#125;</span>
		<span style="color: #009900;">&#125;</span> catch <span style="color: #009900;">&#40;</span>Exception <span style="color: #000088;">$e</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
			<span style="color: #000088;">$errorVO</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> AMF_VO_Error<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
			<span style="color: #666666; font-style: italic;">// Get the currently logged in user</span>
			<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>Zend_Auth<span style="color: #339933;">::</span><span style="color: #004000;">getInstance</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasIdentity</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
				<span style="color: #000088;">$user</span> <span style="color: #339933;">=</span> Zend_Auth<span style="color: #339933;">::</span><span style="color: #004000;">getInstance</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getIdentity</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
				<span style="color: #000088;">$errorVO</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">user_id</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$user</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">user_id</span><span style="color: #339933;">;</span>
			<span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
				<span style="color: #000088;">$errorVO</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">user_id</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span>
			<span style="color: #009900;">&#125;</span>
			<span style="color: #000088;">$errorVO</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">timestamp</span>		<span style="color: #339933;">=</span> <span style="color: #990000;">strftime</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;%Y-%m-<span style="color: #009933; font-weight: bold;">%d</span> %H:%M:%S&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			<span style="color: #000088;">$errorVO</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">errorCode</span>		<span style="color: #339933;">=</span> <span style="color: #990000;">get_class</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$e</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// usually, this will be &quot;Exception&quot;, unless we introduce custom Exceptions</span>
			<span style="color: #000088;">$errorVO</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">file</span>			<span style="color: #339933;">=</span> <span style="color: #000088;">$e</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getFile</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			<span style="color: #000088;">$errorVO</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">linenumber</span>		<span style="color: #339933;">=</span> <span style="color: #000088;">$e</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getLine</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			<span style="color: #000088;">$errorVO</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">messages</span>		<span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$e</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getMessage</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			<span style="color: #000088;">$errorVO</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">stacktrace</span>		<span style="color: #339933;">=</span> <span style="color: #990000;">debug_backtrace</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
			<span style="color: #666666; font-style: italic;">// return response</span>
			<span style="color: #b1b100;">return</span> <span style="color: #000088;">$errorVO</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">function</span> wrapOutput<span style="color: #009900;">&#40;</span><span style="color: #000088;">$data</span><span style="color: #339933;">,</span><span style="color: #000088;">$transaction</span><span style="color: #339933;">,</span><span style="color: #000088;">$cachehit</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$message</span>				<span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> AMF_VO_Message<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$message</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">status</span>		<span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;success&quot;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$message</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">timestamp</span>	<span style="color: #339933;">=</span> <span style="color: #990000;">strftime</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;%Y-%m-<span style="color: #009933; font-weight: bold;">%d</span> %H:%M:%S&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$message</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">transaction</span>	<span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">is_null</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$transaction</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>?<span style="color: #000088;">$transaction</span><span style="color: #339933;">:</span><span style="color: #0000ff;">&quot;no_transaction&quot;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$message</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">data</span>		<span style="color: #339933;">=</span> <span style="color: #000088;">$data</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$message</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">cachehit</span>		<span style="color: #339933;">=</span> <span style="color: #000088;">$cachehit</span><span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #b1b100;">return</span> <span style="color: #000088;">$message</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>The function <em>processRequest()</em> is now very basic. It only incorporates authentication of the requester, and catching errors. I will not implement the rest of the requirements during this article, since that would lead me outside the scope of this article. If you feel like implementing extra functionality for all your calls, then <em>processRequest()</em> is the method to elaborate on. For a business project, I have extended it with everything mentioned in my list earlier.</p>
<p>The hard part is over now. Most of the functionality has been written. Each API call will be accompanied by 2 extra parameters: a client-chosen challenge, and a calculated signature. The given challenge and signature are just the first two parameters of each of our service calls. These parameters will be verified in <em>processRequest()</em>.</p>
<p>The actual verification is done by the <em>verifySignature() </em>method in AMF_Login class. To make it easy, below is a copy of that method again. The parameters are the challenge, chosen by the client, and the signature, calculated by the client. The method will then use that same challenge, and the password stored in a session object, and then calculate the accompanying signature. If both signatures match, then we have a winner! If they don&#8217;t match, then somebody is trying to tamper with the requests. It&#8217;s up to you how you deal with that. I just output an AMF_VO_Error object.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #009933; font-style: italic;">/**
 * Method to verify if each signature for an API call is valid
 */</span>
<span style="color: #000000; font-weight: bold;">public</span> static <span style="color: #000000; font-weight: bold;">function</span> verifySignature<span style="color: #009900;">&#40;</span><span style="color: #000088;">$challenge</span><span style="color: #339933;">,</span><span style="color: #000088;">$signature</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
	<span style="color: #666666; font-style: italic;">// 1. get the password from the session (it was put there during authentication)</span>
	<span style="color: #000088;">$amfNamespace</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Zend_Session_Namespace<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'AMF_Auth'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">// 2. calculate signature with given $challenge</span>
	<span style="color: #000088;">$calcSignature</span> <span style="color: #339933;">=</span> <span style="color: #990000;">md5</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">md5</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$amfNamespace</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">password</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$challenge</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">// 3. compare calculated signature, with given signature</span>
	<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$calcSignature</span> <span style="color: #339933;">==</span> <span style="color: #000088;">$signature</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
		<span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
	throw <span style="color: #000000; font-weight: bold;">new</span> Exception<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Incorrect signature given&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>With this last functionality explained, I think I have everything covered. Only thing left, is giving you an example on how our processRequest() method is used:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #009933; font-style: italic;">/**
 * System proxy class to expose classes to AMF
 *
 */</span>
<span style="color: #000000; font-weight: bold;">class</span> Proxies_AMF_System <span style="color: #000000; font-weight: bold;">extends</span> Proxies_AMF <span style="color: #009900;">&#123;</span>
	<span style="color: #009933; font-style: italic;">/**
	 * Say hello to the world
	 *
	 * @return string
	 */</span>
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> helloWorld<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$args</span> <span style="color: #339933;">=</span> <span style="color: #990000;">func_get_args</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">processRequest</span><span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">__FUNCTION__</span><span style="color: #339933;">,</span><span style="color: #000088;">$args</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	protected <span style="color: #000000; font-weight: bold;">function</span> _helloWorld<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
		<span style="color: #b1b100;">return</span> <span style="color: #0000ff;">&quot;Hello World !!&quot;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>I mentioned the <em>helloWorld()</em> function earlier, and here is the implementation. The Flex client calls the <em>helloWorld()</em> function (without the underscore !!), and gives as paremeters the challenge and signature. You&#8217;ll see that those parameters aren&#8217;t explicitly mentioned in the function definition, but that is no problem. In that function, <em>processRequest()</em> is called, which will do the verificiation and then call<em> _helloWorld()</em>. The response from <em>_helloWorld()</em> will then travel back, over <em>processRequest()</em>, via <em>helloWorld()</em>, to Zend_AMF, stopping at the Flex client.</p>
<p><strong>Ammendments</strong></p>
<p>This article is the fruit of a quite lengthy development process at the company I work at. During this period, I have made many mistakes regarding Zend_AMF, and learned from them. To illustrate that development is a continuous learning process, I will end with a &#8220;mistake&#8221; I just recently discovered:</p>
<p>When I first implemented these security measures, I used the URL to transport the challenge and signature for each API call. This way, could keep my interfaces clean, without having to take into account the challenge and signature. In Flex, I had the front-end developer create a dynamical endpoint for each call. Each endpoint connection only made one call, since in the URL, the challenge and signature were added. However, when an endpoint connection is established, it is standard procedure of AMF to ping the server once. As a result, each call generated a new ping request, effectively doubling the amount of calls. I don&#8217;t have to explain that this is quite a big overhead. To overcome this, I had to extend each API call to accept the challenge and signature as a parameter of that call. And the result of my mistake is that you can enjoy a &#8220;better&#8221; implementation than what I had 2 days ago.</p>
<p>What I want to say: This method is not fool proof, and I have no doubt that there are probably many ways of improving the security. If you happen to have suggestions, by all means, let me know. I&#8217;m happy to learn from you.</p>
<p><strong>Download all files</strong>: <a href="http://www.encapsulated.org/blog/wp-content/uploads/2009/04/amfsecurity.zip">zip</a> | <a href="http://www.encapsulated.org/blog/wp-content/uploads/2009/04/amfsecurity.tar.gz">tar</a><br />
<strong>Credits</strong> where credits are due: Thanks <a href="http://www.vicr.be/blog/">Vic Rau</a> for the small <a href="http://www.encapsulated.org/dev/flex/application/v1/public/images/UnitTesting.html">UnitTest</a> (yes, it is also in the downloadable archive)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.encapsulated.org/blog/2009/04/15/security-with-zend_amf-and-flex-part-2-practise/feed/</wfw:commentRss>
		<slash:comments>21</slash:comments>
		</item>
	</channel>
</rss>
