Skip to content

Conversation

@Elchi3
Copy link
Member

@Elchi3 Elchi3 commented Oct 30, 2025

Description

Adds new documentation describing OTP-based authentication. The article discusses three ways: email, SMS, and TOTP (authenticator apps)

Motivation

Developing a series of guides for implementing authentication covering various techniques, including passwords, one-time passwords, federated identity, and web authentication.

Additional details

  • Overall OTP is presented as a second factor or when confirming user intentions (e.g., payments) and not as a general purpose authentication method.
  • TOTP is presented as the most secure delivery method of one-time passwords.
  • Several flaws with email and SMS-based deliveries are discussed

Related issues and pull requests

None.

@Elchi3 Elchi3 requested a review from wbamberg October 30, 2025 16:17
@Elchi3 Elchi3 requested a review from a team as a code owner October 30, 2025 16:17
@github-actions github-actions bot added Content:Security Security docs size/m [PR only] 51-500 LoC changed labels Oct 30, 2025
@github-actions
Copy link
Contributor

github-actions bot commented Oct 30, 2025

Preview URLs

Flaws (4)

Note! 1 document with no flaws that don't need to be listed. 🎉

URL: /en-US/docs/Web/Security/Authentication
Title: Authentication
Flaw count: 4

  • broken_links:
    • Can't resolve /en-US/docs/Web/Security/Authentication/Federated_identity
    • Can't resolve /en-US/docs/Web/Security/Authentication/Passkeys
    • Can't resolve /en-US/docs/Web/Security/Authentication/Session_management
  • macros:
    • Can't resolve /en-US/docs/Glossary/JWT
External URLs (12)

URL: /en-US/docs/Web/Security/Authentication/OTP
Title: One-time passwords (OTP)

(comment last updated: 2025-11-19 20:01:10)

@sideshowbarker sideshowbarker removed the request for review from a team October 31, 2025 06:02
Copy link
Collaborator

@wbamberg wbamberg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't reviewed the whole thing but I did review the TOTP section, which seems like the most important one. I will take a look at the rest tomorrow.


In Chromium-based browsers, the [WebOTP API](/en-US/docs/Web/API/WebOTP_API) is available additionally as an extension of the [Credential Management API](/en-US/docs/Web/API/Credential_Management_API). Unless you need programmatic access to the {{domxref("OTPCredential")}}, you don't need to use this API. Formatting the SMS in the standardized format and using `autocomplete=one-time-code` should be enough for autocomplete to work across browsers.

## TOTP flows (authenticator app)
Copy link
Collaborator

@wbamberg wbamberg Nov 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is something @hamishwillee always says, which is that we should put the recommended option first (i.e. this one), and the others as alternates/informational. Up to you, but something to consider, and I can see the logic in it.

Comment on lines 78 to 83
In order for TOTP to work, the following steps will need to happen:

1. The website generates and shares a secret seed (which can be made accessible using a QR code).
2. The user generates a TOTP token based on the secret seed and the current time (authenticator apps can help with this).
3. The user enters the TOTP token on the website to authenticate.

Copy link
Collaborator

@wbamberg wbamberg Nov 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this looks like two separate flows, right? Registration and sign-in? I think it might be worth making this explicit, and maybe using the two flows to structure this section as well.

I also think it's worth really spelling out the flows, like:

  • the user installs an authenticator app
  • the user visits the website and asks to sign up
  • the website ....

...even including stuff that might seem obvious.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added in 5130252.


### TOTP secret sharing

To setup TOTP, a website needs to share a secret key with the user. A TOTP secret key is a randomly generated [Base32](https://en.wikipedia.org/wiki/Base32) encoded seed. For example, the following command generates a 32-character Base32 random string::
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
To setup TOTP, a website needs to share a secret key with the user. A TOTP secret key is a randomly generated [Base32](https://en.wikipedia.org/wiki/Base32) encoded seed. For example, the following command generates a 32-character Base32 random string::
To set up TOTP, a website needs to share a secret key with the user. A TOTP secret key is a randomly generated [Base32](https://en.wikipedia.org/wiki/Base32) encoded value. For example, the following command generates a 32-character Base32 random string::

...but also I think we need more context than "the following command" - I guess it is a bash command, but you don't say that. And what is it actually doing? I don't want to paste random bash commands into my website code without some idea of what the bits of them are.

And talking about flows, it's better to always say who needs to do what.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I took out the Bash snippet, mostly because I expect people will use a library for working with TOTP, and we should probably encourage that.


To setup TOTP, a website needs to share a secret key with the user. A TOTP secret key is a randomly generated [Base32](https://en.wikipedia.org/wiki/Base32) encoded seed. For example, the following command generates a 32-character Base32 random string::

```plain
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
```plain
```bash

?

LC_ALL=C tr -dc 'A-Z2-7' </dev/urandom | head -c 32; echo
```

This secret can be provided to the user in the form of a QR code, however, if you want to avoid QR codes, all you really need is an URI in the `otpauth` URI format as defined in this [IETF draft](https://www.ietf.org/archive/id/draft-linuxgemini-otpauth-uri-00.html).
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't fully understand this, and again I think spelling it out is helpful. For example:

  • the user asks to create an account
  • the website generates a secret, and then generates a QR code from that secret (by doing XYZ)
  • the user ...(does something with the QR code)

I don't really understand what the website does with this otpauth URI. How does this enable sharing the secret value.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tried to clarify this in 5130252.

otpauth://totp/ExampleWebsite?secret=MQCHJLS6FJXT2BGQJ6QMG3WCAVUC2HJZ
```

The URI is an URL query string and it has a few parameters (support in authenticator applications may vary). The most interesting parameters are:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"The URI is an URL query string" seems wrong?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-> has

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated in 5130252.


With the shared secret key and the current time as inputs, you can now produce a unique, time-based code. This usually gets done using a cryptographic algorithm, typically `HMAC-SHA1` or `HMAC-SHA256`.

Several apps, like [Ente Auth](https://ente.io/auth/), [2FAS](https://2fas.com) or [Microsoft Authenticator](https://www.microsoft.com/en-US/security/mobile-authenticator-app), allow you to store secrets you've received from various websites or services. You don't necessarily need to use an authenticator app, but if you do, choose one that is trustworthy and secure. For example, there are several TOTP token generator tools online, but you might not know what they are doing with your shared secrets. If you use online services to quickly generate TOTP tokens, at least consider to not provide details for which service the shared secret is intended for.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"you" here seems to refer to the user, not the web developer. Which I think is wrong: we should consistently address the web developer.

What are the security implications of the shared secret? What if an attacker gets access to the secret? In the preamble, we say "Unlike a password, there's no long-term secret to remember or to store securely" (my words actually!) Is this incorrect?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Relatedly it would be good to talk about attacks on (T)OTP. Earlier on we mention phishing but it's kind of implied that this is only a concern for certain versions of email OTP, but I think all OTP variants are vulnerable to phishing: https://developer.mozilla.org/en-US/docs/Web/Security/Attacks/Phishing#multi-factor_authentication.

Somewhere too we should talk about pros and cons. One con I can think of is that users have to install an authenticator app, which is extra friction and another component that we have to trust (I guess?).

Copy link
Member Author

@Elchi3 Elchi3 Nov 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a section about Weaknesses:

Vulnerabilities
Interception: SMS (worst) and email
Phishing: SMS, email, TOTP
Shared secret vulnerability with TOTP tokens (like a database compromise with passwords, also going on on the client side in the authenticator app)

User experience
SMS: privacy concerns, need to have a phone
email: latency
TOTP: need to install an authenticator app and make sure it is secured

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added in 5130252.


## OTP recommendations

OTP, and in particular TOTP, can be useful as an additional (2FA) authentication method and for confirming user intentions, for example when making a payment. For general authentication purposes, much stronger mechanism, such as [WebAuthn](/en-US/docs/Web/API/Web_Authentication_API), should be considered. If you implement one-time passwords, consider the following recommendations:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"much stronger mechanism" - why is (T)OTP weak compared with passkeys?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added more specific guidance (specifically, phishing resistance) in 5130252.

- Set short expiry (ideally ≤5 minutes; 30–120 seconds for stronger protection).
- Invalidate OTPs after use.
- If you use email:
- Ensure users receive the OTP emails quickly.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How can a website do this?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Say that this is a weakness and not say it would be a good practice, because there isn't really something you can do. Take this out

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 5130252.

Comment on lines 142 to 145
- If you use SMS:
- Format messages in origin-bound standard format.
- Use `autocomplete=one-time-code`.
- Monitor and mitigate SIM swap and interception risks.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if it's worth being stronger here and just straight out un-recommending SMS, rather than giving good practice recs.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 5130252.


## TOTP flows (authenticator app)

The time-based one-time password (TOTP) algorithm is specified in [RFC 6238](https://www.rfc-editor.org/rfc/rfc6238). It creates one-time codes that are 6 digits long and which are only valid for a limited amount of time (usually 30 seconds). It is similar to other OTP systems but implements time-based validity and automatic invalidation by design.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also and maybe more importantly: with TOTP the code is not sent by the server. Any time the code is sent from the server to the user, there is the possibility that it could be intercepted. So in this sense TOTP is intrinsically more secure.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noted in "Weaknesses" in 5130252.

@wbamberg
Copy link
Collaborator

@Elchi3 , I've made some edits to this article, if you would like a look. Hope I have not done too much violence to it. I guess you can't technically approve your own PR :) but at least let me know if you are happy.

Copy link
Member Author

@Elchi3 Elchi3 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great, Will! I think this can be merged. Minor thoughts only.


## TOTP

With time-based one-time passwords, the website does not send the sign-in code to the user. Instead, the website and the user are able to generate the same code independently of each other, based on the current time and a shared secret. To generate the code, the user must install an app on their device: this is called an _authenticator app_.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if we want to mention it, but the authenticator app is not a must. If you have the algorithm at hand, you can calculate it however you like (and you are responsible for how you store the shared secret). In my previous version I warned about this and said that (trusted) authenticator apps are better than say random online services .

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't say this because I'm not sure how relevant it is, especially for web developers, who are the audience here.

Even for end users, I'm not sure how relevant it is - yes, you don't need an app, but that's true of lots of things, and it seems perverse to not use an app when it's much easier and probably more secure to use one. Is this a realistic use case that we want to highlight?

And for web developers, their need is (perhaps) to communicate to their users how to use TOTP, which might include something like "you'll need to install an app if you haven't already, you can get one from X or Y or Z". Is it helpful for them to say "BTW you don't need an app, but it's probably less secure if you don't"? Isn't it better for them (and us) just not to acknowledge this option, and keep it simple for users?

I suppose one thing about TOTP is that security of the secret on the client is a risk that the server can't control (similar to whether a user looks after their passwords) and it might be worth mentioning this (as an extension to the general concern about securing the shared secret). But I'm not sure this is worth it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I agree, let's not get into this then.

@Elchi3
Copy link
Member Author

Elchi3 commented Nov 20, 2025

Thank you so much, Will! This is ready to go from my side. Can't merge my own PR, but if you want to r+ and merge, I would be more than happy. It was great talking this one through in person at W3C TPAC in Kobe with you!!

@wbamberg wbamberg merged commit 64e7d62 into mdn:main Nov 20, 2025
8 checks passed
@wbamberg
Copy link
Collaborator

It was great talking this one through in person at W3C TPAC in Kobe with you!!

Likewise!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Content:Security Security docs size/m [PR only] 51-500 LoC changed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants