Rolling Your Own CIAM-Bad Idea Or Horrible Idea?
Heya,
Why not roll your own auth?
This question has come up before so many times that I find it boring. I'm going to document why rolling your own identity solution for customers or users is a bad idea.
Definitions
I want to define what 'roll your own auth' means, because I see it used in different ways.
When I use the term, I mean starting from scratch. Creating a user table in your database with credentials and writing CRUD operations to manage a user including their password. (I don't consider using a framework authentication library to be rolling your own auth.)
If you ever find yourself writing create table user ...
and you are storing credentials, you are rolling your own auth.
Security
Are you thinking about security, day in and day out? If not, rolling your own auth is a bad idea. Authentication is the front door to your application, and there are plenty of attackers knocking on the door. OWASP, a web security project, ranks broken authentication as the 7th most important security issue for applications and the 2nd most important one for APIs in their recent top 10 lists.
There are also new standards and technologies to keep up with. These don't always offer new functionality, they sometimes protect against new attacks. An example of this is PKCE, which prevents certain types of interception attacks. You'll need to make sure you spend time and energy keeping up to date on these.
Finally, there's correct implementation of well known best security practices. The AWS Amplify folks have known for at least five years that they store sensitive credentials in localstorage, which is not a best practice.
Securing authentication is not necessarily rocket science, but if the AWS folks can't do it correctly, will you?
Features
Authentication features are typically non-functional and not a selling point for your customers. Occasionally they are, such as offering federation to business customers. But usually, customers want to sign in as quickly as possible to get to the data or features that your application offers.
When there are new authentication requirements, such as supporting a new social provider or enabling additional MFA methods, this work competes with feature work. You need to research, design and build it, like you would any other software. Oh, and maintain it as well.
Presumably the new authentication related functionality is providing business value, otherwise why would you do it? But it is going to be undifferentiated. Which means when it competes with features that paying customers really want, it may fall down the priority list.
Okay, who cares? When you are building an auth system, you can treat those features like any other, and let the business decide what is built. What benefit would using a non-homegrown alternative provide?
The answer is “increased delivery velocity”. If you use an alternative, you'll be able to deliver these undifferentiated features by configuration rather than coding and still get the value. While you'll still have to configure and test them, you won't have to design and code them. That means you'll be able to deliver the functionality more quickly. Bonus: as the features evolve, someone other than your team will be responsible for maintenance.
Edge Cases
Edge cases abound in authentication systems, and the larger the installed base, the easier it is to support such edge cases. Whether these are standards that might not be widely implemented but are important for your use case (such as Private Key JWT) or feature edge cases like securely handling link checkers when sending magic links, you will run into these.
If you choose to roll your own auth, you'll be responsible for determining if you should support such edge cases, then designing and implementing code to do so.
If you use an alternative, you won't be.
Alternatives
Hopefully I’ve convinced you that you should consider alternatives to rolling your own auth.
However, what are your alternatives? Depends on your needs.
First and easiest: avoid authentication if you can. This is not usually possible for modern applications, unfortunately.
Use a library, such as an open source solution like devise or passportjs. Take the time to learn what your application framework provides. Don't just accept all the defaults; spend some time learning what correct configuration looks like. You're coupling your authentication tightly to your app (they'll typically share the same database).
Use an external auth server. You'll still need to learn how to correctly configure, integrate and operate it. With this solution, you have more architectural complexity but less coupling.
Thanks,
Dan