/ be me
/ be working on new Rails API web app
/ ...I can't. I hate this format
...so I was looking up how to do simple, secure authentication in Rails for my super secret project which you definitely can't find by looking at recent activity on my GitHub account (Hail Mammon[0]) and realized that I hadn't implemented authentication in Rails in a long time. The closest I'd come to was throwing Devise into my app and grumpily remembering to configure the mailer after the fact.
This will seem unrelated, but bear with me: I learned how to calculate interest rates on loans in something like 6th grade. I have since forgotten how to do that without assistance. Much like how I would have been much better prepared to choose a mortgage back then, I would in some ways be much better prepared to figure out authentication a few years ago when I was just starting out in web dev - and had just implemented it from the Hartl tutorial. That said, just like how I now know more of what I'm looking for in a house, I now know more of what I'm looking for in an API.
I wanted an API-only Rails app for a mobile project I'm working on with my cousin. That meant that a great deal of Devise would be mostly useless to me, so I began to look for alternatives, which led me down a rabbit hole. After all, what was the issue with rolling your own authentication, again?
Basically the problems with rolling your authentication are a microcosm of the problems with rolling your own crypto, but not as severe. Don't get me wrong - a compromised system is a compromised system. But rolling your own authentication doesn't have quite the same level of difficulty as rolling your own crypto library, of which there are certain levels:
- Using cryptographic libraries - probably fine, given you know a few key points.
- Choosing your encryption algorithm - check that it's not already broken; once someone has a reliable crack for an encryption scheme, the whole thing is generally dead in the water. It's like being a little dead or a little pregnant - there's really no such thing.
- Implementing an encryption library or algorithm - you really have to know your stuff to write a safe, performant encryption library. There are a few layers involved in this level, but they're all subject to the same sensitivities:
- Wrappers around well-known libraries which are often implemented in low level languages
- Native (to the language you're using) implementations of well-known encryption algorithms and libraries to use them, and
- Mixed language implementations, often in a target language and assembly for performance and reliability. Apparently, compilers, smart little devils that they are, will change their assembler output, often for good reasons like optimization. However, that means that the resulting assembly code is unpredictable - and possibly insecure, as noted crypto researcher DJ Bernstein notes here. And no, DJ Bernstein does not drop phat beats, but his crypto is 🔥🔥🔥
- Designing an encryption algorithm - probably just apply, be accepted into, and enroll in a PhD program in cryptography to get started on this one, so probably not super approachable for most people
Rolling your own authentication, on the other hand, mostly just sits at level 1 on the above tier, if that. A few things to keep in mind:
- Never store plaintext passwords
- Don't pick broken encryption algorithms - better yet, don't get to the point where you're picking algorithms at all, use a peer reviewed community standard
- Know what a salt is for: randomizing password input before hashing it to defend against dictionary and rainbow-table attacks
- Be familiar with the idea of timing attacks - fun fact, the Meltdown and Spectre Attacks are timing attacks
- Know when you're in over your head - for me, that's anything over level 0.5 in the previous list.
Clearly, I'm not terribly confident, but that's because I shouldn't be.
Thanks for this very-detailed educative gist