Hacker News new | past | comments | ask | show | jobs | submit login
Ask HN: What do you use to build auth?
98 points by lumenwrites on June 29, 2022 | hide | past | favorite | 138 comments
How do you build auth for your SaaS apps?

Do you use a library like NextAuth? Do you use a provider like Auth0 or Supabase Auth? Do you build your own auth?

I'm building an app using Next.js and Prisma. I'm currently considering Supabase Auth, Auth0, or writing the auth myself. People keep telling me that writing auth myself is a bad idea, and creating truly secure auth is really hard. Although I tried implementing auth with Supabase Auth, and I tried writing my own auth with Google OAuth and Magic Links, and my own auth ended up feeling much nicer and simpler.

I'm looking for some advice from more experienced people. What do you use? What would you recommend? What are the pros and cons of various approaches?




I too have seen the articles proclaiming that devs should stop implementing auth themselves and instead use some Auth as a service product. After all Authentication is hard to get right, right? Actually the basics are really easy. Using a short-term JWT and bcrypt to salt passwords is like maybe 10 lines of code. The thing is, most of the truly hard Auth problems I've had to solve in my career took a highly custom approach anyway.

I suspect most people use products like Auth0, not because they are trying to solve those hard problems, but more likely, because it's easy to set up and comforting to hand off that segment to a company that says they are battle-tested and secure, etc.

I personally like writing my own Auth because I can cater to my personal level of paranoia and learn more. Maybe I'm weird in that way, that I like to consider questions like, how short-lived should my token be? Should I issue a new token on every request? Local Storage vs cookie? Should I use a one-time token? Should I store the JWT in memory only on the client? How would I invalidate a user's token at will?

There's lots of interesting questions beyond the basics for sure and I can see how that might be intimidating. Most projects only need the basics though. And if you need more, it might be easier to extend your own implementation rather than some use-case not catered to by a library or service.

At the very least, I think it's wise for dev's to experience writing their own Auth a few times to get a grasp of some the challenges and better understand what those services might be doing for them.


> Using a short-term JWT and bcrypt to salt passwords is like maybe 10 lines of code.

You are presenting an extremely limited scope.

What you get from using an authentication provider is things like verifying email addresses, OAuth where you just have to "enable" Google, Github, Apple login possibilities. Implementing all these flows yourself is a lot more than 10 lines of code.

Then you also have to do password reset flows, resent email confirmation emails etc.


Yes, that's why I said "the basics are really easy"? This was not meant to imply 10 lines of code handle the complete user experience workflow around auth. In saying that I have implemented oauth for multiple providers in not too much more lines of code. Maybe like 100.


Also two-factor auth via email/SMS codes


Two factor is actually pretty easily solved too though?


If authentication isn't your core business there's little reason to handle all these things yourself.


also password policies, account takeover detection/prevention, user device/session list management


Devs should never default to using JWTs IMO, I think that is leading folks to delegate auth to providers as it overly complicates the process. There's nothing wrong with stateful API keys/session tokens, and I would wager the majority of web services still use them.


Jwt is a much easier term to google for information than the api key/session solution you mention. I actually default to jwt just because I don’t have a clear picture of what the alternative is called.


I agree, stateful sessions can handle a number of problems and use-cases more gracefully. I work with a lot of api's the service multiple clients though and I do see a use-case for stateless as well.


You didn't mention MFA. You didn't mention SSO. You didn't mention self-serve reset flows. Your approach doesn't work well with mobile apps. These are not rare, exotic things in 2022.


Yeah, that's why I prefaced with "the basics of auth are actually pretty easy". Rather than trying to opt-in to those other auth flows before you need them, I'd suggest starting with the basics and extend as needed. Although the MFA I've implemented was actually pretty easy too.


Personal story: Someone in the dark past of my company decided rolling their own auth was fine. Our platform is mostly Django so there's a lot of pieces in place OOTB so they thought it would be easy and it probably was. At some point, whatever this auth system was used for just fell off the websites. Some new login features were added back and they used hosted platform for passwords. Enter me, years later, no idea that auth every existed. Eventually we noticed a database table with thousands of users whose passwords were hashed with a now broken algorithm. They were probably sitting there for years and had copies, backups and snapshots wherever.


I don't quite follow the moral here. Was the Dev who rolled their own auth back when MD5 was the norm supposed to time travel forward to a time when cloud services like Auth and Cognito existed? Or does the fault lie with whoever replaced his auth with cloud services and forgot to drop the passwords table?

Most of the security nightmares I've heard of result from laziness or lack of care or someone not seeing a job through to the end. All of the encryption alogos we use will be easily brute-forced at some point in the future. Is it worse to store and back up those hashed passwords locally, rather than trusting Okta to do it for you (which incidentally was breached while your old MD5 hashes probably weren't)?


Auth providers have existed for a long time. And the point is that when you pay a vendor who does nothing but auth, they will be able to mitigate all the changes in the industry and (if you put it in your contract) be liable for damages from a breach. The also have up to date controls in place for protecting user data and likely go through external auditing. Give our org's limited resources we don't have audit trails on a lot of things and the reality that any number of past employees could have exfiltrated data and we'd have absolutely no way of knowing. Okta had a small breach which they disclosed that didn't seem to leak passwords, and if they did I'm sure they have controls in place to expire anything that may have been compromised. Hashing passwords is easy. Mitigating an attack is really, really, really hard.


Mitigating an attack is really, really, really hard.

How hard is it? What are the challenges? Could you be more specific? Cause I keep seeing the blog and article headlines telling me how hard Auth is but a lot of them don't go into details. That's the kind of mystification I'm having an issue with.

I'm not against using service providers for CAPTCHA or CDN's like Cloudfront for DDOS/brute-force prevention. Refusing users the ability to register an account with breached credentials sounds like a great idea though I've implemented something like this myself already.

I'd wager that aside from what anyone put in their contracts with OKTA, that they didn't pay out a dime for the 25 minute Breach.

Do I want to just pass the buck for the sake of saying, I'm not personally liable or being able to deflect and say, "look this happened to a lot of other companies too". That's part of the fear that these blog posts and articles try to instill with absolutes of "never ever do this..." or "this is way too hard for you..."

I'd argue I'm less of an attack vector than Okta for most of my use-cases. And I think that's part of the issue here, that a lot of us are talking different scenarios and perspectives. If I was an IT head or sysadmin, yeah, I'd probably use something like Okta or onelogin. For a web app with an admin panel for a restaurant taking reservations, Yeah, I'd roll my own and own the users table with passwords as well. For an enterprise-level web app, I might consider compromising and use something like AWS Cognito. But for all my own personal projects, a few paid contractor jobs, and even a few large-scale apps, I have rolled my own auth and preferred it largely to alternative like firebase, and auth0. I'm starting to get the picture that I'm in the minority there. If you don't care about auth and don't want the liability, sure go with a provider. I did mention in my original comment that maybe I was weird in that I liked going down the rabbit hole on auth concerns.


There's an old adage: If you think auth is easy to write, you probably don't know auth.

I obviously don't know how much it compares to your specific case, but as general advice it's often good advice when phrased less antagonistically: don't roll it yourself because the rabbit hole is deeper than you expect.

On that front, you may think you are paranoid enough, but keep in mind that the service products sometimes have a multiplier effect in play: N developers of various levels of paranoia, M people in various ops/InfoSec/auditing roles, X committees/layers designed to minimize corporate security risk.

If auth isn't your job and isn't your core competency, many times it is worth asking if following the rabbit down the hole is worth the time you could save outsourcing to a multiplier effect of a team that focuses 100% on those tasks. As with most "buy versus build" discussions, it's not just about "comfort" but leveraging those multiplier effects. Can you pay someone else for the years of experience and "rabbit hole wandering" and multiple layers of security audits? Auth is a "must have" feature for most products but in and of itself is mostly a security liability and mostly pure overhead: no customer is paying you directly for your auth features, auth is the annoying hurdle to features that they do care about and will pay you for. All that time spent on auth and auth security audits rarely appear to provide good returns on investment for your product and your customers. Time spent on auth is time wasted from user-facing features.


I've never head that adage. I did hear one from Miles Davis that says, "If you have to ask, you'll never know." I ask a lot of questions though so I never paid much attention to old adages I guess.

If auth isn't your job and isn't your core competency

I'd argue, it sort of is a core part of any web dev's job and any who neglect diving into it do so at their own risk. Maybe I come from a different time or place than what's the contemporary norm, though I'm okay with that. The main issue I have is with company-sponsored blogs and comments that will just blanket state you should never roll your own auth (because you can pay us instead, oh and btw, we rolled our own auth so you don't have to).


I can understand skepticism with company-sponsored blogs. For what it is worth, I don't have a product to sell here in this space and make no commissions.

As a user, I subscribe to haveibeenpwned alerts on my main email addresses and have been for multiple years. I think there are fewer humbling "[hackers leaking my users table] won't happen to me" reminders than that. It happens to everyone. The ones listed in haveibeenpwned are just the tip of the iceberg and the ones we know about and have been confirmed/verified.

As an enterprise developer, I've been a part of some of the worst security audits imaginable. Thankfully those were all preventative industry requirements, and I'd hate to have to deal with "the real thing". Those audits always come with a reminder: the most secure data is data that you don't have, anything else it doesn't matter how well you think it is encrypted at rest is a liability.

As a user I never want to have to setup another password ever again. I realize that's a pipe dream and we are still at least a few standards away from making that dream a reality, but I believe in it and I've championed it when I've thought standards got close. (I was a fan of the original, now dead OpenID [but not the Zombie OIDC wearing its skin]. I thought Mozilla's Persona/BrowserID was brilliant and killed too early in its infancy. I'm hopeful for Webauthn.)

As a developer I never want to own another database table with passwords stored in it. It's low hanging fruit that every attacker is looking for. I don't care at this point how those passwords are salted, hashed, encrypted, mashed, or other waffle house preparation keywords. Attackers still try to pull the records no matter how safe you think they are. Not having them at all is just entirely easier than worrying about having them.

I don't entirely care how I get rid of the password table. I've paid for solutions. I've used passwordless tools like "magic links". (To use those right you often need all the hard lessons of JWTs and other token types and keeping those secure. It's not necessarily "easier" or "harder", but a lot of knowing how to do it right transfers.)

I just believe pretty strongly at this point that the best password table is one that you don't have and don't have to manage. No matter how easy it seems to "just bcrypt it".


There's a lot of food for thought there and I can actually get on board with a lot of what you said. I enjoyed your perspective at the very least. I too have been a part of some tough audits, fedRAMP, etc. I've worked on apps that regularly get pen-tested. XSS is real, though more often I've seen ITOR issues. No need to worry about being hacked when you're giving it away for free. And then there were at least four OWASP courses I've been asked to do for work.

I'm not quite to the point of never wanting to own another user table with a password column. Maybe I will be someday. Yes, it's a liability but I still think my table (which lives on RDS or Aurora btw) is less of a target than Okta's users tables, which were breached earlier this year. BTW, Auth0 was recently acquired by Okta.

But yeah, if I was spinning up a large-scale, enterprise-level web app, I'd probably tell my stakeholders we were going with AWS Cognito or something, just to offset liability. Never mind, I'm still going to have to have a users table, and if I'm using Cognito for authorization (group-level authorizers) then god help me (check out their limits on those custom fields too). And btw, they use JWT, and their front-end solution Amplify still uses local storage to hold credentials. And it's going to be even more difficult to set up the basic auth flow than if I rolled it myself, but who cares, as soon as the execs hear AWS solution or cloud-native, they nod and feel assured. After all, the liability is now somewhere else as you said. Never mind there's a host of missteps and other ways you could still mess it up on your side of the fence there.

For all of my personal projects, a few smaller paid side-projects, and at least two enterprise-level products, I've rolled my own and owned the DB and it's felt much better to me than the alternatives I've had to face when I forced into some auth as a service solution. I've done auth0 twice (never again). Firebase once. Cognito at least 4 times. I still prefer to roll my own. Maybe I am a masochist. Maybe I've been lucky. Maybe I just go against the grain and do things my own way, providing less of a common attack vector.

The number of devs I've run across who don't even understand the basics of authentication has surprised me. Yes, it's seemingly easy in concept as you say, to "just bcrypt it" but it astounds the number of devs I've come across or worked with who didn't even understand what that was or what it looked like. Then we have the "company-sponsored blogs" and the echo chamber of people throwing down absolutes of "whatever you do, never roll your own", "you don't understand how hard Auth is", etc...

But I'm coming to accept that maybe I'm in the minority on this topic so I'll stop ranting for now. I suspect that a lot of us on this thread are speculating or speaking from different scenarios and experiences, like a sysadmin or IT head, vs legacy enterprise apps, vs mobile, front-end specific SPA's with stateless auth, vs server-rendered stateful, session-based web apps, etc...

In any case I appreciate you taking the time to map out your thoughts and perspective in detail and I think it's probably broadened my own thoughts on the subject.


Recommending people that don't know how to/if to do it (that's why they are asking) to write their own auth, trivializing the problem and in the same comment recommending using JWT terrifies me quite a lot.


There's nothing wrong with JWT as a token spec. I prefer stateful sessions as well but but a stateless token also serves specific use-cases. It has also become a standard practice for decouple front-ends that live on different domains, etc.


> I too have seen the articles proclaiming that devs should stop implementing auth themselves > and instead use some Auth as a service product.

It's a moved goal post which sneakily tries to position itself on top of the old adage "never roll your own crypto". Problem is, that adage is really about security whereas "don't roll your own auth" is about not wanting to do a mostly boring part of your job. I'd take my hat off if they'd admit it, but it's much easier to get budget with potential security scares compared to "we don't wanna".


Too true and worthy of a rant of all it's own...


Having your own password table even feels archaic today. From what I've seen, even simple internal apps are doing SSO with a directory provider (Google, AD/ADB2C, Okta, etc.)


I mean, it's stored in a DB somewhere, even if it's not your own. I would argue your own DB probably has less of an attack vector than major providers.


The identity federation protocol flows are pretty straight forward (I may be biased!) ... but you should use existing libraries for all the crypto.

Defeating credential stuffing attacks is HARD. That is where services such as Auth0 shine.


Existing crypto libs like bcrypt, which I mentioned? Or are you talking about something more? The credential stuffing mention you make makes me think you must mean something more. Does Auth0 by default advise users that they are using breached emails/passwords? If that is default behavior then I agree it does add a shining point to their feature-set.


Existing libs for JWTs and PKCE

Minimizing a credential stuffing attack requires detecting the attack and then adding captchas or other bot mitigation techniques.


captcha integration is super easy and doesn't require a full auth integration service. Detecting a brute-force maybe less so maybe, though I get a lot of DDOS pretection for free with AWS & cloudfront. But I was more interested in the idea of letting users know they were trying to use a breached email/password on register or login. I've got that on bitwarden (password manager), though now days I just auto-generate any password.


Not implementing it yourself does not imply that you should use auth-as-a-service. There are plenty of auth libraries out there for your programming language of choice. Take a look at their source code and see how much stuff is in there to get a sense of why you should not implement your own.

I use django-allauth: https://github.com/pennersr/django-allauth


Oh yeah, for sure, there are a really good libs. Someone mentioned passport. I've personally used Devise/warden in Rails. Though we had to monkey patch/extend it so much that 6 years later it was almost a different beast entirely.

But I'd still argue it's worth knowing what those libs are doing for you and you can only really appreciate it once you've rolled your own. I've done so on many a personal project where the risk was low. But yeah honestly, if I was rolling a large-scale enterprise app today, I'd probably utilize AWS Cognito. But this is also not for the faint of heart IMO.


The authentication portion of devise is actually really small!


In your “should I..”s, you mention implementing multiple insecure approaches. If you’re implementing sessions tied to localstorage, your application has a medium severity vulnerability. If you’re improperly invalidating, that’s yet another medium severity vulnerability.

The problem is, you’ll slip up here and there. The experts recommend not rolling your own for a reason; little mistakes and gotchas like the details in your post can lead to significant compromise.


I didn't advocate for storing your session in local storage. I posed it as a question.


The only time I think it’s okay is with PKCE.


I mean, yeah, sure. Or for a number of other use-cases. I'd argue the best way is for the client to keep the token in memory over local storage. Of course if you have a tightly coupled app, session-based secure cookie is the best.


I may be misunderstanding you, but I do want to reiterate: if it’s in localstorage, I will hijack user sessions on your pentest.

If there’s a use case to keep session tokens in localstorage, it’s insecure design that’s inherently vulnerable.


What I mean by tightly coupled, is if you can have your Frontend and Backend on the same domain, then yes by all means an httpOnly cookie is ideal. Now days there are a lot of SPA's that don't do that, or that have multiple api services across domains, or you are only writing a front-end and using some backend as a service like AWS amplify or numerous other scenarios that have led us to the concept of stateless authentication. You can still use a cookie in those situations, albeit without the use of httpOnly, which means they are going to be just as vulnerable to XSS as local storage. This is why I mentioned keeping a token in memory (this can be made even more secure with web workers). But since this doesn't persist across reloads, it's not an ideal solution for most leading towards utilizing strategies using refresh tokens/one-time use tokens, etc.


For small JS projects, I use Passport[0] as it is quite simple to implement and has ton of examples (including how to use it with Next).

For bigger projects where I need a full-fledged and reliable solution out of the box, I use Ory[1].

[0] http://www.passportjs.org/ [1] https://www.ory.sh/


I'm actually on the inverse side of this now:

I find Passport to be a dumpster fire of complexity and foot guns while Ory Kratos[0] + Ory Oathkeeper[1] have been the simplest way to add Auth to a project now (even for an MVP).

I've been using the zero trust proxy tutorial[2] and copy pasting the configs over. I just chuck some containers into Docker Compose and it goes. I don't even have to write the UI because Kratos does that but.

0: https://www.ory.sh/docs/kratos

1: https://www.ory.sh/docs/oathkeeper

2: https://www.ory.sh/docs/kratos/guides/zero-trust-iap-proxy-i...


Disclaimer: I am the co-founder of Cerbos[0]

Auth is actually a combination of two things: authentication and authorization.

Whatever you do, please do not build either by yourself. It always starts simple and it is guaranteed to get more complex than anyone is willing to maintain (unless you have a dedicated security engineering team)

There are many providers for each. Authentication is about the user's identity and where they belong in the organization (directory), and authorization is about what they are allowed to do based on their identity, role, and attributes.

Cerbos[0] is an open-source authorization solution which integrates with many identity providers to enable your product to implement fine grained permissions. We have integrated with the most popular authentication providers and they can be found on our ecosystem page[1]

Cerbos also has an out-of-the-box integration with Prisma[2] which enables you to fetch only those records that the user has permissions to from your data store - one of the most tricky parts of implementing authorization.

Whatever solution you end up going with, please save yourself some time and do not re-invent the wheel!

[0]: https://cerbos.dev [1]: https://cerbos.dev/ecosystem [2]: https://cerbos.dev/blog/fully-featured-authorization-for-you...


Just went to the cerbos.dev site-- there is a cookie banner that says you serve targeted ads, and asks me to "accept all". No option to reject tracking/ad cookies.

At this point, why even have the banner? Real As*hole design


Sorry about that and thank you for bringing it to our attention. As you might imagine we spend a lot of time on that site and did not notice the option to reject is not available. We will action this very soon.


Sounds like you should be using a service for it.


Auth is actually a combination of two things: authentication and authorization. Whatever you do, please do not build either by yourself.

It's blanket statements like this that really make me rant on this subject. Lets mystify auth and tell devs to stay away from it! By the way, pay me to do it for you...

I mean by your own blanket advice, you should have never made the start-up that you did. There are no absolutes (well only for siths). Just tell people the pros and cons and what features you have. I work on apps in production, running for almost a decade, which we rolled our own auth on, and that have been maintained with a very basic level of tech-debt. I stand beside that work and guarantee it to our stake holders. What I cannot guarantee is X-company for the next ten years and if we will be able to migrate our data off their platform if they don't get funding.

Auth is not that hard. Policies are not that hard. Unix solved permissions 40+ years ago. I would argue, that if you are a small business use-case, you will probably never have to worry about these issues. If you are enterprise, you will have money to spend on it and be able to hire the talent and expertise. If you are somewhere in-between, then sure, go for some easy-use provider that gives you a form you can iframe or react component into your app or whatever. There is a market and use-case for cloud based services for user management, auth, policies, etc... I'd personally go with AWS cognito in this case, which I think is even a good cloud-native approach for enterprise. But please stop telling every dev to never build auth or policies by themselves just because you just recently did it and are now trying to monetize it.


You are overlooking a very simple fact in your comment. Cerbos is open source and has an Apache2 license. Therefore most of your points are irrelevant:

  * No one needs to pay
  * No need for a company to be around for the next 100 years.


What I am not overlooking is that they as a company and in this comment have an implicit bias against Dev's rolling their own auth since their business model is based on them not doing that. The most critical point that I raise that is not irrelevant is they are prone to making blanket statements and falling into absolutes with "Never ever do this..." and "This is way too hard for you..." even though there are a wide array of diverse scenarios and use cases in web dev. And even if it is open source, a lot of enterprise won't touch it if there's not a support plan, or at least a lot of companies would not be willing to fork and maintain a large open source lib they had little dev involvement with. So their death as a company would essentially equal EOL for a good number of clients regardless.


This is very cool. I'm familiar with CASL for authz which also has a Prisma integration; is the main benefit of Cerbos over that the built-in logging?


Built-in logging is definitely one of the main benefits. However, the following are also other major benefits of using a service like Cerbos:

  * By running as a standalone service, any part of your application stack (in any language) can make consistent authorization checks 
  * Support for most major programming languages via SDKs
  * Infinite scalability via serverless functions or sidecar deployment model
  * GitOps enabled policy development and deployment via a full testing suite for ci/cd pipelines. 
  * Full audit trails of every decision made and how they were derived.
  * Simple human readable YAML policies
  * Ability to have different policies for different environments and ability to have canary deployments
You can find more about all of the benefits and features on our product page[0]

[0]: https://cerbos.dev/product-features


How does this compare to Keycloak?


Keycloak handles both authentication and authorization and they are tightly coupled. Cerbos solely focuses on authorization and is capable of integrating with any authentication method that is already existing in your application.


If you are going to implement yourself I would recommend familiarizing yourself with the NIST SP 800-63b [0] guidelines.

Have a good understanding of cryptographic primitives and what the state of the art is right now for hashing, salting; both at rest and in-transit, etc.

And make sure you follow the principles of least privilege.

Of course this is a fair bit of work and there are specialists in the industry who've made authentication into a service which takes care of following the guidelines and best practices... if you know how to vet them.

They don't always get it right either. Standards and practices evolve. Authentication (and its sibling authorization) require keeping up to date and being vigilant.

[0] https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.S...


I write my own, and I mostly use session cookies. I do support login from other OpenID connect providers like Azure Active Directory(AAD) in addition to old email/username/password + 2fa with otp. Basically when they have successfully authed I create a new session cookie for them. The disadvantage is that when the user logout AAD, they still have a session in my application. Though I can always force logout by having a background job that validates that the user is still logged into AAD.

I've heard people say that writing your own auth is bad and hard, and the same people fucking it all up with a misconfigured Apache/Nginx server because they don't read/understand the documentation. Mistakes do happen, do your research, discuss it with others and you will learn a lot while creating a secure system that was not that hard to implement in the first place.


Hi! Disclaimer, I'm the co-founder/cto at Stytch[0]. We built Stytch because we went through the pain of building auth both in house and with incumbent players and wanted a better tool for developers building authentication. Stytch is flexible to enable you to build the experience that you want for your users but we do all the heavy lifting when it comes to both authentication and authorization.

We have support for both magic links and google oauth as well as many more options, one of the benefits of going with a provider is that with one integration you'll be able to get more auth products as your auth needs expand and get more complex (ie 2fa with authenticator apps etc). We also handle all of the fun edge cases when it comes to things like email deliverability and ensuring that your magic links end up in your users primary inbox and don't get blocked by spam filters etc.

I'd love to answer any questions you have and help get you up and running with auth so you can get back to focusing on your product!

[0] https://stytch.com/


I'm currently working on a project with the same stack: NextJS + Prisma + Postgresql and I started to implement this open source auth library:

https://supertokens.com/

Here is the documentation for implementing the library with NextJS:

https://supertokens.com/docs/thirdpartyemailpassword/nextjs/...

Btw, the library is backed by Ycombinator.


Thanks for trying us out! Feel free to reach out if you have any issues


Well, I wrote one with rust and actix-web for exact same purpose.

In my opinion, writing basic auth is simple and safe if you keep OWASP guidelines and other best practices in mind but adding features like SSO and MFA etc is complicated. With that said, almost everything else I tried feels so heavy and slow that I'm sticking with mine for now.

If I've to use prebuilt solutions, I'll pick one that is open source and can be self hosted.


Seconding this.

Basic auth is easy.

The hardest parts are OAuth, SSO, MFA, OWASP Security, tracking metrics correctly. Good lord.


I researched and tried several hosted auth solutions.

I ended up choosing https://userfront.com/

I think it has the best DX.


We did the same and it has been great. Their MFA beta is so much simpler too. I do wish they were easier to find...


For most projects these days I will use a provider for two reasons:

1. Easy to implement 2. The burden of security is moved.

I use clerk.dev for almost any project at this point. They take care of auth/ authorization/ database sync.

Sure I could implement these on my own but why not use SSR for next and hook in and have everything setup in minutes so I can focus on the rest of the app that matters more.


Disclaimer I work at ZITADEL and am one of the co-founders.

We always recommend not building auth by yourself. In the first place it may look simple like its only two input fields and a button (username, password), but to get a really secure solution its a lot more to do. You might need some more authentication methods like passwordless, mfa or identity brokering with google, microsoft, etc.

With ZITADEL we built a solution that combines best of Auth0 (great SaaS solution) and Keycloak (opensource). We believe that a cloud SaaS solution is great to go if its possible to use a cloud solution, but there are always lots of on-prem use cases, thats why we are opensource. https://github.com/zitadel/zitadel

ZITADEL is also focused on B2B usecases, so you can have multi tenancy really easy.

If you have any questions just let me know.


I try wherever possible to use tools but it's tough -- I have some signup features that need to integrate tightly with login flows, and stock framework auth is often not flexible enough

I spent something like 3 weeks this year on refactoring related to auth systems -- it's endlessly frustrating to me and I blame the fact that there's no web standard for login

I avoid 3rd party providers like auth0 -- I believe that they're better at security than me, but 1) they're a large target, 2) they're solving a harder problem and 3) giving the keys to every user acct to auth0 et al feels like too large of a compromise to make on behalf of my users. (that said, if I'm breached, I've given data to a worse third party).

also not wild about oauth, esp from a consumer perspective -- too easy to expand scope later and demand privacy leaks in exchange for logging into your acct


I build my apps on Sandstorm[1]_. Sandstorm provides authentication as a part of the platform. For Django applications, I wrote Django Loves Sandstorm[2]_.

If your application fits into Sandstorm's model of grains[3]_, then the security benefits of Sandstorm are many.

.. [1] https://sandstorm.io/ .. [2] https://pypi.org/project/djangolovessandstorm/ .. [3] https://docs.sandstorm.io/en/latest/using/security-practices...


and is there a way to turn this to serverless?


I sleep better at night thanks to Spring Security and KISS. [1]

Reading the docs from top to bottom, and diving into the source code makes me believe that "you should never roll your own auth" should be an addendum to "you should never roll your own crypto". The number of edge cases and gotchas is simply mind-boggling. It's not about being a good enough programmer to cover yourself, but about years of collective experience dealing with all sorts of exploits and browser shenanigans.

[1] https://docs.spring.io/spring-security/reference/servlet/aut...


I’ve been tinkering in this space for about a year now. They all have their own problems.

- NextAuth is bare basic but gets you going real fast. The most examples - both simple and complex - and works with so many DB adapters.

- Clerk was probably the nicest developer experience: fast, works with many frameworks, and great community. But there’s not a lot of support outside of basic examples.

- Supabase Auth is a little more mature than Clerk and ultimately what I ended up choosing. But it doesn’t have the out of box features: orgs, different environments, MFA.

As I said, landed on Supabase for the application database. It makes a lot of sense and works great.


MFA is close - aiming for our next Launch Week in August


I write my own. Though my platforms do not socially integrate.

I tend to use one API endpoint for pass phrase authentication, which returns a token (any sufficiently complex unique string, such as base64 (or hex) of a >128 bit unique key . Many auths use a hash, to which I say don’t get carried away)

The token is a temporary throw away credential that should:

* expire (say 8 hours)

* times out after inactivity (say 2 hours)

* unique to session (allows distinction among concurrent sessions). I hash the token to create a unique session ID for logging

I only store these in cache, not the db so they expire and cannot be recovered (hashed again to create a trackable unique value.)


From a user perspective, how does everyone here feel about magic links vs email and password?

Personally, I am torn.

As a developer, magic links are awesome. You put a new project online, and everyone on planet earth already is a user. Well everyone who has an email.

But from a user perspective, it is more cumbersome. For one because the switch between email and website. And because the typical magic link implementation invalidates the link after one use. So if I don't keep the cookie, I have to do the "enter email, receive email, click link" dance again. Entering my email and a password is faster.


There are users out there (likely even people that you know, because statistically it's a lot of people) that habitually never remember passwords and their login flow is almost always "Click Forgot Password, Enter Email, Receive Email, Click Link, Enter new Password they also won't remember" so from that perspective magic link flows save at least two steps!

Even power users that have trained themselves to use a password manager generally have more steps than they think they do to open the password manager, enter master passphrase/biometrics/etc, copy and paste the password.


said it before, but I love magic links. One more site where I dont have to create an username/password (and yes its a hassle, even with a password manager)


I'd rather use SSO over magic links as a user, for what it's worth.

Email is unreliable, there's typos, people not knowing their email address, etc. Meanwhile with SSO, two clicks and it logs you into the site with the email you're logged in with.


For me, Auth0 was the quickest and easiest.

I only wanted read-only social network login.

There was an official library in the language of my choice.

It was free (at my level of use).

The only thing I need to keep secure is the API tokens for Facebook / Twitter / GitHub etc. I don't even bother storing anything other than the user's ID, current name, and service.

If someone hacks my service, they won't be able to do anything nefarious with the user's data.

Building your own is a nightmare. If a login provider changes their API flow, Auth0 are incentivised to fix it - rather than passing the buck to me.


Wrestling with this now for a side project. I've landed on .NETCore+ASP.NET Identity after getting frustrated with NuxtJS+fastify-auth, but that's really because I'm more familiar from my day job and didn't like the SPA road Nuxt was forcing me down.

That said, I have a related question I'm hoping the security nerds here can help with: I know it's bad practice to reveal the existence of an account during registration, because it gives an attacker a way to know if a user has an account. So on registration, if the email already exists on another account, you shouldn't say "that account already exists" or do anything that would reveal the account already exists. To me, that means you should always send the user to a "registration successful, check your email" page and then if they already exist, send an email saying it exists with links to password reset & login. That means that the app must be unusable until the user validates their email. But that seems annoying and is not what many sites do. For example, I just tried on shopify, and if the account already exists, they send you to the login page. If not, they log you in automatically. So, for shopify I could in theory scrape using a email list and find who has accounts. To see why this is bad, think of shadier sites (my saas is not). So, my main question: am I making too big a deal about this security requirement or the usability problem it presents? Am I missing some alternative?

Related, I'm thinking about letting users send an email to bot@mysaas.com or text 5558675309, which would respond with a "finish registration" or "login" page and auth token accordingly. This would let them skip the verify email step. Is this a bad approach?


I think you should focus on what an attacker gains by your app leaking account existence. Is that knowledge valuable or revealing? If not, then probably not necessary to overcomplicate it.

E.g. in the Shopify case, you learn that an email address has a Shopify account. That should be fine as long as they have some rate-limiting in place on their auth endpoint and enforce good passwords.

YMMV, I'm not a security expert, etc.


I’ve always liked the way Apple does it. For iCloud, the ‘Forgot Password’ page requires a first and last name. I imagine you could do something similar for registration: if the user email already exists and the first and last name is the same, tell them definitively if the account exists.


Your question is missing a couple key inputs. Q: Is your SaaS app targeting enterprise use cases, where the customer will want to enable SSO and centralized provisioning? Keybase is a reasonable choice in this case because of the SAML and SCIM support. Q: What is your expected revenue per user? Auth0 solves many problems out of the box, but is priced on MAU which can be prohibitive if your revenue per user is low, but deals with lots of complicated issues if not and lets you focus on building your app.

I'm the founder of Hellō[0], and if you are targeting consumers or individual professionals and want to give them choice, check it out.

As some background, I cofounded the OpenID Foundation, drove creation of OAuth 2.0 and what became JWT, and gave a popular Identity 2.0[1] talk years ago.

[0] https://hello.coop & https://hello.dev [1] https://www.youtube.com/watch?v=RrpajcAgR1E


I think you meant KeyCloak not Keybase? haha.


I did!


> People keep telling me that writing auth myself is a bad idea, and creating truly secure auth is really hard.

Yes the problem these days is a lot of commercial providers want this to become "common knowledge" and for it to be "best practice" to use their systems. But what happens if Okta has a data breach and you don't even know if your users were affected? (This happened)

I strongly believe in rolling your own auth:

1. It keeps it simple

2. You control the data that's a critical part of your system

3. Okta and Auth0 are giant targets because they have so many peoples' creds - you aren't

4. Even if you do use something like Auth0, you still need to implement authorization somehow. Of course, there are people who want to sell you solutions for that too...

Use libraries for the underlying primitives like bcrypt and JWT's. Do the rest yourself. Keep it simple.

Oh, and keep it simple.

The one good reason I've seen recently to use third party auth services is because they often support MFA. But how many companies actually need that? I've worked for a bunch of companies over my career and the amount of times I've had to implement/add MFA is 0.


I'd also argue that adding MFA with TOTP really isn't _that_ hard either. There's a bit of setup work to be sure, but it's a feature just like any other that has a pretty easy to grasp flow once you do a bit of reading.

Don't do your own cryptography (just use bcrypt or if you're confident you won't mess it up, libsodium), but authN/Z is entirely within the realm of "roll-your-own" and should be table stakes for most businesses these days.

Even adding SAML or OIDC support really isn't that hard.


Auth0. I've tried a bunch of third parties and I found Auth0 to have good documentation, a great free plan, good support, and a user experience that is quite good. Some of the Rules/Actions terminology is a bit confusing, but overall the management UI and APIs are quite good.

In addition, they have easy means of customizing the User object, querying external data sources, etc. Highly recommend.


In the past few years, from zero knowledge to implemented the same auth features including login, registration and reset password etc in past company projects.

Hashing the password with Bcrypt and auth with session-cookie for login. It's not easy but once you start implementing those on your own, you will learn and understand more.


Simple hashed passwords and a few emails are not hard to make myself so I do that. Also makes it much easier to tie in roles which are much different for each project. It really isn't that hard to build a simple one yourself and gives you much more control and one less dependency on an outside service.


Whatever the server side framework offers natively, plus framework specific plugins such as for OTP login or whatnot, depending on the project. If your framework doesn't take care of authentication for you, it's probably not production ready.


I built a Next.js library for this purpose using Hellō and iron-session. This lets me roll a new application with social login without needing to register with Google/Apple/other providers.

https://github.com/irrelevelephant/nextjs-hello

Its interface is essentially just a login button component, and functions to retrieve the user session state on both the client/server.

If you're not using Next.js, you may want to use Hellō directly - it's a simple OIDC provider with some convenient benefits.

https://www.hello.dev/


Implementing simple auth is not that hard, with JWTs. But you need to use a service anyway for mail (confirm password, reset password etc.), so in the end it's not worth. These days I use Supabase auth and it works.


If I want to put something together fast I use the default AWS Cognito and Firebase Auth widgets. I think Firebase Auth has more third party sign in options.

In my current project I do away with accounts completely and just email a link that sets a cookie for 30 or 90 days [1]. I think the Auth you choose highly depends on the money/privacy/sensitivity/fraud potential of your project.

[1] https://tedpiotrowski.svbtle.com/shade-map-pro


Absolutely recommend against using AWS Cognito. It is a nightmare to use.

Currently I am trying to integrate Firebase into AWS because of how bad Cognito is.

One thing going well that Cognito will never be is Firebase Auth.


What made it a nightmare to use? We're just about finished migrating to Cognito (using our own UI) and it's been the same experience as working with Auth0 but much cheaper. The only goofy part was in order to have a custom password reset email you need to put it in a lambda.


Attributes. There are standard attributes like email, phone_number, name, address. Then there are up to 50 custom attributes you can define which need a min/max length and can be of number or string type. You can't remove or change them after you define them. As you user metadata grows this can be insufficient and inflexible causing you to store user data set in another place like a DB. Now your user data is fragmented. Part of it is Cognito and part of it is in the DB. This leads to complexity and performance hits when querying data and consistency issues when updating data. I would avoid using Cognito attributes at all costs and use a DB table for user metadata instead.


Ok, good to know. We've always used our IdP as bare bones as possible and store all user info locally in the DB, so that's why this wouldn't be an issue for our particular setup.


I wish it was easier to use Firebase Auth without the half-maintained javascript mess that is firebase-ui, which has not worked with the current Firebase SDK for, over a year now? (or at least I still failed transitioning from SDK 8 to SDK 9 as of a couple of months ago).


I got it working a couple of weeks ago


You're right. Things I don't like about Cognito is it stores your users email address/phone number but limits additional metadata so you need a separate user DB table. Now you have to keep Cognito and your user DB table synced and if you want to display a users email along with mailing address, etc on a page you have to query both Cognito and your user DB.

The ease of two factor Auth is nice though.


+1 That's one product AWS completely dropped the ball. Also, it has not received relevant updates for a long time.


I usually write it myself with Django, Django REST Framework and JWTs alongside either Vue.js or Ember (and their with libraries).

Truth be told, I usually hate having to do it. That said I’ve never found a reasonable alternative.

There are usually differences in each set up that require customisation (for example magic links like you mentioned) and trying to integrate a platform like auth0 feels like it would be as much work.

I also don’t like the idea of the inevitable migration when I need something else it doesn’t offer, it goes out of business or gets acquired.


Regarding magic links, this is where you are emailed a link and login ?

Do you know any libraries that make this easy ? Looking for this myself using Django.



Looks perfect, thanks!


Always go back to devise in rails land. It isn't worth the effort to integrate with an external service for the side projects I work on, but maybe I should try it just once


I'm exploring a signature-based authentication scheme here: https://github.com/jshawl/proof.im

At a high level:

1. Claim and prove ownership of a public key 2. Sign a session claim that links the handle with the public key 3. Service verifies the claim's signature was signed by the corresponding private key


I bet just passport js with its many strategies is a good enough option for 98% of SaaS startups out there.

It’s not a rocket science unless you’re big enough to bother about tricky use cases and unique security requirements.

Despite what Auth providers are trying to promote.

PS: I mean authentication only. Authorization seems like a different beast with different challenges, sometimes tightly coupled with your business logic.


Not exactly your question, but since you are using NextJS I highly recommend you use its API route[0] support to proxy your backend API calls, which allows you to avoid exposing auth tokens, etc to client web front end

[0] https://nextjs.org/docs/api-routes/introduction


If the front end isn’t sending an Auth token back then the front end isn’t logged in. How do you propose making authenticated calls from the client?


Next handles the session, I mean exposing one or more OAuth/JWT for backend services.


I use firebase auth because it’s free at any scale and it takes minutes to set up. It’s backed by google so I’m not kept up at night.


Same. I feel like I'm missing something by the vast majority of other comments saying roll their own/unknown third party


I think if I had my own enterprise product with a lot more complexity, I would roll my own.

It’s possible I am using the product wrong, but I found it kind of hard to use the rules engine for granular access. What I did instead is make my own simple permissions engine and since my backend APIs verify against the firebase token, I then pass that into my rules engine before it writes any mutations.

I lock down firestore access by using my own api that then uses the admin sdk. Obviously this is a bit slower but it gives me the most confidence that only my backend services can make changes to the data.


Same as well. Basically authentication->firebase, authorization->backend api (I normally write custom python decorators for this)


We've rolled our own (zero frills) so far, but are looking at PropelAuth (https://www.propelauth.com/) to add MFA and other bells and whistles and we like what we see. (Full disclosure, they've become friends of ours through YC)


Thanks! I’m the founder of PropelAuth - our focus is providing user authentication for b2b businesses. We did a launch HN[0] a while back if you want to read more about us.

[0] https://news.ycombinator.com/item?id=30700770


I just started using FusionAuth and am a fan. It's like a cheaper, better documented Auth0 that you can self-host.


To get the best of both "build" and "buy", I recommend using one of the open source alternatives.

That way, you have as much control over it as if you built it yourself but it comes ready made and off the shelf.

The open source options are: Keycloak, SuperTokens, Ory and many more

(Im the cofounder of SuperTokens)


Django auth only for projects that have their users in the database.

Django-auth-ldap with python-ldap when I need to use ldap.

Django-allauth when I need oauth providers (google github etc)

Requests-oauthlib integrated with django auth when I need a more customized solution.

I've never understood the reason to use anything else ...


I've tended just to go with the quickest and easiest thing for me, which is firebase + jwts.

I'd be interested to know points to migrate away from firebase/google dependencies. I struggle to use anything else as it's so easy to get all the social logins set up...


I got used to Keycloak and now I like to use it for pretty much everything


We use identity server from M$ its fairly good and works for our purposes, its easy to bind clients etc. we can always expand it if we want it to do more.


I just spent the last week building one using webauthn. It’s actually pretty awesome and I’ll probably open source it in the next few days.


I am surprised that I did not find keycloak here…


For small projects, Keycloak is wayyyy too heavy for them. It requires multiple domains which makes sign outs hard... a OIDC server and client... it's a lot.

It works well when you need to stitch together multiple services but otherwise it's not something I'd use for an MVP. (And even then you can wrap Auth with nested subdomains and a top level cookie w/ a proxy to pass headers to each service. Easier and less complexity because state lives in one place.)


I usually use the default docker image. Use an older config file or use the Keycloak web interface for configuration. There are Keycloak libraries for laravel, react,vanilla js etc., so I felt the whole architecture was pretty simple and 30 mins of work to get it all set up.


The only use case I've come across Keycloak is for China auth where we can't use firebase


As an IAM engineer who's been doing this shit for way too long, I'd write my own auth.

But you? It depends on what your goals are :P


I use a library called Flask-Login that provides the framework for good session cookie website auth.


Out of the box with Laravel and sometimes Socialite if I need to integrate other social logins.


Currently a lot of stuff is organically grown, but moving to keycloak for a lot of things.


OIDC or x509 on the proxy and it passes the username through


next-auth has been the best I've ever used.


I have used AWS Cognito and Azure AD B2C


Firebase auth is really easy to use


There is oidc-provider for Node


Cognito


Auth isnt hard, built lots of auth systems.

Crypto is the thing I won't touch with a ten foot pole.


-1 Auth (in the form of broken access control) is literally _the_ most common security problem according to the OWASP Top 10 [1]. And I think people thinking it isn't hard does significantly contribute to this questionable honor.

[1]: https://owasp.org/Top10/A01_2021-Broken_Access_Control/


Authentication systems are the most common thing to have security related bugs?

I'm shocked.

FWIW, the majority of things on that list aren't what I'd consider covered by any auth library I know of.

It's mostly people just not using their authentication, diy or not.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: