Account Security Updates

Alongside introducing new security features like Two-Factor Authentication (2FA) and integration with, we also take a quick look into the inner workings of Two-Factor Authentication.

Have you wanted to throw away your expensive internet bill and use your neighbor's insecure wifi? Was the only thing holding you back the Honeybadger single-factor auth flow? Well, have I got news for you.

Announcing: Two Factor Authentication (2FA)

All kidding aside, we take security very seriously. We are thrilled to be able to provide an important tool to help keep our users and their data more secure.

I figure I could just explain how to enable 2FA, but what's the fun in that? How about we take a light-hearted glimpse into the wild world of cryptography and figure out how 2FA works.

If fun's not your thing, you can totally go straight to How to enable, my feelings won't be hurt.

⚠️ Warning: Some theory below

Many 2FA implementations are built upon an algorithm called Time-Based One-Time Password (TOTP). Rolls right off the tongue.


Yes, the beauty in this method is that you are not transmitting the same "password" every time you log in. Using an authenticator application, a one-time "password" is generated and remains valid for a short duration (usually 30 seconds), which greatly dilutes the effectiveness of a malcolm-in-the-middle attack.

Although there are some complicated bits, the overall implementation is relatively simple.

The Secret

A key point to understand about TOTP is that the server (verifier) and the authenticator (prover) must have a shared secret. This is the real "password", however it's only transmitted once (so I guess this is one-time as well)!

The recommended way to consume the secret is via QR code. When you scan the QR code into your smartphone, the secret is encoded within a standard URI that looks something like this:


There are a few benefits to providing a QR code (as opposed to exposing the plaintext secret):

  1. Who has time to type in a 32 character code?
  2. Your authenticator app can provide helpful labels for your one-time password (referencing the email and issuer in the URI). This is especially useful when you use 2FA on multiple services.
  3. Finally a good reason to use a QR code!

There are some additional (mostly ignored) parameters for the otpauth scheme, which you can view here.

MAC and Me

Once the secrets have been agreed upon 🤝, you will be asked (at some point) to provide a One-Time Password. This is where things get real.

TOTP is built on top of another algorithm called HMAC-Based One-Time Password (HOTP), which itself is based on Hash-based Message Authentication Code (HMAC). It's all one big crypto onion.

TOTP & HOTP are basically variations on what message gets hashed. HMAC is really where the magic happens. HMAC produces a digest, which is the output of running some value through a hashing algorithm. Let's see it in action with some ruby code:

OpenSSL::HMAC.digest("SHA1", "my-secret-key", "the-earth-is-flat")
=> "R\xABp\xCB\xEC\xFEJ\r#\x02\xC8\xAB\x96\xB68\v\xDA0\xD7z"

Wow, look at that binary string! That's our Message Authentication Code (MAC).

We chose SHA1 as our hashing function (as does our implementation of TOTP). There are many other functions to choose from, each with their own security and performance implications. What's radical about a hashing algorithm is that for any input, we will get the same output, every time! It will also produce a vastly different and unique output from any subtle input changes (ahem, depending on the hashing function, but don't worry we are not terribly concerned with collisions here).

Okay, so it's called a Message Authentication Code because it can be used to prove that a received message is authentic. If you and I know the secret (my-secret-key), I can send you the message the-earth-is-flat along with the MAC. All you need to do is run the exact same digest function, with the same inputs, and if the MACs match up, you have authenticated the message! You know it wasn't tampered with and only could have come from me!



So let's bring this back to TOTP. It's time to talk about time. You see, with TOTP, instead of digesting a preposterous message like the-earth-is-flat, we instead use a time step count (converted to a string) as the input. If you open your authenticator app, and watch when the codes get switched, you might notice a pattern. That's right, say it with me: "They switch on the minute and the half minute", very good.

This makes calculating the message a little simpler. In this case we use the rounded down count of 30 seconds (the time step) since the beginning of time (well, unix time). So, in ruby again: / 30
=> 51772900

Ah hah! Thats our Message.

So in our Authenticator app, we use our trusty digest function to get a new HMAC:

hmac = OpenSSL::HMAC.digest("SHA1", "avwe8aw71j2boib23jkbjk32", "51772900")
=> "H\x7F\xC1\xACL\xDA\xDB\xE7DQ\x91kE\x1C\xE3,c\nH\xA0"
=> "332204"

The last step is to get the number code from this binary string. Since there is some bit manipulation required, I am going to hide behind our anonymous get_otp_code function for now. If you want, you can read about how it works in the HOTP Spec.

When you submit the code to the server, it performs the exact same digest operation and compares the codes. When they match, you're in! Because we are working with time, latency is a factor. There are strategies to account for possible delays. Understanding that will be your homework, if you want.

That's the gist of how Time-Based One-Time Passwords work!! 🎉 Feel free to send me a thank you email after you use this info to be the life of your next dinner party!


While I think it's important to understand how these things work, it's strongly discouraged to roll-your-own anything crypto related. One of the great things about the Ruby / Rails ecosystem is that you can often find a gem (sometimes many) to solve your problem.

We use devise here at Honeybadger and there is a great devise plugin called two_factor_authentication. There are a few 2FA implementations to choose from, so here are some reasons we chose this one:

  • Simple setup (a migration, some config & initializers sprinkled about)
  • It allows for the One-Time code to be entered on its own page (after valid user/password)
  • Acceptable defaults, yet simple to override
  • It also has a max login attempts check, which is recommended by the spec

How to enable

Setup is simple: Navigate to the User Settings > Authentication page, select "Set Up Two Factor Authentication" and follow the directions to sync up the secret using Authy or Google Authenticator (or really any other TOTP app).

2FA Setup

That's it! Next time you login, we will prompt you for your authenticator code. Fill it in and go with complete and utter peace of mind. 🧘

2FA Login

Security and simplicity? Can it get any better?

One last thing: Pwned Password Check

I've got a quick one for all you proponents of weak passwords. We also integrated with the devise-pwned_password gem. From now on, when you perform any operation that requires the password, we check to make sure the proposed password is not prevalent within any known data breaches. If you are adding a new password, and it fails the check, we won't allow it.

If you aren't already, we highly recommend using a password manager (1Password ahem).

One of the more interesting bits of Pwned Password is how your password stays secure even while checking against a database from a 3rd party service. It's called k-Anonymity and you can get an overview about it here.

Well, that's all we have for now. Until next time! 👋

What to do next:
  1. Try Honeybadger for FREE
    Honeybadger helps you find and fix errors before your users can even report them. Get set up in minutes and check monitoring off your to-do list.
    Start free trial
    Easy 5-minute setup — No credit card required
  2. Get the Honeybadger newsletter
    Each month we share news, best practices, and stories from the DevOps & monitoring community—exclusively for developers like you.
    author photo

    Kevin Webster

    Kevin is the freshest Honeybadger (both in time and breakdancing abilities). Kevin has been building things with software since his dad brought home the family IBM 386. He fancies himself a bit of a programming polyglot. When he's not compromising his ability to write Ruby by learning new languages, he enjoys hiking through the Oregon wilderness, hanging with his family, or watching cringeworthy b-list movies.

    More articles by Kevin Webster
    Stop wasting time manually checking logs for errors!

    Try the only application health monitoring tool that allows you to track application errors, uptime, and cron jobs in one simple platform.

    • Know when critical errors occur, and which customers are affected.
    • Respond instantly when your systems go down.
    • Improve the health of your systems over time.
    • Fix problems before your customers can report them!

    As developers ourselves, we hated wasting time tracking down errors—so we built the system we always wanted.

    Honeybadger tracks everything you need and nothing you don't, creating one simple solution to keep your application running and error free so you can do what you do best—release new code. Try it free and see for yourself.

    Start free trial
    Simple 5-minute setup — No credit card required

    Learn more

    "We've looked at a lot of error management systems. Honeybadger is head and shoulders above the rest and somehow gets better with every new release."
    — Michael Smith, Cofounder & CTO of YvesBlue

    Honeybadger is trusted by top companies like:

    “Everyone is in love with Honeybadger ... the UI is spot on.”
    Molly Struve, Sr. Site Reliability Engineer, Netflix
    Start free trial
    Are you using Sentry, Rollbar, Bugsnag, or Airbrake for your monitoring? Honeybadger includes error tracking with a whole suite of amazing monitoring tools — all for probably less than you're paying now. Discover why so many companies are switching to Honeybadger here.
    Start free trial