top | item 22157166

Ask HN: How do you currently solve authentication?

114 points| scottmotte | 6 years ago

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?

99 comments

order
[+] kisamoto|6 years ago|reply
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/

[+] nujabe|6 years ago|reply
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...

[+] vbezhenar|6 years ago|reply
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.
[+] XMPPwocky|6 years ago|reply
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...

[+] onion2k|6 years ago|reply
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?

[+] sammorrowdrums|6 years ago|reply
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...
[+] thephyber|6 years ago|reply
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.

Components:

- 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

[+] Kiro|6 years ago|reply
I use Firebase since I don't want to be responsible for user data. I don't trust my security skills enough.
[+] rmdashrfstar|6 years ago|reply
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.
[+] cs02rm0|6 years ago|reply
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.

[+] thephyber|6 years ago|reply
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.

[+] friedman23|6 years ago|reply
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.
[+] javajosh|6 years ago|reply
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.

[+] ajessup|6 years ago|reply
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.
[+] scottmotte|6 years ago|reply
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.
[+] sansnomme|6 years ago|reply
Kudos for reinventing WebAuthn.
[+] fantyoon|6 years ago|reply
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.

[+] domlebo70|6 years ago|reply
I use Auth0. Works well enough
[+] folkhack|6 years ago|reply
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!

[+] muse900|6 years ago|reply
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

[+] chauffer|6 years ago|reply
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.
[+] skyfantom|6 years ago|reply
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).
[+] hugofloss|6 years ago|reply
Small correction, it's called Devise.
[+] kcolford|6 years ago|reply
I use keycloak. It's just like auth0 except it's self hosted and I run it alongside all my other instances.
[+] zwarag|6 years ago|reply
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.

[+] gremlinsinc|6 years ago|reply
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.
[+] clintonb|6 years ago|reply
I use Django’s included authentication.
[+] rgovostes|6 years ago|reply
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.

https://python-social-auth.readthedocs.io/en/latest/

[+] anticodon|6 years ago|reply
For Django projects I prefer to start with django-allauth. Saves lots of time later.
[+] danpalmer|6 years ago|reply
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.

[+] pharaohgeek|6 years ago|reply
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.
[+] bobsoap|6 years ago|reply
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.
[+] sarakayakomzin|6 years ago|reply
I'm certainly going to trust an authentication service with a bad certificate.
[+] etherio|6 years ago|reply
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/

[+] anonymoushn|6 years ago|reply
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.
[+] tooop|6 years ago|reply
Laravel built in auth, Socialite for social logins.
[+] forgotmypw|6 years ago|reply
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.

[+] polishdude20|6 years ago|reply
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?
[+] jchw|6 years ago|reply
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.)

[+] vbsteven|6 years ago|reply
Spring Security for the logic and password storage. I usually build my own pages for password resets and logins