<?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>Open Source Solutions for Small Business Problems &#187; Technical</title>
	<atom:link href="http://opensourcesmall.biz/tag/technical/feed/" rel="self" type="application/rss+xml" />
	<link>http://opensourcesmall.biz</link>
	<description>The living site of the book by John Locke</description>
	<lastBuildDate>Fri, 05 Dec 2008 23:00:30 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.2</generator>
		<item>
		<title>SOAP, Web Services, and PHP</title>
		<link>http://opensourcesmall.biz/2008/08/soap-web-services-and-php/</link>
		<comments>http://opensourcesmall.biz/2008/08/soap-web-services-and-php/#comments</comments>
		<pubDate>Sat, 23 Aug 2008 17:52:04 +0000</pubDate>
		<dc:creator>freelock</dc:creator>
				<category><![CDATA[Technical]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[soap]]></category>

		<guid isPermaLink="false">http://opensourcesmall.biz/?p=266</guid>
		<description><![CDATA[One of my projects in the past few weeks has been to put together a SOAP server for a client. So suddenly I&#8217;ve had to learn a lot of the nitty gritty details about what works and what doesn&#8217;t&#8230; While they&#8217;re fresh, let me jot them down here. WARNING: Extremely technical content ahead. First of [...]]]></description>
			<content:encoded><![CDATA[<p>One of my projects in the past few weeks has been to put together a SOAP server for a client. So suddenly I&#8217;ve had to learn a lot of the nitty gritty details about what works and what doesn&#8217;t&#8230;</p>
<p>While they&#8217;re fresh, let me jot them down here. WARNING: Extremely technical content ahead.<br />
<span id="more-266"></span><br />
First of all, SOAP is supposed to stand for &#8220;Simple Object Access Protocol.&#8221; It&#8217;s anything but simple. There is a lot of SOAP software out there, but subtle implementation gotchas that can be quite difficult to figure out.</p>
<p>We chose the native PHP SoapServer in PHP 5.2 to implement the project, mainly because we&#8217;re a PHP shop, and a little smoke testing revealed it was quite quick to get set up and going. It turns out that it&#8217;s quite hard to debug. For its good points, it can read in a WSDL and automatically map methods to methods on a class, and it converts arrays, simple objects, or complex objects to a valid response object, and request objects into simple or complex objects on the incoming side.<br />
<strong><br />
Problems with PHP&#8217;s SOAP Server:</strong></p>
<ul>
<li>No validation of incoming or outgoing documents.</li>
<li>No warnings, exceptions, or errors if it can&#8217;t convert a document to fit the schema&#8211;it just dies.</li>
<li>No debugging information about what it&#8217;s doing.</li>
<li>No ability to manage namespaces, especially if they need to be copied from the SOAP envelope into the payload.</li>
<li>Difficult to test.</li>
<li>No access to the raw XML of either the request or the response.</li>
</ul>
<p>Using PHP&#8217;s SoapServer is quite simple, except when things aren&#8217;t perfect&#8230;</p>
<p>Here&#8217;s what the code looks like for the simple case:</p>
<p><code><br />
< ?php<br />
  $xml = $GLOBALS['HTTP_RAW_POST_DATA']; // or file_get_contents('php://input');<br />
  // make sure you have something to process, throw an error if $xml is empty<br />
  $soap = new SoapServer('http://path/to/your.wsdl');<br />
  $soap->setClass('mySoapClass');<br />
  $soap->handle($xml);<br />
?><br />
</code><br />
That&#8217;s basically it. You declare methods on &#8216;mySoapClass&#8217; that correspond to the SOAP methods. These handler methods receive a simple object as a parameter, and you can do whatever you need to do with that data. Then it needs to return some data structure that can be serialized to the expected type defined in the WSDL. The return data structure can be an array, a simple object, or an object of a class you define that can serialize appropriately.</p>
<p>Great. With this much, it took me about a day to have a working web service with 8 methods and a bunch of complex data objects. The problems started when people connected with different SOAP software.</p>
<p>The web service I was implementing defines a specific SOAP Fault document, so if I did run across a problem, I could simply throw an exception of that type. My wrapper object kindly passed the custom fields defined in the WSDL.</p>
<p><strong>Problem #1: Validation</strong></p>
<p>As I said before, there is none. If the SoapServer gets anything it doesn&#8217;t like, it doesn&#8217;t send any response at all. And since all you get inside your method handlers is an already-converted object, you don&#8217;t have any way to validate the response without using a global variable or a call to a singleton.</p>
<p>In our case, the project specified that we strip out the payload from the SOAP header and store the payload XML on the disk as a document for several methods, and do processing on other methods. Processing a SOAP request was not a problem. Storing a valid XML document was. Several methods just stored the XML on the disk, with another method retrieving it and returning it to the caller. The problem we had was that the Soap Response was more picky than the Soap Request&#8211;so documents that we loaded from the disk and returned as the response would fail with no explanation.</p>
<p>Our solution was to load the raw XML into a DOM Document, and validate it against the schema. This mostly worked, until we had to deal with a request generated from Jitterbit. More on that later.</p>
<p>The question is, what to validate? We weren&#8217;t supposed to store the entire SOAP envelope&#8211;just the payload. So how to extract it? The simple way was to grab the first child of the Body element, append it to the DOMDocument itself, remove the original root, and call the normalize() method. This did generate a warning, but not a fatal error, and did the right thing. Furthermore, we could also access the raw libxml validation specifics, by calling libxml_use_internal_errors(true), and then when a document fails to validate, using libxml_get_errors() and libxml_get_error() to grab the details.</p>
<p><strong>Problem #2: Returning valid XML responses</strong></p>
<p>The root of all of our problems in this project has to do with where namespaces are defined. One limitation of libxml appears to be that you can only point it to one schema for validation at a time. We can validate against the SOAP Schema, or our custom schema, but not both at the same time, unless one includes the other. So our validation options consist of:</p>
<ol>
<li>Include the SOAP Schema in the custom schema, and validate the entire SOAP body, or</li>
<li>Extract the payload from the SOAP body, and validate only that against our schema.</li>
</ol>
<p>#2 is clearly the correct way&#8211;we really don&#8217;t care about the SOAP envelope once we have the message. But the problem is, many SOAP clients put the namespace declarations on the SOAP Envelope, and not the payload root element. In fact, the XML generated by the PHP SoapServer class does this itself.</p>
<p>So our first task was to generate the proper XML Namespace declarations on our generated payloads.</p>
<p>To do this, we could no longer rely on the PHP SoapServer&#8217;s automatic conversion of simple objects or arrays to XML&#8211;we had to generate our own XML, and tell the SOAP server to use that instead. This turned out to be difficult to track down, so here&#8217;s the answer:</p>
<p><code><br />
< ?php<br />
  class dataClass{<br />
    /* Serialize XML as desired here.<br />
        Omit the XML declaration, start with the root element<br />
        You can also simply build the XML as a string from object properties<br />
    */<br />
     function toXml(){<br />
         $this->myDom->documentElement->setAttribute('xmlns','http://my.custom.namespace/version_1');<br />
         $xml = $this->myDom->saveXML();<br />
         preg_match('%< \?.*=\?>(.*)$%s',$xml,$match); //strip XML declaration<br />
         return $match[1];<br />
   }<br />
}</p>
<p>// snip to end of actual SOAP handler method:<br />
   $out = new SOAPVar($data->toXML(),XSD_ANYXML);<br />
   return $out;<br />
}<br />
</code><br />
The SOAPVar object allows you to control the output of the SoapServer a bit better, with support for namespaces, raw XML, or casting objects in a certain way.</p>
<p><strong>Problem #3: Jitterbit</strong></p>
<p>Validating a clean payload without namespace prefixes seems to work fine. Our technique of moving the nodes around with the DOM seemed to keep most of the namespaces intact, so even if there was no xmlns declaration on the payload root, we could still validate just the payload effectively, and serialize/de-serialize without issue.</p>
<p>Except for Jitterbit.</p>
<p>Now, I loaded up Jitterbit yesterday, and it didn&#8217;t do this&#8211;this might be a problem with an earlier version. The problem is, Jitterbit is extremely verbose, specifying not just a namespace prefix on every element, but also an xsi:type. And even that&#8217;s not enough to break it&#8211;except that the value for its xsi:type also contained a namespace declaration. And if this namespace declaration was not the root namespace, suddenly our validation broke.</p>
<p>It broke for us on types declared as ns:token, ns:string, ns:integer &#8212; the simple types specified by XSD itself, which Jitterbit put into a namespace prefixed with ns: and declared on the SOAP Envelope.</p>
<p>For example, here&#8217;s the start of a problem document:</p>
<p><code><br />
< ?xml version="1.0" encoding="UTF-8" standalone="no" ?><br />
<soapenv :Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"<br />
                  xmlns:ns="http://www.w3.org/2001/XMLSchema"<br />
                  xmlns:oi="http://ws.outdoorindustry.org/v1_2/"<br />
                  xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"<br />
                  xmlns:ws="http://ws.outdoorindustry.org/v1_2/ws/"<br />
                  xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"<br />
                  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"<br />
><br />
</soapenv><soapenv :Body><br />
<tns1 :submitPO<br />
                  xmlns:tns1="http://ws.outdoorindustry.org/v1_2/"<br />
               xsi:type="tns1:PO"><br />
               </tns1><tns1 :DocumentID>06AB4EF9-6AF157E7-3F8441AB-AB499933</tns1><br />
               <tns1 :POType>Preseason</tns1><br />
               <tns1 :Vendor xsi:type="tns1:VendorType"><br />
                   </tns1><tns1 :VendorID xsi:type="ns:token">999</tns1><br />
                   <tns1 :VendorName xsi:type="ns:token">Sample Vendor</tns1></p>
<p></soapenv></code></p>
<p>The first validation error was on the VendorID, with xsi:type=&#8221;ns:token&#8221;. If I copied xmlns:ns=&#8221;http://www.w3.org/2001/XMLSchema&#8221; into the tns1:submitPO element, it validated fine. The PHP DOMDocument seems to be able to keep track of namespaces on elements and attribute names even after the envelope is gone. But not attribute values.</p>
<p>After hours of banging on this, we came up with 3 workarounds for this:</p>
<ol>
<li>Completely regenerate the XML, after processing. To do this, we would need to create a custom data class for each incoming object, provide a classmap to the SoapServer, and then generate brand new XML out of the data object. This is perhaps the best approach, but I didn&#8217;t think of it until the project was over&#8211;I was thinking about writing out the data to the database and then loading our custom objects and serializing them as we do for our responses. The biggest drawback here is that we need to model the entire complexity of the request, as allowed in the schema. And this was a really complex object&#8230; lots of work to implement, when we&#8217;re only going to store this XML for passing to other systems.</li>
<li>Hack the XML to get the offending namespace into the stored document. This turned out to be easy to program, but uses lots of CPU resources&#8211;DOMDocuments are expensive to use. It&#8217;s also the most brittle approach, only catching this single case&#8211;if the namespace prefix changes, or a different required namespace is necessary, it&#8217;ll break. To do this, we created a new DOM Document, imported the root node of the payload, appended it to the document, and used setAttribute to set an &#8220;xmlns:ns&#8221; attribute on the root. This did not actually get the namespace recognized for validation, and normalizeDocument did not fix it&#8211;but creating a third DOMDocument, and doing $doc->loadXML($doc2->saveXML) did make the namespace recognized by the object so we could successfully validate.</li>
<li>Hack the XSD to validate the entire SOAP request. By including the SOAP schema in our custom schema (using xs:import), we could validate the raw SOAP request, then extract the payload and save it. The saved XML does not validate on its own, but we know it validates. So we can remove our validation check on the outgoing document, and as long as the other system does not explicitly validate the standalone XML, we&#8217;re okay.</li>
</ol>
<p>Whew. Hope this helps somebody&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://opensourcesmall.biz/2008/08/soap-web-services-and-php/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>What&#8217;s git, and why do you use it?</title>
		<link>http://opensourcesmall.biz/2008/06/whats-git-and-why-do-you-use-it/</link>
		<comments>http://opensourcesmall.biz/2008/06/whats-git-and-why-do-you-use-it/#comments</comments>
		<pubDate>Mon, 30 Jun 2008 19:46:17 +0000</pubDate>
		<dc:creator>freelock</dc:creator>
				<category><![CDATA[01. Open Source]]></category>
		<category><![CDATA[09. Document Management]]></category>
		<category><![CDATA[Economic Musings]]></category>
		<category><![CDATA[Technical]]></category>
		<category><![CDATA[code management]]></category>
		<category><![CDATA[dojo]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[joomla]]></category>
		<category><![CDATA[ledgersmb]]></category>

		<guid isPermaLink="false">http://opensourcesmall.biz/?p=250</guid>
		<description><![CDATA[At Freelock, we&#8217;re always trying to figure out ways to do things better. Recently I started digging into a developer tool that&#8217;s making, as Bryan over at the Linux Action Show would say, my head explode. For a long time, we&#8217;ve managed our custom code projects and business documents in a central repository, called Subversion [...]]]></description>
			<content:encoded><![CDATA[<p>At <a href="http://freelock.com">Freelock</a>, we&#8217;re always trying to figure out ways to do things better. Recently I started digging into a developer tool that&#8217;s making, as <a href="http://www.lunduke.com/" target="_blank">Bryan</a> over at the <a href="http://www.jupiterbroadcasting.com/?cat=4" target="_blank">Linux Action Show</a> would say, my head explode.</p>
<p>For a long time, we&#8217;ve managed our custom code projects and business documents in a central repository, called Subversion (also known as svn). Subversion is relatively easy to understand&#8211;it&#8217;s like having a library of files you can check a copy out of, do some work on it, and then check it back in. Subversion is the librarian that tracks who has copies of what, and when they checked it out. So if Erik checks in changes to a brochure, and then Jill goes to submit changes to the same document, Subversion will say &#8220;hey wait a minute, that document has already been changed&#8211;you need to make sure you put Erik&#8217;s changes in your document before I&#8217;ll let you put in your document.&#8221;</p>
<p>This is great for managing conflicts between people working on a single team, or for code that is being developed in relative isolation from the rest of the world.</p>
<p>The problem is, we&#8217;re doing more than that&#8211;we&#8217;re taking code from various open source projects and either customizing it or building new applications on top of it. And so when the outside projects get updated, we need to manually update anything we&#8217;ve written that depends on that code. There is no longer a single repository where we control our code&#8211;there is our code library, plus another one for every project we use.</p>
<p>This makes managing add-ons for projects like Joomla or ZenCart quite challenging, because our add-ons get scattered throughout the filesystem to be able to hook into the right place. And if we have to touch a core file, we&#8217;re going to end up needing to re-implement our change with any update to that core file.</p>
<p>There are other issues we run into, managing our code and hosting, all of which take fairly time-consuming, manual intervention. Here&#8217;s the list:</p>
<ul>
<li>Since we host and provide security updates for Joomla, Word Press, Zen Cart, Drupal, and others, we need to upgrade dozens of installations any time there&#8217;s a new release that has a fix for a security vulnerability. With Joomla this has happened quite a lot, and every Joomla installation needs to be upgraded individually&#8211;and tested. And since each installation is slightly different, we can&#8217;t manage them easily within a single repository, while updating the underlying code.</li>
<li>Templates, modules, components, blocks, themes, plugins, and whatever. Developing these types of add-ons are our bread-and-butter. But code for these often get scattered across an installation, making it quite difficult to manage just our add-ons while we develop them, or roll back to earlier versions if there&#8217;s a problem.</li>
<li><a href="http://dojotoolkit.org" target="_blank">The Dojo Toolkit</a>, and builds. We&#8217;re doing a lot of development with Dojo right now, to add desktop-like functionality such as trees, sortable tables, right-click menus, animations, and lots of other really cool things. However, if you don&#8217;t &#8220;build&#8221; the code after you write it, it&#8217;s painfully slow in a web browser. And due to the nature of how Subversion works, you can&#8217;t easily store a built Dojo tree if you ever want to change it again. Which means you&#8217;d need to build it every place you deploy it. And on some computers, it can take a long time to build&#8211;on our demo server, one of our projects currently takes 8 minutes.</li>
<li>As we get more directly involved with open source projects like <a href="http://ledgersmb.org">LedgerSMB</a>, we&#8217;re finding the need to change core files while we hack away at some particular feature. To do this, you create a branch of the code, work on your feature, and then merge your changes back into the &#8220;trunk.&#8221; If you don&#8217;t have access to save directly to the project repository, doing this gets a lot more complicated.</li>
</ul>
<p>Git to the rescue. Git solves all of these issues. Read on for a technical discussion of how.<br />
<span id="more-250"></span><br />
<strong>Managing lots of installations with Git</strong><br />
We haven&#8217;t yet started doing this, but for projects like Joomla and ZenCart, this is going to be really effective. It&#8217;s not quite as helpful for Drupal, which allows for a bunch of sites to be centrally managed out of the box&#8211;though even there it will help us recover quickly from a failed upgrade.</p>
<p>Here&#8217;s the basic approach:</p>
<ol>
<li>Create a master git repository, either by pulling down the Subversion repository using git svn, or just unpacking tarballs of a release and importing into our git repository for the project.</li>
<li>Create a new git clone for each installation, and drop into each installation directory. Create a current branch for that repository, and rebase it to the current installed version.</li>
<li>Commit local modifications to the repository. Make sure the .git directory is getting backed up, and is not accessible through the web server.</li>
<li>When a new release is available, use git pull to update each local installation. Use git reset HEAD^ &#8211;hard to undo if there&#8217;s a problem.</li>
</ol>
<p><strong>Managing submodules, customizations</strong><br />
This we get pretty much for free by having dedicated repositories for particular problems. Managing add-ons we&#8217;d like to use elsewhere can still be challenging, but we can pull customizations from other repositories to assemble custom packages&#8211;it&#8217;s at least easier to manage these across installations.</p>
<p>The main thing to do is to make sure when you&#8217;re developing on a particular add-on, you&#8217;re always doing it in a branch dedicated to those changes. Then you can merge them into other projects more easily. It&#8217;s also possible to &#8220;cherry-pick&#8221; commits involving particular files, and pull those changes into a new branch if development ended up getting mixed in with different features.</p>
<p><strong>Dojo Toolkit builds</strong><br />
We&#8217;re huge fans of the Dojo Toolkit. It makes developing really sophisticated browser-based applications much easier, not just providing a large set of active widgets but also a data abstraction layer and an encapsulation system for your own code.</p>
<p>Its biggest downside is that every feature you want to use means adding another file that the browser needs to load. And we use a lot of features&#8230; the base package loads about 20 files, and in our applications there are well over a hundred. This takes a long time to load, and isn&#8217;t very scalable.</p>
<p>The solution? Use the Dojo build process. A Java program can build all the features you want to use into a single compressed, stripped, javascript file. The difference in speed is incredible&#8211;applications suddenly load right up. And this build system can easily build your Javascript as well.</p>
<p>The problem is, this build system is not compatible with Subversion, because Subversion scatters its working copy data inside each directory, but the build system deletes the directories every time you build. So you can&#8217;t easily manage built code inside Subversion.</p>
<p>Git stores all of its repository information in the top level directory, so you can easily build and re-build Dojo and manage it without any issues.</p>
<p><strong>Do local development on open source projects</strong><br />
Now here&#8217;s the traditional reason to use git: to allow you to manage changes to open source projects without needing write access to their code repositories. We simply set up git repositories to track their Subversion repository, and then we can use all the features of git to manage our customizations.</p>
<p>When the original project has new releases, we just pull them into our repository and git handles most of the merging for us. If we want to contribute back to the project, we can copy them into our Subversion tracking branch and commit them straight back to Subversion&#8211;or send a patch.</p>
<p>We&#8217;re starting to set up public git repositories for projects we work with extensively. You can browse them here:<a href="http://git.freelock.com"> http://git.freelock.com</a>. You can clone and pull updates from here: git://git.freelock.com/git/&lt;projectname&gt;.git. You can read more about how to manage non-standard Subversion repositories in git <a href="http://freelock.com/kb/Git">here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://opensourcesmall.biz/2008/06/whats-git-and-why-do-you-use-it/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Technical note: HTTP Auth with AJAX</title>
		<link>http://opensourcesmall.biz/2008/06/technical-note-http-auth-with-ajax/</link>
		<comments>http://opensourcesmall.biz/2008/06/technical-note-http-auth-with-ajax/#comments</comments>
		<pubDate>Sat, 07 Jun 2008 21:06:49 +0000</pubDate>
		<dc:creator>freelock</dc:creator>
				<category><![CDATA[Technical]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://opensourcesmall.biz/?p=246</guid>
		<description><![CDATA[I&#8217;ve been struggling to get Project Auriga to set HTTP Auth from a nice pretty login form, and think I have it working. What follows is a very technical discussion&#8211;if you&#8217;re a business reader, you should probably skip this post&#8230; HTTP Auth is a specific mechanism for handling authentication. HTTP Auth is built into Apache [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been struggling to get <a href="http://projectauriga.org">Project Auriga</a> to set HTTP Auth from a nice pretty login form, and think I have it working.</p>
<p>What follows is a very technical discussion&#8211;if you&#8217;re a business reader, you should probably skip this post&#8230;</p>
<p>HTTP Auth is a specific mechanism for handling authentication. HTTP Auth is built into Apache and IIS, and so the server can handle authentication purely through configuration, offering many different back ends for storing the data. Browsers also handle HTTP Auth natively, popping up a normal login box whenever it gets a Basic Authentication request from the server. But this login box is ugly, and doesn&#8217;t provide a friendly experience to allow people to create an account, get a password resent, or anything&#8211;it falls back to a basic error page. You can, of course, customize the error page, but not necessarily help people with the password login itself.</p>
<p>There are several benefits to using HTTP Auth, though. First of all, other applications on the same server can accept the same credentials, allowing you to sign in once and access multiple applications without having to log into each one. Secondly, you can set up stronger authentication methods, such as client-side certificates. Also, you can configure the server to protect large parts of a web site very easily, reducing exposure to information disclosure.</p>
<p>So how do you make a sign-in form on a web application set http auth? Browsers do not allow you to access these settings via script. You can use an XmlHttpRequest object to set authentication, but only after the proper challenge has been sent from the server. The biggest problem is, if the server sends this challenge twice in a row, your browser will intercept the second request and pop up the ugly password prompt. So designing a form that keeps this login prompt from popping up under most circumstances is quite the challenge.</p>
<p>The gist of the issue is that while you can open an XmlHttpRequest object with a user and password for http authentication, the browser will only actually use those credentials after the server has rejected a request. The process looks like this:</p>
<ol>
<li>Your script creates and sends an XmlHttpRequest with http auth username and password.</li>
<li>The browser submits the request to the server, without sending the username and password.</li>
<li>The server responds with 401 requires authentication, and a WWW-Authenticate header specifying a realm.</li>
<li>The browser looks in its cache to see if it already has http auth set for that domain and realm. If it does, it sends those credentials, NOT THE ONES you specified in your XmlHttpRequest. If it does not have those credentials, only then will it set http auth to what your script asked for.</li>
<li>The server responds. Generally, if the username or password are incorrect, the server will repeat the 401 response, and WWW-Authenticate.</li>
<li>The browser gets its second 401 in a row, and pops up its password box. Your script never gets a chance to intercept this. So if the stored http auth credentials are wrong, or the user mistypes the password, their browser takes over and you get a password prompt.</li>
</ol>
<p>How do you handle this situation? It turns out you need to engage in some trickery on both the client and the server.</p>
<p>Here&#8217;s a basic flow of how you need to handle this, from both the server and the client perspective:</p>
<ol>
<li>First, collect the credentials from the user, and create your request as outlined above.</li>
<li>Browser sends request without credentials.</li>
<li>Server responds with 401 and WWW-Authenticate.</li>
<li>Browser sends cached credentials, if they exist, or your credentials if not.</li>
<li>If credentials are accepted, server allows log in and responds with 200. If credentials are not accepted, server returns an error code OTHER THAN 401, and does not send a WWW-Authenticate:
<ol>
<li>We use 403 not authorized for a credential failure here. You might also use 400 Bad Request.</li>
<li>Because the response was something other than 401, your browser caches the bad credentials.</li>
<li>XmlHttpRequest status reflects the error condition.</li>
<li>Your script checks the result for the error your server has returned. Now comes the crucial part:</li>
<li>Your script submits a new request with different credentials to some server location that will return successfully. For example, we call a login method on our application, passing username &#8220;public&#8221; and password &#8220;?&#8221;.</li>
<li>The browser sends the new credentials and submits the request.</li>
<li>The server returns 200.</li>
<li>The browser updates its http auth cached credentials with the new bogus ones.</li>
</ol>
</li>
<li>Now you can present an error to the user, and ask for new credentials.</li>
</ol>
<p>The key to the above process is that if the browser gets two 401 responses without having a 200 somewhere between, it will pop up its password box and there&#8217;s nothing you can do about it. So the key is to use a different error code to indicate bad credentials, and do an intervening request that will return 200 so that you can re-authenticate.</p>
<p><strong>Logging Out</strong><br />
You cannot really log out of HTTP Auth. But you can change the credentials to a known bad user. That&#8217;s a key technique we use to effectively log out of an application, and we re-use this method to reset after bad credentials.</p>
<p><strong>On the server</strong><br />
I&#8217;m very much still in development with this. You can see the server side code for Project Auriga logins <a href="https://baker.freelock.com/svn/auriga/trunk/include/session_login.php">here</a>.</p>
<p>In this system, we do set a cookie after successful login, to keep from having to check credentials again. This script also allows for cookie-only logins without using http auth. The important bits:</p>
<ul>
<li>action=logout: if this is called, the script always returns successfully. This allows the client script to provide new bogus credentials. It passes a username of &#8220;public&#8221; to log out completely.</li>
<li>action=httpauth: if this is called, and there are no http auth credentials or the http auth username is &#8220;public&#8221;, return a 401 and WWW-Authenticate. This is always the first request from a browser, and triggers the browser to re-request with the credentials.</li>
<li>action=httpauth, with http auth username set, and it&#8217;s not &#8220;public&#8221;: The second or later requests, we never want to return a 401 or the browser will pop up its password prompt. So we return 403 (or 400) if the credentials are bad, or allow the script to continue processing if its good. In this case, our authenticate method returns true if credentials are good, false if the user is not found, and throws an exception if the credentials are bad.</li>
</ul>
<p>That&#8217;s basically what you need to do on the server side. Now for the client.</p>
<p><strong>Client-side logins</strong><br />
We&#8217;re using the <a href="http://dojotoolkit.org">Dojo Toolkit</a> extensively in Project Auriga, so the login functions are using dojo.xhr* requests to wrap the XmlHttpRequest objects and provide convenient callback functions. You can see our login code <a href="https://baker.freelock.com/svn/auriga/trunk/public_html/auriga/Login.js">here</a>. Key items:</p>
<ul>
<li>auriga.login is called by the login form. Note that if this is the first time to this page, the dojo.xhrPost actually happens twice: first time with no credentials, and the second time with them. If the second post is accepted, auriga.login_complete is called. If the second post returns any kind of error, auriga.login_err is called.</li>
<li>auriga.login_complete is easy&#8230; it just redirects to wherever the server response designates.</li>
<li>auriga.login_err is the real trick here. If it detects the error code we&#8217;ve chosen for bad passwords, it immediately calls the server logout method, to get a good response so the next time the browser gets a 401, it won&#8217;t immediately pop up the password box.</li>
</ul>
<p>You can see the code in action on our <a href="http://demo.freelock.com">demo server</a>.</p>
<p><strong>Other notes</strong></p>
<ul>
<li>Actually doing single sign-on is hard. We&#8217;re trying out different strategies for detecting whether a user already has http auth set, by calling our login method once on page load, but haven&#8217;t gotten that figured out. In our current script, just clicking Login with the form blank but authenticated elsewhere on the same domain and Realm, will log you in with your existing credentials.</li>
<li>Because your browser stores credentials based on the domain and the realm together, all applications that you set to share these items must accept the same credentials. If you have a different password on a different system on the same server, you must set a different realm, or logging into one will log you out of the other.</li>
<li>If you want to require http auth, but not Javascript, I suggest submitting something different to the server using Javascript to identify this type of request. Perhaps show your form only when Javascript is available, and when it&#8217;s not, have a link to a protected page to let your browser go ahead and show the password dialog.</li>
<li>Using http auth can actually allow users to disable cookies, if your application is RESTful. In Project Auriga, the session login script supports either&#8211;the client pages and logins work with either a cookie or http auth. The login process attempts to set http auth and a session cookie. On subsequent attempts, it uses the cookie to avoid re-authenticating every request.</li>
<li>Finally, a note on security: Basic Authentication provides no protection against passwords being sniffed over the network. If you need a secure login, be sure the server conversation uses SSL&#8211;otherwise neighbors on your wireless network can easily sniff out your password. HTTP Auth does not make your application more secure&#8211;it just makes it easier to share authentication with other resources on the same server.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://opensourcesmall.biz/2008/06/technical-note-http-auth-with-ajax/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>

