Passwords are Obsolete — How to Secure Your App and Protect Your Users

Eric Elliott
Apr 1, 2020 · 7 min read
Image for post
Image for post

I’ve said this part before, so if you read the previous article, skip to “How to Implement Passwordless Authentication”, below. I’m posting the introduction again for those of us who are too lazy to click a link.

Managing user authentication and authorization is a very serious responsibility, and getting it wrong can cost a lot more than unauthorized access to your app. It can also compromise user privacy or lead to financial damage or identity theft for your users. Unless you are a huge company with a huge security team, you don’t want that kind of responsibility or liability for your app.

Most apps today are built with username and password authentication, and once a user is signed in, that user session can do anything it wants to do, without revalidating the user’s intention.

That security model is broken for a number of reasons:

Passwords are obsolete. If you have any doubt about that, head over to HaveIBeenPwned and plunk in your email address. Sensitive data has been stolen in many high profile data breaches impacting companies like Dropbox, Adobe, Disqus, Kickstarter, LinkedIn, Tumblr, and many, many more. If there’s a database with passwords in it, it’s only a matter of time before it gets stolen.

Hashing passwords won’t save you or your users. Once a database of passwords has been stolen, hackers aim immense distributed computing power at those password databases. They use parallel GPUs or giant botnets with hundreds of thousands of nodes to try hundreds of billions of password combinations per second in hopes of recovering plaintext username/password pairs.

If an attacker can discover a password that hashes to the same hash as the one stored in your database, they’ll take that combination and try it on things like bank account websites. In many cases, even a salted, hashed password database will leak another valid username/password pair every minute or so. That’s about half a million leaked passwords per year — and that rate is doubling every few years. I wrote about this topic in 2013. The bad guys are now hashing passwords more than 10 times faster than they were then.

User Sessions Get Hijacked. User sessions are commonly hijacked after authentication, allowing attackers to exploit that user’s application resources. To prevent that, you’d need to re-authenticate the user with every request, and in the land of usernames and passwords, that would create an awkward user experience.

Upgrading Authentication

A hijacker would need the ability to sign on behalf of the user, but they can’t do that without access to the user’s private key, which is protected by hardware-level security. Using Hardware Security Modules (HSMs), we can protect private keys from exposure to the internet. Instead of sending the private key over the network, we send the messages which need signing to the private key in the HSM. The user authorizes the signature, and the signed request gets authenticated and processed. If the signature is invalid, the request gets rejected.

Additionally, those key pairs can encrypt and decrypt user data so that only the user who owns the data can read it. If an app developer chooses to let users encrypt their data, even the application can’t decrypt the data without the user’s permission. With this security model, we can put users in control of their private information.

Passwordless Authentication with Magic Links

Password-only security is obsolete and dangerously insecure. Magic links eliminate the headaches of lost or stolen passwords and protect app users.

But you don’t want to try to roll your own public/private key-based magic links, or you’ll move from the frying pan into the fire. If you think keeping passwords safe is hard, don’t even think of trying to manage private keys, which, if stolen, could potentially grant access to an Ethereum wallet loaded with valuable money, collectibles, memberships, etc.

Lots of apps and wallets push that responsibility on end users. That’s like putting the key to a bank vault in somebody’s mobile phone. What if the phone gets lost, stolen, or upgraded?

In my opinion, the best way forward is to delegate key management to people who specialize in key management. One such service has launched today. It’s called Magic. It’s made by Magic Labs, a cybersecurity company who have assembled experts from companies like Docker, Apple, Google, Amazon, Yelp, Uber, Accenture, and TD Bank.

Their security model stores your user’s private keys in HSMs. An HSM is a bit like a hardware locker for private keys. The keys are protected by hardware and never leave the hardware. Keys are never exposed to the internet. Instead, messages that need to be signed by those keys are delivered to and signed on the dedicated hardware.

Imagine a bank safety deposit box. What’s inside the box is a key that can be used to authorize signatures and transactions. When you rent a safety deposit box from a bank, the contents of the box belong to you. The bank just keeps it safe for you. Using Magic is a bit like giving each of your users a dedicated safety deposit box for their key. Magic can’t access the keys, and neither can you. Keys are always in the user’s control but hosted in the cloud, so users don’t have to worry about losing them.

In other words, Magic is a non-custodial, hardware-secured key management system. It features best-in-class security and SOC 2 compliance. But the best part is that your users don’t need to know what any of that means. All they need to know how to do is enter their email and click a button.

Adding Magic to Your App

Before you dive into the source code, you’ll need to understand some foundational concepts:

This file requires a few helpers. The first is a usePromise hook that holds onto a persistent reference to the magicReady promise. I promise, you want your magic to be ready before you try to use it, or your spell will backfire.

And the localStorage drop-in replacement for useState:

Last, some miscellaneous tools:

With the hook finished, our next step was to integrate the hook with our existing app. We use Redux and try to isolate logic, I/O, and state process as much as we can from our presentation components. This Higher Order Component (HOC) lets us compose our magic link logic into every page in our app in one place.

Here’s the HOC we use to compose cross-cutting concerns into every page that needs them:

Since these HOCs are so easy to create and maintain, you can create custom HOCs that omit features that aren’t needed for a particular page or add features that aren’t needed for every page. Now we can sign in or out anywhere on our site!


  • Password-only security is obsolete and dangerously insecure. Don’t use it.
  • Public key cryptography gives us public/private key pairs we can use to enhance user safety significantly.
  • Key management is hard, both for app developers and end users.
  • App developers should delegate key management to security specialists.
  • Hardware Security Modules (HSMs) can securely store user keys in the cloud, without forcing users to know what any of this means.
  • Magic links eliminate the headaches of lost or stolen passwords and protect app users.
  • Magic provides best-in-class, non-custodial, delegated key management for your users. They’re paving the way for a more secure future for apps and users. They have set a new bar for user authentication security and user experience, and they’re currently the only authentication solution I recommend for developers of new applications.
  • Magic unlocks Ethereum. With Magic’s Ethereum-based public/private key pairs, we can use them to transact with Ethereum and EVM-compatible protocols and tokens, unlocking lots of capabilities that were never possible before blockchain technology was invented.

Note: You don’t have to build an Ethereum dapp to benefit from Magic’s passwordless authentication and improved user security. You can improve any app with Magic.

Next Steps

Take a test drive of the authentication flow on Our existing users have GitHub authenticated accounts that need to be linked the first time you sign in, but once you’ve linked your GitHub account once, you won’t need to do it again. Sign out and sign back in to see the Magic-only flow.

The GitHub flow requires shields to be down in Brave because of how the authentication flow is delegated. The new Magic authentication flow works like a charm with shields up. Magic’s simplified flow has lots of hidden benefits.

While you’re checking out, browse the premium content, and explore some of our online JavaScript lessons.

Make some magic.

Eric Elliott is a tech product and platform advisor, author of “Composing Software”, cofounder of and, and dev team mentor. He has contributed to software experiences for Adobe Systems, Zumba Fitness, The Wall Street Journal, ESPN, BBC, and top recording artists including Usher, Frank Ocean, Metallica, and many more.

He enjoys a remote lifestyle with the most beautiful woman in the world.

JavaScript Scene

JavaScript, software leadership, software development, and…

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store