Has anyone built their own authentication system?
I'm building out a website (never did full stack before) and am implementing authentication. It's turning out to be more work than I expected. Is it unreasonable to implement auth yourself with JWTs? You also need to setup email sending for verification which takes more time. Yes, several. This is going to be a controversial one... but it isn't nearly as difficult as people make it seem. You shouldn't roll your own crypto libraries, but storing a bcrypt hash of the users password in the database, and then creating a JWT and setting it in a cookie, or create a session table and store a UUID in the cookie as a key to the session table really isn't that difficult. Personally I think the problem is we are being sold so many 'conveniences'/solutions these days. They want you to think you cannot safely do it yourself, and on top of that, often times it's actually more difficult just to learn how to use whatever API the convenience that's being sold to us, uses. You are often better off learning what is really happening under the hood, and solving the actual problem, instead of trying to figure out whatever api/tool that is being sold to you as a convenience.
EDIT: to clarify, if you are inexperienced: I recommend learning by implementing both session + JWT auth on a side project, before using hand-rolled solutions in production. This has been my experience as well. I started with tools like supabase and appwrite and after spending so much time fiddling with their APIs, decided to do as this commenter suggested and found it wasn't as difficult as I was led to think. Bonus points, store meta data about the hash algorithm. That way if you ever need to change it in the future due to a weakness in the algorithm you can validate the password against old metadata and rehash with new metadata and update the record. Many of the popular password hashes include metadata in the default output already. bcrypt certainly does. Argon2 as well. Most libraries give you a string that contains all the parameters it needs for hashing. I'd say that the basic user and session management is easy to implement. The issue is when things get more complicated and your customers want to have single sign on, groups, roles, OpenID and so forth. You can still do it yourself, but at some point you might be spending a lot of developer time on reinventing the wheel instead of working on your actual product. You might also have to build all the associated dashboards for managing all that. I've done this as well, where I work. There's some talk about replacing it with an off-the-shelf solution, but my service takes one call to issue a token and one call to authenticate it. The talk about replacing it is with OAuth2, so the result will be that integrating with any service will be more difficult than writing the entire auth service in the first place, but what can you do. I have, and the basic username / bcrypted / scrypted password / JWT implementation was quite easy. What I found difficult* was all the accessory quality of life functionalities, e.g. password reset via mail, automated backups, 2 factor authentication, social login etc. You might not want all of them, but email verification / reset is kinda the expected baseline and it means you have to use an external mail-sending system anyway. *difficult not as in "hard to implement", more as in "lots of moving parts, hard to maintain" It's actually very easy to implement your own authentication. You should use either Argon2 or Bcrypt to store passwords. If the website is small, you shouldn't use JWTs (see https://blog.ploetzli.ch/2024/should-i-use-jwt-for-authentic...). Ideally, you should use an encrypted HttpOnly cookie with SameSite=strict, etc. which you can optionally sign just like you would sign a JWT although that's unnecessary. You might also find this useful: https://cheatsheetseries.owasp.org/cheatsheets/Authenticatio... > You should use either Argon2 or Bcrypt to store passwords. I've used randomly salted SHA512 to create a stored password. What's wrong with that? As long as the salt is an actual salt (i.e. unique random value for each user entry), it's not a disaster, but it's going to significantly easier to crack a password that was hashed once than one that's gone through hundreds of thousands of hashing iterations or used a more advanced algorithm like argon2 which is more resistant to cracking by design. The recommendation that I'm familiar with is to increase the cost as high as your servers can reasonably bear. High number of iterations and more advanced algorithms will increase the load on your servers but in turn they'll also provide much better protection. For a simple website JWTs are almost definitely an overkill (you would get all the drawbacks for none of the benefits). A session based authentication with some libs from your ecosystem for the crypto parts and a nice intro on how to combine them together could be the perfect thing for you. I have always found jwt easier to deal with than session based authentication. Nice thing of using sessions is that you mark cookies as HttpOnly and you avoid them ever being leakable by crosssite scripting. And you get them transparently in your JS -> backend calls. Of course downside is that once you move to multiserver you have to think of setting up sticky loadbalancing or distributed sessions. If you are using python and flask for building the web application, then there is a well defined tutorial on implementing user login and password. https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial... I had to implement my own because all the alternatives were some combination of 1. Crap 2. Over complicated for my needs 3. Ridiculously expensive Unless you are more experienced and smarter than average engineer working on a 3d party solution - you should build your own only for educational purposes. As others have pointed out, rolling your own simple username-password auth isn't too hard. As you go forward, you might need to add other things like 2FA or social login or SAML, and those things aren't exactly hard either (there's TOTP validation libraries in most languages I think, and for SAML you can use Jackson [1] which translates it to OIDC for you). It is quite boring though. What language/framework are you using? Typically you would implement your own authentication for learning the nuts and bolts of auth, but never for a production/live system on the web. You would either use something like Firebase Auth or the built-in one that comes with your framework of choice. Identity in .NET core for example. On the topic of auth, and as an aside, wondering if anyone has used a UUID + API key combination to do auth instead of JWT/cookies? Why never for a live system? Store users with an username/email and scrypt-encrypted password. On login, pull the encrypted password where username = $1. Compare. If valid, create a session id (fill 16 bytes with a cryptographically secure random number generator and encode it), store it that in the db along the user_id and some expiration time. You now have a session_id -> user_id mapping which can. ok, i was trying to do this for production. I am switching over to firebase but it's not working well with my client-server-architecture Ah I see, most frontend frameworks have libraries that work with firebase auth. If you use an MVC like rails or .NET core MVC etc, you can use Firebase auth from a CDN and put it in script tags along with JS to work with the library. Yes, multiple times. But if you'd like to build an MVP you can't go wrong with a SaaS auth service to get you started and transition to something else. Even better nowadays, there are multiple SaaS/starter kits you can use (most are paid) that remove all these chores and you can get down to your domain flow. I know a number of companies rely on Auth0 et al because it looks safer to customers, and in case of a breach it's good to be able to say that you are relying on industry standards etc. However, my own experience is that the API's are in fact more complex to deal with than just setting it up yourself. So at least for MVP's, I wouldn't recommend it. Yes. On login issue a single session auth token to be stored in the header and passed for all future API requests. You should consider one of the many frameworks that handle this sort of thing for you (every language has them.) It is unclear from your comment how you might be helped. Oh yeah. I built the oauth 2 stack at my company. Just read through the spec and made sure I did everything, and was obviously very careful. It was pretty boring and grinding. For a personal site, I’d use something off the shelf for sure.