Skip to content
Insights · Engineering

Show the factor they enrolled

Name the factor on that account, show a sign-in without it refused, and show a different account's factor still works. A campus rate is not your log.

Scroll
EngineeringOct 20, 202615 min readBy Salman Naqvi, Founder & CEO
Show the factor they enrolled

A sign-in asked for a second factor. Tonight, three proofs, in a console you administer. Name the factor on that account: which kind, when it was enrolled, and whether it is the one the product will accept. Show a sign-in that does not present it refused, or write that the product cannot refuse a missing factor. Then show a different account, with its own factor, still able to sign in. If any of the three requires the person who built the login, you have not shown the factor. You have a settings toggle and a hope.

This is the authenticator bound to one account. It is not the sign-in event. Show the login they did not make is the row: who, when, accepted or refused, and the source field that is really there. A refused sign-in does not name the factor that account holds, and naming the factor does not prove which attempt just failed. It is not the session that attempt opened. End the session they still hold kills a session that already exists. Ending it does not unenroll the factor, and unenrolling the factor does not, by itself, prove the old session is dead. It is not the role. Name the role that account holds is what the account may do after it is in. A role of admin is not a second factor. It is not the text they accepted. Show the consent they gave is that text, the act, and the time. Agreeing to a purpose is not enrolling a device.

None of what follows is a rate for this product, and none of it is legal advice. The counts below are two universities' Duo logs from 2018 and 2019, plus a standards publication's rules for verifiers. A campus deployment is not your customer base. A publication written for agencies that document a system security plan is not a finding that those rules bind a Virginia company. They do tell you the shape of a proof a founder can perform this week, which is a product question.

Joshua Reynolds, Nikita Samarin, Joseph Barnes, Taylor Judd, Joshua Mason, Michael Bailey, and Serge Egelman measured Duo at the University of Illinois at Urbana-Champaign and the University of California, Berkeley, and reported it at USENIX Security 2020. The logs are not one pile. UCB provided 32,366,721 anonymized 2FA log events from 27 June 2018 to 26 June 2019. UIUC shared a log of 6,467,262 2FA events from 13 June 2018 to 31 March 2019, and, as a different object, 1,985,601 telephony charge records. A charge record is not a ceremony. Do not add 1,985,601 to 6,467,262 and call the sum the login log. They also shared 17,085 2FA-related support tickets, and student or employee status for 38,536 of 77,931 UIUC users. 38,536 is not 77,931. A year of logs is not nine months (Reynolds et al., Empirical Measurement of Systemic 2FA Usability).

What they kept is smaller than what they were handed, and the paper prints both. They removed duplicate records, 238,338 from UIUC and 156,728 from UCB, and 2,108 malformed logs from UCB. They removed one UCB user their security team identified as a runaway testing script, responsible for 913,180 failed login events. The usable set they print is 37,523,629 events, 6,228,924 from UIUC and 31,294,705 from UCB. 6,228,924 is not 6,467,262. 31,294,705 is not 32,366,721. 37,523,629 is not "over 35 million," if you meet that phrase in a summary of the paper. The phrase and the usable total are different sentences. A script's 913,180 failures are not a customer's failure rate. Public university Duo in that window is not this product's log.

The time in their Table 1 is an estimate, and it is not the log's clock. They mapped ceremonies onto four types and applied median seconds measured by other people, on other interfaces. App push, 11.8 seconds. Phone call, 20.8. SMS or code, 18.4. U2F or YubiKey, 9.7. 11.8 is not 20.8. 9.7 is not 18.4. The counts beside those seconds are UIUC 2,884,875 push, 865,559 call, 1,688,161 SMS, 204,489 U2F, and UCB 5,967,112, 1,272,396, 1,970,448, and 46,427. The table's total row does not print a count. It prints hours: 29,525.5 at UIUC and 37,414.1 at UCB, and 22.7 minutes and 15.6 minutes per user-year. 22.7 is not 15.6. 9.1 minutes of push per UIUC user-year is not 0.5 minutes of U2F. Do not multiply a count by 11.8 and replace the hours cell. The paper says the mapping is imperfect, because the dataset labeled 16 distinct second factors and the table has four rows. 16 is not 4. The introduction's "about ten minutes per year" is not 22.7, and it is not 15.6. A different sentence says organizations should expect between 10 minutes and an hour, and that only about 10% of people spend more than an hour. 10 minutes is not 10%. An hour is not 22.7 minutes.

An average workday, in their prose, sees about 20K of 78K users at UIUC and about 40K of 105K at UCB. 20K is not 40K. 78K is not the 77,931 in the status file. About 35% of UIUC users and about 20% of UCB users log in less than monthly. 35 is not 20. UIUC had no device remembrance. UCB had an optional 30-day remembrance. 70% of UCB logins were remembered, which they write as 21.1M of 30.0M. 30.0M is not 31,294,705. They estimate that policy saved about 80K person-hours a year. 80K hours is not 21.1M logins. A hypothetical they price at $20 an hour, for an organization of 100K users, lands between about $400K and $600K. 100K is not 105K. $400K is not $600K. Neither is UCB's payroll. They also say a 30-day window is not a 30 times reduction, and that UCB users spent about 32% less time than UIUC users, not 70% less. 32 is not 70. The hidden factor they name is the session timeout: UIUC web services time out after 8 to 12 hours, and UCB after 15 to 30 minutes. 8 hours is not 15 minutes.

Other campuses are citations inside this paper, not rows in this log. Colnago and colleagues, as Reynolds reports them, had an overall remembrance rate of 49%, with 55% of users taking advantage of the feature, and qualitative shares of 20% unaware, 10% unable, and 12% choosing to avoid it. 49 is not 70. 55 is not 80, which is the share of UCB users Reynolds says benefited. 20 is not 10 is not 12. Abbott and Patil, as cited here, are about 20% remembrance at a different university. 20 is not 49. Doerfler and colleagues' "over 90%" is a success rate of a Google challenge system against known attackers, and that system optionally uses 2FA among other signals. Over 90% is not a Duo error rate. Strouble's about 14 work-years, from 2009, is lost cards at the U.S. Air Force. 14 work-years is not 80K person-hours, and it is not your help desk. A 2019 survey of over 1,000 executives, eight in ten organizations using 2FA and 96% expecting to expand it, is reference 1 in the introduction. Eight in ten is not 96. 1,000 executives are not 77,931 users.

Failure is a second cut of the same logs, and it is not the time estimate. They observed that more than one in twenty 2FA ceremonies did not end successfully, and the logs were created only after the username and password had already succeeded. More than one in twenty is their phrase. Do not print it as 5%. The leading causes in the prose are users canceling or abandoning, then invalid passcodes. Table 2 prints an error total of 487,676 at UIUC and 1,159,079 at UCB, each marked 100%. Those totals are counts of errors, not counts of ceremonies. 487,676 is not 6,228,924. 1,159,079 is not 31,294,705. On the UCB column, user canceled is 558,562 (48.19%), no response is 278,202 (24.00%), invalid passcode is 187,777 (16.20%), anomalous push is 77,176 (6.66%), and deny-unenrolled-user is 14,546 (1.25%). 48.19 is not 24.00. 6.66 is not 1.25. Anomalous push is 0 at UIUC because only UCB turned on the block of duplicate pushes. Deny-unenrolled is the error when someone is forced into 2FA and has not set up a factor. 14,546 is a count of that error at UCB. It is not a count of people who enrolled. User-marked fraud is 165 at UCB, 0.01%. 165 is not 558,562. 0.01 is not 48.19.

Who sees the errors is not the same cut as how many errors there were. At UIUC, 60% of users experienced 1 to 100 errors and 40% saw none. 60 and 40 are that sentence. At UCB, 75% experienced between 1 and 100 errors and 20% saw none. 75 and 20 do not become 100 in the paper, so do not add them and then invent the missing share. 45% of UIUC users and 60% of UCB users saw error rates under 20%. More than one in seven users at both universities experienced errors more than 20% of the time. The figure caption's phrase is fewer than 20% of users saw errors more than 20% of the time. More than one in seven is not the caption's fewer than 20%, and neither is 45. Recovery time, from a failure to the next success, averages 10 to 100 seconds. The median is split between that bin and 10,000 to 100,000 seconds, which they gloss as about 3 to 28 hours. 10 seconds is not 10,000 seconds. Hours pass before 40% of users next successfully log in, by their individual medians. The worst 20% are not retried until at least the next day. 40 is not 20.

The help desk is a third object, a sample of a sample. Of 17,085 tickets, 9,724 were automated signup alerts and 640 were vacation replies to mass mail. That left 6,721 user-caused tickets, 6,169 at the general help desk and 552 escalated to security. 9,724 is not 6,721. 552 is not 6,169. They designed a codebook on random subsets of 200, 13 codes, then applied it to a different random subset of 500. 500 is not 6,721, and 200 is not 500. Two coders, codes not mutually exclusive, Kupper-Hafner .79, which they call substantial agreement, and which they chose because Cohen's kappa assumes exclusive codes. Setup and enrollment is 172 of that 500, 34.40%, with a 99% confidence interval of 5.48 points. 34.40 is not 5.48. 172 is not 6,721. Update-a-device is 69, 13.80%, interval 3.98. Phone or SMS is 51, 10.20%, interval 3.49. The app is 26, 5.20%. A hardware token is 18, 3.60%. Asking to stop 2FA is 10, 2.00%. Positive opinion is 0. 172 is not 69 is not 51. Because the codes can overlap, do not add the percents to 100 and call the remainder a missing category.

The publication that names the kinds of factor, as distinct from a campus log, is a different document from the session section already quoted on end the session they still hold. NIST Special Publication 800-63B-4, the authenticators section, says that with two exceptions the technical requirements for each authenticator type are the same regardless of the authenticator assurance level. The exceptions are reauthentication, and phishing resistance at AAL3. You are not a federal agency, and nothing here finds that an assurance level applies to your company. What the section is for, on this page, is the difference between kinds. A password is something you know. Used alone, verifiers shall require a minimum of 15 characters. Used only as part of a multi-factor process, the minimum they shall require is 8. 15 is not 8. They shall not impose other composition rules, and they shall not require periodic changes. A forced change after evidence of compromise is a different sentence from a calendar rotation. A look-up secret, the recovery-code shape, is something you have, shall be at least 6 decimal digits or equivalent, shall be used successfully only once, and is not phishing-resistant. 6 is not 8. A password is not phishing-resistant either. An activation secret is a local unlock for a multi-factor authenticator. It is not sent to the verifier. An out-of-band secret is a short-lived secret the verifier generates and sends to a device. A push, a phone call, and an SMS are three rows in the university table. They are not three names in this section, and this page will not pretend they are (NIST, SP 800-63B-4, authenticators).

Two storage rules sit next to those lengths, and neither is an enrollment. The salt on a stored password shall be at least 32 bits. 32 bits is not 15 characters. Verifiers shall compare a new password to a blocklist of commonly used, expected, or compromised values, the entire secret, not a substring. A blocklist is not a second factor. Rate limiting failed attempts is not an enrolled device. Allowing a password manager to paste is not phishing resistance. The section says passwords are not phishing-resistant in its own sentence. A product that stores "MFA: on" and cannot name the kind has not met the proof on this page, whatever an assurance level would have required of an agency.

Do the three proofs on one real account, in the console that actually stores the factor. First, the binding. Copy the kind the product records, the time it was enrolled, and whether it is still the one a sign-in will accept. If the screen says only that a second step is enabled, write that the kind was not stored. Do not infer a hardware key because the marketing page mentions one. Second, the refusal. Attempt a sign-in that does not present that factor, and show the refusal, with the account unchanged. A banner that says the feature is on, with no refused attempt beside it, is a setting. If the product cannot refuse a missing factor, write that, and do not tell the customer the account is covered. Third, the other account. A different person, with their own factor, still signs in. If turning the feature on locked every account, you have a flag, not a binding. If the first account can still sign in with a password alone, the enrollment did not reach the verifier.

Three moves feel like the proof and are a second problem. Resetting the password, because the reset mail is the tool you already have, while the request was about the factor. Disabling the second step for the whole tenant, because the console has no per-account path, and then describing the outage as a recovery. Asking a model which factor the customer enrolled. The model will describe a plausible device. It will not open the row. A session you can end, while the factor remains enrolled for the next sign-in, is end the session they still hold. Ending the session does not unenroll the device. A role you can name, while the factor is still missing, is name the role that account holds. An admin with no factor is still an admin.

The path is ordinary when an admin can see one account's factor without opening the next account's mail as the way to prove it. Gigbase is a multi-tenant workspace with authentication, subscription plans, and role-based access for agencies, admins, and team members, plus a dedicated admin dashboard. The shape that matters here is an admin, in an account you administer, who can open one person's sign-in settings. That case is not a factor ledger. Nothing in the description is a headcount, a duration, or a result figure. If the only control on the admin screen toggles a tenant-wide flag, you do not have this proof. You have a kill switch.

There is a version of this afternoon where hiring the path is the wrong purchase. Nobody can enroll, because the product does not have accounts yet. You have no product. You are still choosing who will build, and the document in front of you is a term sheet. The criteria for that choice sit on the page written for a top saas development company. That page is criteria. It does not rank anyone, including us. The only fact in the room is a share from a paper. More than one in twenty is not your log, and 48.19% is not your log. A customer has already seen another customer's data. Naming a factor does not close a leak. Or you wanted a lawyer to say whether a publication applies. Hire the lawyer.

When the account is real and the console cannot name the factor, the missing object is specific. An admin action, in an account you administer, that shows one factor, refuses a sign-in that does not present it, and leaves a different account able to sign in with its own. A startup software development company that expects this will have put that action next to the rest of account admin, before a stranger's success is the way you discover the vendor owns the enrollment. One that needs a call in order for you to see which factor is bound is telling you who holds the front door. If the first slice is a fixed capability, an AI integration sprint is the shape where the acceptance sentence can include the three proofs. If you do not yet know which system stores authenticators, a two-week AI readiness assessment maps the systems. The findings are yours. They are not a promise that a guideline applies, and they are not a rate.

A migration a deploy applied, and the tokens one model response billed, are different objects: name the migration the deploy applied and name the tokens the response billed. Do not record either on this page. A schema version is not an authenticator. A token count is not a second factor.

Before you tell them the account has a second step, do the three proofs and write the kind. Name the factor, or write that the kind was not stored. Show a sign-in without it refused. Show a different account's factor still working. Do not reset the password to avoid the row, and do not ask a model what they enrolled. A campus can tell you how often a ceremony fails after the password already succeeded. The binding is the page you can defend.

Find this useful? Tell Google to show you more of it.

Let's put AI to work in your business.

A 30-minute call. You bring the workflow or the roadmap — we'll tell you what's feasible, what it costs, and what we'd build first.

Book a call→