Some of de most basic and useful general principles of programming must be applied when approaching security matters in your code.
Stay DRY (Do not Repeat Yourself)
More than unproductive, repeating yourself when implementing security is dangerous. Bugs have more room to spread and remain undetected (slipping between a copy and a paste or two .hg commits ). Attackers get more chances to see your code.
Let’s KISS (Keep It Simple, Stupid)
Breaking this universal principle is bad enough in any area. With security, code complexity obscures the general idea being implemented, and, I found, sometimes leaves room for incredibly elementary logic mistakes. Getting drawn into the code forrest, one sometimes forgets what their actually doing. Security code needs thorough and extensive testing, which is a daunting task anyway, even without having to deal with complex code. So keep it simple.
Divide et impera
Dividing the code that deals with security into small logical bits is a very good idea. It helps with the extensive testing and debugging this type of code demands, and it allows for easier updates.
Single point of failure
Try to keep the points of failure to a minimum in this critical section of your code. For instance, you should have a single class that deals with all the encryption, based on a limited set of “fixed” functions, and no more. Variation is bad here. This class shall be inherited or used by all classes that need data encryption.
Similarly, user authentication should be dealt with specifically by a single class, through a single function that does all the required processing, i.e. hashing of the input password string and the comparison, plus whatever else you require.
That way, all failures converge into a single function (or limited set of functions), easy to test, debug, update, and the risk of forgetting a flawed authentication mechanism on top of a script somewhere is eliminated.
Build on top
Don’t reinvent the wheel, unless your business is building wheels (or you need to learn more about wheels – Jeff Atwood), or you really think you’re competent enough to build a better one. Build on top of what others have achieved. That means incorporating paradigms, thinking patterns and models into your work, not just code.
For instance, in the field of security, it’s not just pretty pointless and time consuming to try and write a new SHA-256 cipher algorithm, but also dangeorus, should you get it wrong. Same with trying to come up with “novel” password recovery mechanisms.
Make sure the scripts accessed via AJAX comply to the same security standards as all others.
Test, test, test
And then test some more, and do not assume safety by thinking some scenarios are extremely unlikely.