Hacker News new | past | comments | ask | show | jobs | submit login
Ask HN: How do you currently solve authentication?
114 points by scottmotte on Jan 27, 2020 | hide | past | favorite | 99 comments
There are a lot of different ways to do authentication these days. How do you currently solve for it?

Any tools you swear by? Anything you recommend? Anything you hate? Do you recommend writing it from scratch or using a framework or service?

Depends on the project:

Firebase Authentication[1] is an excellent easy add on for apps (both Web and Mobile) that I want to get running quickly. It's free, scales, supports lots of social auth providers and can take care of email verification etc.

When I'm building a website it really depends. Wordpress and Django have excellent inbuilt authentication and authorization systems. Djangos can be quickly expanded to support social providers with `django-allauth`[2]

For everything else I use KeyCloak[3] - Red Hats open source Identity Provider/Single Sign On which supports oAuth2.0, OpenID Connect, SAML, themes etc. Documentation and support is relatively good but can be quite overwhelming especially if you're not used to the relevant standards (knowing the different flows in oAuth2.0 and which one you want to use).

[Self plug]: I'm building a KeyCloak-as-a-Service for those who don't want control of their authentication without the hassle of setting up their own cluster. We're in closed Beta at the moment but if you're interested you can search for "Tromsso keycloak"[4] and leave an email to be invited in.

[1] https://firebase.google.com/docs/auth/

[2] https://github.com/pennersr/django-allauth

[3] https://keycloak.org/

[4] https://tromsso.com/

Firebase Authentication.

I can't say enough good things about this service as it has been a game changer for me productivity wise.

-Supports most of the popular OAuth providers natively or you can add any custom OAuth system via custom tokens.

-SMS Auth, passwordless login (aka magic links)

-Excellent and well maintained client/server SDKs for most of the languages. Makes user management very convenient, including neat things like revoking tokens, cookie session management, linking accounts of users with multiple providers, RBAC via web tokens.

-Tight integration with Firestore. Can have fine grained security controls on which users can read/write what documents etc.

What takes the cake is Custom Tokens [1]. This is really useful for seamlessly integrating with another authentication system. Would recommend anyone to take a look if they're exploring an auth service.

[1] https://firebase.google.com/docs/auth/admin/create-custom-to...

I'm storing hashed password in the database. I'm writing POST http handler and storing user info in the session information. I don't know why would I use framework or even service, it's just few dozens of simple lines of code. I don't use frameworks for simple things. I guess it might make sense when one need to support login via Google, Facebook, etc, I'm working on enterprise websites which don't need that.

Presumably checking user passwords for security is out of scope?

How do you mitigate credential stuffing attacks? Throttling per account? Globally? By source IP?

A user leaves their company. How do you automatically deactivate their account?

You're using password hashes. Cool. A secure password hash function, right? Scrypt, argon2, maybe bcrypt? (MD5, SHA1, and SHA2 are not password hashes.)

You're comparing them in constant time, right? Are you sure? The compiler hasn't "optimized" you into problems here?

You're working with enterprise websites. You obviously support 2FA; and you're probably going to want to support SSO with SAML2, and definitely integrate with Active Directory over LDAP.

And your password reset flow- just send an email with a magic link? do you generate the magic link's token with a CSPRNG? Is it long enough? When does it expire? And admins probably have to be able to reset anybody's password, but with strong auditing and accountability features...

You store user info in the session information- basically caching it out of the database? How do you invalidate sessions after a user changes their password or has their account disabled?

Can somebody put Unicode in their password?

You're writing a POST handler. You protect against CSRF, right? (yes, tricking somebody into logging in as another user can be very useful!)

Doesn't seem so simple to me...

I think most people don't realise how many attack surfaces there are.

Good TLS and salt + strong hash solve the simple cases of DB theft and network MITM... But that's the bare minimum amount of protection.

As it does nothing for tokens being stolen, sessions, password reset hacks and emails being compromised.

It does nothing for stopping users trying to brute force. Password strength, loads of things mentioned.

I think the point is not really needing to know what good libraries mitigate against, but that you probably (as an individual) don't know all the ways that things can be compromised, and can't easily remember to implement them all, so you want a system that has been created, tested and improved by many security conscious people and out in the wild.

You probably wouldn't build your own lock for your front door either. The risks simply outweigh the benefits.

You're absolutely right, but there's one pretty critical point I want to make:

> Good TLS and salt + strong hash solve the simple cases of DB theft and network MITM...

It doesn't even solve this that. If you're explicitly salting your password hashes and not using a library, you're probably doing something very wrong. Unless you're hashing your passwords with an expensive key stretching function such as bcrypt or scrypt (or even better, a CPU hard hash like argon2) anyone who get their hands on your database can very cheaply bruteforce about 90% of your passwords (all but the most expensive ones).

A salt will only protect you from rainbow table attacks, and while that's useful, since computing SHA-2 on a GPU is so mind-bogglingly fast today, it just doesn't mean much anymore.

Depends. Spending years researching security and finding as many possible attack vectors and accounting for those, plus, building tests for the situations will make for a very hardened system.

More eyes on security, can also mean a short time of eyes by a single person on a single problem - missing the bigger picture. Adding to the problem, security researchers are very few and very busy (I've hired). They don't have time to look at open source code, unless there's a possible reward (that's big enough).

The most common front door locks sold are the ones people who pick can open the fastest, perhaps a bad analogy?

I can see what you mean, but that's not to say a normal person would be likely to do it better themselves though. Lock levels are selected (perhaps naïvely sometimes), based on a certain tolerable level of inconvenience and cost factor.

Luckily software is cheaper to implement strongly, but still email + password is usually selected as the method in spite of being the easiest thing to crack (as far as getting into individual accounts is concerned).

We could get users to all use ubikeys or more complex forms of multiple factor auth.

We could make it so that if you compromise an email account, you can't just reset all the external account passwords using it.

Plenty of sites allow insecure passwords that are in rainbow tables and cannot defend against targeted attacks (unless a user actually selects a strong password themselves).

Also just as houses often have big windows that can be smashed, perfect crypto / secure auth practices fail to work with the presence of an exploit somewhere else in the stack are frequent sources of compromise too.

It's not a perfect analogy of course, but actually I don't think locks / houses is a bad one. Users don't value security enough to want the most secure locks on their accounts and frequently get annoyed if asked to use 2-factor Auth, multiple passwords for single sites etc.

Nit: I don't believe that comparing hashes in constant time is important, as long as you accept the user's password and then hash it, since being able to find the prefix of the hash is computationally just as hard as reversing the hash.

Though it doesn't hurt to do anyway :)

It is important when comparing (some forms of) auth tokens, such as csrf tokens.

Side note: Using the language the correct way to compare hashes is important. Researchers found that PHP can coerce strings into scientific notation if the hash begins with “0e...” and using the == != operators, thereby causing a massive error space[1]

[1] http://www.darkreading.com/vulnerabilities---threats/php-has...


It's not so simple but also not an obscene amount of effort. Even with a Micro framework the first iteration should be there after a week or two. Probably most effort is 2FA and the whole E-Mail sending, verification etc. Especially testing this :/

Reliable implementations for hash functions are available for literally any language that is used in production. They take care of all the problematic parts. (In fact nobody should write this by himself or herself)

I'm sure as a custom implementer it's still possible to accidentally sneak in something time-dependent (still difficult to exploit, with smart rate limiting in place, I would say forget it) or a null/whitespace bug (easy to exploit but might require custom tooling). But that's just a matter of testing and having a 2nd pair of eyes look over it.

How do you know an off-the-shelve solution doesn't have the same problems or different ones? With a limited time/money budget auditing someone else's code is far more effort than doing the same thing with the own code.

Good points. Difficult and unforeseen issues like these are exactly why you'd use a framework of some kind, where thousands of users have already tested and fixed various issues.

incidentally though i ve not had passwords stolen from custom-built authentications (that were not as strong as u say), but i did from cms systems that are common and thus have tons of bots attacking them (e.g. wordpress). Security through obscurity should be added to off-the-shelf auth libraries i guess

Sounds like the perfect job for outsourcing to a 3rd party solution or using a battle tested framework!

I'd use a framework even for very simple authentication. There's just so much to supporting a decent UX that people expect now;

- limiting login attempts with a die off time between tries

- blocking automated brute force login attacks

- verifying accounts by email on sign up / invitation

- verifying username and password changes by email

- a friendly forgotten password workflow

- supporting even one basic 2FA factor (especially important on enterprise)

- logging user activity

- permission management

You could easily write all those things yourself. None of them are very complicated. But if you get any of them wrong it's very, very bad. Why wouldn't you use something that thousands of people have tested already?

Without disagreeing with your point, I'll make an attempt to answer this question:

> Why wouldn't you use something that thousands of people have tested already?

I think some of us find the most portable thing between projects -- across languages and platforms -- are outlines of what some part of an application has to be able to do and an ability to implement it from scratch.

There's certainly always some level at which off-the-shelf is a more productive and reliable choice. A DIY approach tends to yield more dividends to the degree that constraints or requirements in play would compel you to work against the grain of off-the-shelf stuff (thereby having to deal in the details anyway, not only for the problem, but for how the frameworks does things), and fewer dividends (or outright liabilities) to the extent that off-the-shelf will more than cover you.

Additionally, it's good to remember that something like Bob Martin's observation can apply: "framework authors are out to screw you -- that's not quite true, they're not exactly out to screw you, but they will screw you because the framework authors have their interests in mind, not yours." The language is a little bit over the top but it's true that dependencies are not solid foundation points, they're viscous potential points of future instability because they're projects driven by incentives that are not always aligned with yours. And the closer they are to the center of your app the more that might matter at some point. What happens with authentication if/when you decide to migrate frameworks? Or if your framework-supported application is only one of several (not all based on the same stack!) providing service in front of a common datastore?

It's worth reckoning with the overhead and hazards of DIY for sure, it's just also worth reckoning with the sometimes more subtle costs of framework buy-in.

I'll also add that while there are times I'm an enthusiastic supporter of framework use, I can't imagine being anything other than skeptical about outsourcing authentication to a third party service. Maybe there's a circumstance in which I'd find that would make more sense someday, but placing such a core thing in third-party hands gives me the shivers.

I can't imagine being anything other than skeptical about outsourcing authentication to a third party service..

Just to clarify, I said framework not service. I'm advocating in favor of using things like Passport.js that you run entirely yourself. I'm not advocating for auth services like Auth0 or Firebase Auth (which have there place, but require a lot more consideration beforehand).

Are you using salts, and what hash algo are you using? For a security comment on DIY I'd hope that you be more specific as I don't want somebody reading it and thinking they can just MD5 passwords with no salt and expect their system to be safe...

I'm using salt for every password with PBKDF2WithHmacSHA256 algorithm. It's an old algorithm, but it's not broken and it's supported in Java without any additional crypto libraries. I think that modern alternatives are bcrypt, scrypt and argon 2.

Thanks for that, I agree simple password authentication doesn't require a library, but there are still pitfalls and mistakes so I don't mind encouraging libraries as at least there is (for the popular libs) some responsibility taken for quality of implementation, and things like password reset mechanisms etc.

As you mention handling multiple Oauth providers and stuff that is usually not worth the effort without a library, but anyway. Just looking out for people like the younger me (who would probably have tried to roll out things they shouldn't have, naively).

If this were a tech interview and you had ever had a job in industry on your resume, I would likely end consideration of you a candidate and switch to mentor mode to help you understand what to study before your next interview (at a different company). I dislike when developers insist on “not invented here” mentality and anything concerning security should not be an excuse to reinvent the wheel and make the same mistakes a million other developers already made.

Auth is ridiculously complex, is the source of MANY critical security defects, has plenty of frameworks which solve significant parts of it, and always seems easy until someone explains to you what all you didn’t know you needed.


- login page

- two factor state

- password reset form

- username lookup form

- logic for 401 status

- logic for 403 status

- throttling, is ban, user lockouts, and/or captchas for the forms you don’t want attacked at scale

- if you are storing credentials on your server (like password hashes), you better know what the options are for hashes, what a salt is, have investigated bcrypt and scrypt, know what happened when any of the thousands of large websites had their user databases leaked

- maybe support warning users that their credentials in your DB matches a record in HaveIBeenPwned and lock down their account until they password reset using their email address

- have a plan for when the hash you chose is deprecated in a few years while you aren’t paying attention and need to spent days re-coding to support new hash and legacy hash users, auto-migrating the legacies on next login

- want to support multiple 3rd party IDPs as well as local password auth? That starts to explode complexity and the number of forms.

- want to support SSO for enterprise? Use a framework that already supports SAML integration

There are roughly 3 phases in your career. In the first, you don't know much and do things simply, naively. In the second, you know quite a lot, and like it or not you will be quite attached to your own expertise, it will be part of your identity. Your solutions tend to be complex, but you believe they must be that way, and you have evidence this is so. In the third phase, you begin to perceive systems as ephemeral results of some causal chain, and have a sense of how they became the way that they are. This depth of understanding allows you to embrace simplicity again, but this time you understand precisely the limits of that complexity.

I think a lot of professionals (not just programmers) get stuck in phase 2. This is where, in our field, most of the code comes from: capable, smart people writing new code furiously, and with the not incosequential fact that it provably works. Sure, it has bugs, but you can get to those eventually. It also happens to be the most "defensible" phase, where you get to speak down to others - you have concrete experience, real knowledge, so you are justified. I would guess this is also the bulk of working programmers.

So, the OP's solution could be coming from a phase 1 or phase 3 place. You are certainly coming from phase 2. I would encourage you to stretch a bit and consider when the OP's simple solution makes sense, and when it doesn't. I would hope you would do this in an interview as well, because you'll find phase 3 people saying all kinds of whacky things, which might not make sense to you unless you ask.

(A careful phase 3 will make sure to preface his simple solution with his limits, and to not do so is a little bit sloppy, but personally I don't think that's a deal-breaker.)

Fair enough, but if you have reached phase 3, you would undoubtedly know that Auth logic is fairly complex and rolling your own half baked solution will put your users at risk?

I can't think of a situation where OP's solution makes sense. Except for the obvious cases (app will never be in production, will never have real users or contain valuable data, etc)

The OPs soln makes sense for an intranet application with a small-ish user base (e.g. an internal app used by startup personnel) In this case, the likelihood of threat models like brute-force attacks, XSS, etc are all dwarfed by other threat models (social, physical, etc). I think it's a good compromise; and at least they aren't storing passwords in the clear, and picked a good hash function! These are really low-hanging fruit and you'd be surprised how often even this goes wrong.

In any event, I also believe there is a generally better approach to auth that avoids a lot of the complexity of traditional approaches. It's speculative, but see my other comment in this thread: https://news.ycombinator.com/item?id=22157951

I use Firebase since I don't want to be responsible for user data. I don't trust my security skills enough.

Since you hadn’t mentioned PBKDF2 or SHA256 (or higher), a usage of salts, nor handling authentication across service boundaries in an enterprise context, this is essentially an advertisement for using a third-party service.

If you are handling salts yourself, you should probably use something else D:

Last time AWS Cognito, and at least initially, Amplify.

I'd never write it from scratch. It's always a PITA, there's always significant compromises - do you make people sign up, do you let them use Google/every other available federated login provider, what 2FA options, will it work on a locked down network, etc.

AWS Cognito web interface is a dumpster fire if you expose it to people outside a small team. A little buggy, but terrible if your brand is associated with their out-of-the-box web flow. Password resets, username collision issues due to capitalization, login flow state can throw error messages that users can’t comprehend or fix, etc will all bleed customer support time.

The APIs seem fine, but you still need to build a GUI to replace all of the flows.

Okta is a far more mature solution for something directly customer facing and supports better 2FA options.

I want to use cognito but the documentation is not good. For example, how do I use cognito to authorize against an api I wrote? It's not clear from the documentation.

You'd probably use a custom workflow backed by lambda functions that interact with your api: https://docs.aws.amazon.com/cognito/latest/developerguide/co...

As a rule I think if you feel you're outside the sweet spot of an AWS service before you start using it, I'd take that as a steer that it's probably not the right route to go.

It feels like someone's hackathon project that was accidentally deployed to production, and has been running ever since.

Warning: this post is about a speculative design unproven in production. Definitely use the de facto standard framework in any production code you write!

I get so depressed with authentication complexity. Seems to me there are two ways to avoid it: first, write a service that doesn't care about user identity (it is a fun exercise to think of such a thing!), and second, secure messages, not connections or sessions.

Securing messages with public/private key encryption, I believe, is the best possible general approach. Thinking in messages yields the programmer great benefits, not just inside code (it is the cornerstone of the OOP paradigm, after all), but outside of code (message passing is also the cornerstone of distributed programming). Even if you are building a webapp it helps to think in terms of something more general. HTTP becomes just another channel over which messages move. Your app can (and probably will) become sensitive to other channels: email, SMS, webhooks, etc. If you embrace message-level security then you can ignore the channel and deal with the message. Channels may change, but your application code doesn't need to.

For an SPA, the key problem (no pun intended) is that a users private key is on the users browser, in the simplest implementation, accessible by everything on the page. If you're not end-to-end encrypted and don't use 3rd party resources at all (its possible!) then the naive solution is fine. The most robust solution is to use a browser extension to isolate the private key. The site requests encryption services from the extension.

Another fun and interesting problem is the multi-device user. Do we allow copying the private key, and if not, how do we associate private keys together? I think this is a fun problem from lots of angles, particularly the prospect of your own devices inviting each other to share an identity.

While it won't solve for SPA, the SPIFFE project (https://spiffe.io/) aims to deliver short-lived keys and certificates to workloads at runtime to allow them to establish channel authentication (mTLS) and encryption, and to generate & validate JWT tokens for individual message authentication.

Novel and I like the mental model. It seems like this pushes more of the management to the user - to manage the key. Or providing the user nice consumer tools to manage the key - adjacent to your core product. The hard part here is probably getting consumers to use/download/install that tool.

>The hard part here is probably getting consumers to use/download/install that tool.

I agree. I think there are ways to mitigate this, though. If the extension is open source, and very small then at least the digerati would be more open to it, and then it might become a standard extension, like ublock origin.

Kudos for reinventing WebAuthn.

WebAuthn, interesting. It's not quite the same, because they want to offload the private key storage and computation to hardware, which requires browser changes. My design requires either nothing or at most an extension install.

I use bcrypt to hash the user password and then store it in a database. When the user wants to log in I use the compare function of the bcrypt library. If the hashes match I set a session cookie.

I suppose if I worked on projects that wanted to support OAuth I would use Passport.js, but I don't know how much I would trust the any but the largest packages for that.

I use Auth0. Works well enough

Auth0 for complex stuff is pretty outstanding in my experience! It's nice to get sane and reliable OAUTH as a service...

I've rolled a lot of different custom authentication solutions for small apps with a handful of users all the way up to millions of users and thousands of concurrent sessions... having an "out-of-box" service saves a TON of time and headache =)

Not affiliated with Auth0, just love it to all heck. The free-tier offering is very fully-featured - try it out!

Auth0 is nice tbh but I find it quite pricey once you scale a bit.

I think it’s important to make good decisions at the very start.

I am definitely not against auth0 and I think it’s great, just think well enough before using it because it might come free at the start but after you acquire more users it comes at a hefty price

+1 for Auth0. I've used it for my SaaS cause I was sure that if I bothered rolling out my own I'd definitely miss some critical point opening up my users to a breach. Not only that but depending on your market your users may expect social-media signups/logins which becomes a pain to implement and maintain. The Auth0 free-tier up to 7k active users was more than sufficient for me when bootstrapping a new project.

I use https://www.pomerium.io/ for my internal services with Google oauth. I like it because unlike oauth-proxy I can define which users are allowed to which (sub)domains. I run this in Kubernetes and it supports forward authentication, so adding a new service is editing a configmap to let pomerium know about the domain and its allowed users (support for defining this in the ingress is coming), and adding a few ingress annotations.

In some Rails projects i use Device gem, or simpler version made by my own (salted passwords in database, and user_id as jwt in session store).

For Ruby, There is also Rodauth [1]

[1] http://rodauth.jeremyevans.net/why.html

Thanks for the link, Rodoauth looks interesting. Especially that all JWT things is already included.

Small correction, it's called Devise.

I use keycloak. It's just like auth0 except it's self hosted and I run it alongside all my other instances.

I'm not currently solving it that way but my next side project definitely is going to try out metamask as the mean of authenticating the user.

A friend of mine showed me some "dapps"(decentralized apps) that he uses (uniswap.io, axieinfinity.com and some other i forgot). They all used metamask as the "login platform". The point is that you have your key in this metamask plugin that is stored in your browser and you can sign things. That means you get a challenge from the server and metamask then asks you if you want to sign that challenge. The hole onboarding experience was super easy and you theoretically could use that to pay for some premium features of a service.

I thought that is really cool because you don't need to enter email, username, password and whatnot. You just click authorize and you're in.

It works if your app is only used by crypto crowd.. I'd never use it though, I don't want to have to have metamask installed in my browser.

I use Django’s included authentication.

If you ever want to support more complex sign up / log in flows, Python Social Auth is worth looking into. It provides almost everything you need for handling sign in through Google, etc. You can customize the sign-in flow to add e-mail validation, initial account setup, or whatever is necessary.


We use Django’s built in auth on an extensive Django site.

We have sign in with Facebook, but implemented ourselves, total of about 200 lines of code plus tests, which was worth it to us to own over having a dependency.

We have various custom additions to the auth flows which have meant the decision to stay with Django’s auth and not use complex extensions such as social-auth or all-auth have paid off enormously.

We use python social auth on internal Django based sites for simple Google SSO, but they have far fewer requirements around auth, and aren’t performance sensitive at all.

For Django projects I prefer to start with django-allauth. Saves lots of time later.

Can you elaborate on why? I've used Django a lot and have yet to find auth a problem after running things for quite a while, so I'm curious what the issues might be that django-allauth helps with.

Django-allauth provides templates, the ability to login with email, and other functionality that drastically improves the UX over what is included with Django auth. Django auth is still used on the backend.

Here is the link, for convenience: https://github.com/pennersr/django-allauth

Simple: Don't. Developing a secure authentication service is actually more difficult than it would seem on the surface. I've come to rely on an external authentication service (or, if necessary, a reputable library/framework specifically designed for it). These days my go-to is Keycloak (https://keycloak.org). It supports pretty much everything: standard username/password, MFA, SAML, OIDC, etc. Plus, it's easily deployable within a Docker container so standing it up is a breeze.

I haven't heard of keycloak before, but I'm not sure what to make of their SSL cert not being valid for the non-www version of their domain (i.e. your link). Such a oversight doesn't exactly inspire confidence in a security related product.

I'm certainly going to trust an authentication service with a bad certificate.

Well, the URL is missing www so you see the bad certificate error; Although, I agree that they should have handled automatic redirection from non-www to www.

I have been implementing different methods for oauth: - building my own handling with hashed passwords stored in the database - using the fantastic sorcery [0] gem for Rails. It's a light-weight auth solution that allows me to customize many different aspects of auth while providing a solid structure. It also has many sub modules that can be added for oauth, resetting password or stronger application security.

[0] https://github.com/sorcery/sorcery/

My users send their password over TLS. I check the password using bcrypt. I assume further communication over the same connection comes from the user.

Do you use a salt?

Also how do you determine what is the same connection and what mechanisms do you have in place to prevent someone stealing that session?

bcrypt does not allow me to not use a salt. A connection is the same if it's the same file descriptor and it's been open continually. My client uses public key pinning to ensure it is talking to my actual server. I don't have any mechanism to prevent someone who can break TLS and take over TCP connections from impersonating users in my online game.

Re salt, presumably you’re storing that bcrypt as a hashed string though?

Re TCP connections, I was thinking HTTP proxies. Sounds like this isn’t HTTP traffic though so that’s not an issue.

Also why was my previous comment negative karma’ed? All I was doing was asking a couple of questions on a post that’s quite vague. The amount of abuse HNs rep system gets is pretty absurd.

I'm storing strings like

  > =bcrypt.digest("hello", bcrypt.salt(10))
This string includes the algorithm, the difficulty, the salt, and the hash, so bcrypt.verify can do everything for me when someone tries to log in.

I appreciate your line of questioning. My reply to the top-level thread is pretty low value, since most people are trying to build web services that need sessions that persist across connections.

Complaining about downvotes is usually a way to collect more downvotes. This is partially because people are aware that it is against the guidelines at https://news.ycombinator.com/newsguidelines.html and partially because people get some sadistic pleasure out of punishing minor transgressions.

Ahhh awesome.

The game stuff sounds interesting too.

You're getting negative karma'ed because your comment shows a lack of understanding of what bcrypt is and what it does. Here's a short explanation: bcrypt is a hash function that you should use for storing hashed passwords. When calculating the bcrypt hash of a string, a salt is automatically added. The result you get looks something like this: `$2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy` The 2a specifies which version of bcrypt was used, the 10 is the number of rounds, N9qo8uLOickgx2ZMRZoMye is the salt and the remaining characters are the hash. When checking this hash against a password you have to call a second function and pass in the password as well as the hash. This second function will automatically parse the passed in hash and calculate the hash of the password with the same number of rounds and the same salt.

Nar, I’m familiar with bcrypt. I was just getting bcrypt mixed up with scrypt. Doh.

Even so, that’s still not a good enough reason to -rep without feedback.

Laravel built in auth, Socialite for social logins.

I am working on a hyper-open, hyper-compatible, and hyper-accessible forum system with accessibility by historic browser included in the spec.

I use a multi-layer authentication system with various levels of compatibility, security, and accessibility.

* The default mode is unauthenticated, which allows the user to post plaintext. Optionally, this can be backed by a device fingerprint, which would group all of this user's posts together. This is supported by all post-Mosaic browsers, except perhaps Mosaic 1.0, which does not support HTML forms. (For Mosaic, there is a fallback writing mode, of the form http://example.com/your+message+here)

* There is also a cookie-based authentication system, in which the user asks for a new ID, and the server sets cookies for user id and checksum. The checksum is checked against a server secret via hashing, so no storage of account data is needed on the server. This works with all cookie-supporting browsers.

* The other authentication system is based on PGP, and allows the user to either use in-browser PGP (insecure) or client-based PGP (less insecure) to sign their messages. These messages can be both client verified and grouped together into a profile on the server.

If I use a an external framework or library to let me users login via Google or say outlook, do I need to have my own outlook or Google account? Do I need some authorization to do this if say my company uses outlook for their emails and I want to let my co-workers use their account info to sign in through outlook?

Typically to integrate OAuth2 based authentication flows, you need an OAuth Client ID and Client Secret that identifies and authenticates your application with the provider. Generally this requires an account of some kind, though it may not always be identical to a normal user account on all systems. For Google you would need a Google account, its managed in Cloud console (though any kind of account will work.)

I actually don’t know if you need this if you just want to identify the used, off hand; I know there is a separate flow for that when using OIDC, but I suspect it still would have at least a Client ID. (This would be used for the provider to display your application name and possibly some other info.)

Does anyone know if there's a decent, comprehensive library that handles all authentication / login for .Net Core apps? Bonus points if there's a SSO addition (even if that part is commercial).

Identity.NET for embedding a library, Identity Server for hosting a service.

They're not the simplest, and unfortunately the scaffolding story with Identity.NET is a bit of a nightmare for MVC apps (if you're not careful, you can end up with a ton of hidden-but-accessible razor page endpoints), but the code is robust and most cases are covered.

Identity.NET will also need you to write your own implementations of a couple of database access classes if you don't want to drag a dependency on Entity Framework Core along for the ride.

Documentation is fairly dry and mostly complete (Microsoft style) but be careful with versioning because dotnet core moves fast.

Fantastic. Thanks very much for that.

Rails + devise even if my application is in another language than Ruby. Laravel could also do the job. Every time I have looked, authentication tools in Javascript are paid or overengineered.

Keycloak. Open source IDP.

I've been eyeing Firebase authentication for a Django project of mine, but haven't implemented it yet. Can anyone recommend it or advise against it?

I've used Firebase for authentication and it works pretty well and has good documentation. I haven't tried other options such as AWS Amplify though. I just keep a user reference in Firebase and then do everything else in my own app/db.

In .net world aspnet identity give you a basic login, can add social logins and identity server adds auth2 support. Both highly customizable

For user authentication: Hosted (Auth0 or Okta), self-hosted: Hydra

For Service Identity: SPIRE/SPIFFE... (or Oauth CC flow if mTLS is not possible)

keycloak is really awesome. This also makes sure when you move to any other oAuth2 authentication, we can simply switch the server details.

On the other hand firebase authentication is very scalable easy to set up and start.

Dont write it from scratch, if you are in JVM, Spring Security provides a robust implementation, we can just plug, configure and play

Spring Security for the logic and password storage. I usually build my own pages for password resets and logins

In my services, I use a combination of:

- hashed password or webauthn token - palm vein or usb token or (less preferred, SMS)

we've been plugging away at writing an open-source OAuth2 server: https://github.com/curveball/a12n-server


One very important aspect of authentication is session management. Doing this wrong (or naively), can have catastrophic effects for your app!!

Let me provide an example: It's common knowledge that JWTs are very common. A lot of people who use JWTs, implement them as access tokens for their APIs. JWTs also require a shared secret key - what if this is stolen? Then an attacker can use that to hijack any user's account very trivially, and you may not even realise that it's happened! This is far worse than anyone getting hold of hashed passwords from your database.

That being said, I use the following flow for session management: - User logs in, the backend issues a short-lived (~1 hour) JWT and a long-lived refresh token and sends them to the frontend. - The frontend sends the JWT for each API call while it's still valid - In the event that the JWT has expired, the frontend should then use the refresh token to get a new JWT AND a new refresh token (rotating refresh token - see https://tools.ietf.org/html/rfc6749#section-10.4) - If the refresh token expires, then the user has to login again.

While this sounds quite straightforward, the key here is to use rotating refresh tokens - that's what actually makes it fare more secure than just using simple refresh tokens (i'd argue that it's almost the same level of security as just using a long lived access token)

Some of the benefits of this approach: - You can detect token theft! If an attacker gets hold of the refresh / access token, because they keep changing, you can detect if an old token is used which is a strong singal of theft (see the RFC link above) - You can change the JWT secret key without logging any users out: Once you change the key, all JWTs are instantly invalidated. But then your frontend client can simply use its refresh token to get a new access token signed with the new signing key (along with a new refresh token). - Allow your users to be logged in for however long you want without compromising security.

Some implementation gotchas: - When changing the refresh token, be sure to not invalidate the older token unless your backend is sure that the frontend has received the new token. This can be confirmed by the frontend using the new access / refresh token. This is important since if not done, and if the user is in a bad networked area, it can lead to them being logged out. - See this blog and specifically this race condition: https://medium.com/hackernoon/the-best-way-to-securely-manag...

If you do not want to implement this on your own, you can also check out https://supertokens.io - It provides an end-to-end implementation of the above taking care of all race conditions and network failure issues. It also prevents other common web attacks which are on the OWASP top 10 list.


In terms of user authentication for the login part, I prefer using a no-password method - email or SMS OTP. The reason for this is that I do not have to care about managing user passwords (though that's not too difficult), I do not have to build forgot password flows, and most importantly, users don't have to remember yet another password.

I also only allow 3 attempts for OTPs per OTP. So after sending the OTP, if a user fails to input the correct one 3 times, then I revoke the old OTP and send a new one (this is so that someone can't simply brute force their way into an account). If the user login is successful, then I revoke all OTPs for that user. If the user clicks on sending the OTP again, then I send a different OTP (but the old one is still valid). This allows me to have a an OTP timeout of say 1 hour - which is more than enough!

According to me, this coupled with the above session management flow, is perfect!

Another thing to bare in mind, for those who are rolling their own, is how you caress those passwords from the DB.

The common approach is a simple DB SQL select. But that then means if your web server gets exploited an attacker can dump the entire password database.

The safer option is to write a stored procedures to return or modify that table and set permissions on that table so even your web app creds can’t directly query the password table. Then your web service only has access to check a single password, rather than downloading every hash on the DB.

If you can also offload the encryption/decryption and hashing then that is another step forward too.

Anyone care to elaborate how this post is wrong?

Hint: it isn’t. But I’ve been penalised for it all the same

I'll bite. It doesn't seem obviously wrong to me. I would also love to know if I'm misunderstanding something.

I've never seen it done this way, but I think postgres pgcrypto could support this.

If I had to guess, I haven't seen it done this way because authentication frameworks are not normally in a position to lock down access to the database in this way (e.g. it couldn't create a password table that the web app credentials can't see, because it's integrated into the web app and uses the web app credentials to create the password table). The way they typically behave is: - When updating password, run bcrypt in the web server and INSERT - When testing password, SELECT the bcrypt hash down to the web server, and test on the web server.

Have you used this stored procedure strategy in production? I'm particularly interested if it's caused any challenges with resource usage in the database server?

The top answer in this stack overflow question makes the argument that you should bcrypt in the web server to lessen the time it's unhashed: > Use php bcrypt if you can, it'll lessen the time that the password remains unhashed. https://stackoverflow.com/questions/2647158/how-can-i-hash-p...

I'm not sure I agree with this argument, unless perhaps the database is hosted by a separate vendor (which would mean another party is receiving the unhashed password). Also note: the strategy proposed in that answer doesn't have the benefit of a stored procedure preventing a SELECT all, so maybe the less time argument makes sense in that case.

Perhaps there's a valid discussion around - is this going overboard? Is preparing for a leak of web app database credentials an attack vector we really need to prepare for? If we do, are password hashes the critical data we need to be securing in this manner? When hashes leak I've been asked to change my password as precautionary measure, but hashing algos are such that this event shouldn't be catastrophic. Unlike a credit card number leak, for example, which would cause a bigger headache.

I learned this technique when I worked on the blue team of a cyber security firm.

It’s not about sending your passwords in clear text to your RDBMS. You’d still use bcrypt like you normally would but instead of querying the password table directly you’d have that prewritten as a stored procedure. That way you can have different permissions for the password table.

Some frameworks and/or other managed solutions might already be doing this but it’s worth mentioning anyway since people are talking about hand rolling their own auth.

I don’t know why I added the part about offloading encryption though. That doesn’t make sense. I guess that will teach me talking security before my first coffee of the day

I can't really use bcrypt like I normally would, since bcrypt normally* concatenates the cost and salt into a single string with the hash that I store in my database: https://en.wikipedia.org/wiki/Bcrypt

I believe I can split out the cost and salt. That would let me:

1. SELECT the user's salt and cost from a table that is accessible with my web app credentials.

2. Run bcrypt on the user-provided password with the selected salt and cost within my webapp.

3. Ask my stored procedure if my resulting hash matches the hash in the database, even though I cannot SELECT the hash directly with my web app credentials.

Am I understanding this correctly? I imagine it would have been easier pre-bcrypt, when generating salts was less abstracted away from the developer.

I can't think of a reason this wouldn't work, and it adds a layer of security if implemented properly. But I say that hesitantly, as I would all things crypto, particularly since I wouldn't consider it common practice and I'm not sure if I'm overlooking something. I'm pretty sure I'd need to hack on bcrypt-ruby more than comfortable to actually implement.

* I say normally because that's what the wiki says and how bcrypt-ruby behaves, but I haven't done wider research.

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