Es ist üblich, Nutzer aufzufordern, ein Einmalpasswort (OTP) anzugeben, um ihre Identität per SMS zu bestätigen. Einige Anwendungsfälle für SMS-OTP:
- 2‑Faktor-Authentifizierung Zusätzlich zu Nutzername und Passwort kann das per SMS gesendete Einmalpasswort als starkes Signal dafür verwendet werden, dass das Konto der Person gehört, die das Einmalpasswort per SMS erhalten hat.
- Bestätigung der Telefonnummer Bei einigen Diensten wird eine Telefonnummer als primäre Kennung des Nutzers verwendet. Bei solchen Diensten können Nutzer ihre Telefonnummer und den per SMS erhaltenen Einmalcode eingeben, um ihre Identität zu bestätigen. Manchmal wird sie mit einer PIN kombiniert, um eine 2‑Faktor-Authentifizierung zu bilden.
- Kontowiederherstellung: Wenn ein Nutzer den Zugriff auf sein Konto verliert, muss es eine Möglichkeit geben, das Konto wiederherzustellen. Das Senden einer E-Mail an die registrierte E-Mail-Adresse oder eines SMS-Einmalpassworts an die Telefonnummer sind gängige Methoden zur Kontowiederherstellung.
- Zahlungsbestätigung: In Zahlungssystemen fordern einige Banken oder Kreditkartenaussteller aus Sicherheitsgründen eine zusätzliche Authentifizierung des Zahlungspflichtigen an. Dazu wird häufig ein SMS-Einmalpasswort verwendet.
Im Folgenden finden Sie Best Practices zum Erstellen von SMS-OTP-Formularen für diese Anwendungsfälle.
Checkliste
So sorgen Sie für eine optimale Nutzererfahrung mit SMS-Einmalpasswörtern:
- Verwenden Sie das
<input>
-Element mit:type="text"
inputmode="numeric"
autocomplete="one-time-code"
- Verwenden Sie
@BOUND_DOMAIN #OTP_CODE
als letzte Zeile der SMS mit dem Einmalpasswort. - Verwenden Sie die WebOTP API.
<input>
-Element verwenden
Ein Formular mit einem <input>
-Element ist die wichtigste Best Practice, die Sie befolgen können, da es in allen Browsern funktioniert. Auch wenn andere Vorschläge aus diesem Beitrag in einem bestimmten Browser nicht funktionieren, kann der Nutzer das Einmalkennwort weiterhin manuell eingeben und senden.
<form action="/verify-otp" method="POST">
<input type="text"
inputmode="numeric"
autocomplete="one-time-code"
pattern="\d{6}"
required>
</form>
Hier sind einige Ideen, wie Sie dafür sorgen können, dass ein Eingabefeld die Browserfunktionen optimal nutzt.
type="text"
Da Einmalpasswörter in der Regel fünf- oder sechsstellige Zahlen sind, kann es intuitiv erscheinen, type="number"
für ein Eingabefeld zu verwenden, da dadurch die mobile Tastatur auf Zahlen beschränkt wird. Das wird nicht empfohlen, da der Browser erwartet, dass ein Eingabefeld eine zählbare Zahl und nicht eine Folge mehrerer Zahlen ist. Das kann zu unerwartetem Verhalten führen. Bei Verwendung von type="number"
werden neben dem Eingabefeld Aufwärts- und Abwärtstasten angezeigt. Durch Drücken dieser Tasten wird die Zahl erhöht oder verringert. Vorangestellte Nullen werden dabei möglicherweise entfernt.
Verwenden Sie stattdessen type="text"
. Dadurch wird die mobile Tastatur nicht nur für Zahlen verwendet, aber das ist in Ordnung, da der nächste Tipp für die Verwendung von inputmode="numeric"
genau das bewirkt.
inputmode="numeric"
Verwenden Sie inputmode="numeric"
, um die mobile Tastatur auf Zahlen zu beschränken.
Einige Websites verwenden type="tel"
für OTP-Eingabefelder, da dadurch auch die mobile Tastatur auf Zahlen (einschließlich *
und #
) umgestellt wird, wenn der Fokus darauf liegt. Dieser Hack wurde in der Vergangenheit verwendet, als inputmode="numeric"
noch nicht weit verbreitet war. Seit Firefox die Unterstützung von inputmode="numeric"
eingeführt hat, ist es nicht mehr erforderlich, den semantisch falschen type="tel"
-Hack zu verwenden.
autocomplete="one-time-code"
Mit dem Attribut autocomplete
können Entwickler angeben, welche Berechtigung der Browser für die automatische Vervollständigung benötigt, und den Browser über die Art der Informationen informieren, die im Feld erwartet werden.
Mit autocomplete="one-time-code"
wird das Einmalpasswort in der SMS heuristisch vom Betriebssystem geparst, wenn ein Nutzer eine SMS erhält, während ein Formular geöffnet ist. Die Tastatur schlägt dem Nutzer dann das Einmalpasswort zur Eingabe vor. Es funktioniert nur in Safari 12 und höher unter iOS, iPadOS und macOS. Wir empfehlen jedoch dringend, es zu verwenden, da es eine bessere Möglichkeit ist, die SMS-OTP-Funktion auf diesen Plattformen zu verbessern.
autocomplete="one-time-code"
in Aktion.
autocomplete="one-time-code"
verbessert die Nutzerfreundlichkeit. Sie können aber noch mehr tun, indem Sie dafür sorgen, dass die SMS dem ursprungsgebundenen Nachrichtenformat entspricht.
Optionale Attribute
Optionale Attribute:
pattern
gibt das Format an, dem das eingegebene Einmalkennwort entsprechen muss. Verwenden Sie reguläre Ausdrücke, um das Abgleichsmuster anzugeben.\d{6}
beschränkt das Einmalkennwort beispielsweise auf einen sechsstelligen String. Weitere Informationen zupattern
finden Sie unter JavaScript für komplexere Echtzeitvalidierung verwenden.required
bedeutet, dass ein Nutzer das Feld ausfüllen muss.
Weitere Informationen finden Sie in unseren Best Practices für Anmeldeformulare.
SMS-Text formatieren
Die Eingabe von Einmalpasswörtern soll nutzerfreundlicher werden. Dazu wird die Spezifikation für ursprungsgebundene Einmalcodes, die per SMS gesendet werden, angepasst.
Die Formatierungsregel lautet im Wesentlichen so: Beenden Sie die SMS-Nachricht mit der Empfängerdomain, vor der @
steht, und dem Einmalpasswort, vor dem #
steht.
Beispiel:
Your OTP is 123456
@web-otp.glitch.me #123456
Das Standardformat für OTP-Nachrichten erleichtert und verbessert die Zuverlässigkeit der Extraktion. Durch die Verknüpfung von Einmalpasswörtern mit Websites wird es schwieriger, Nutzer dazu zu bringen, einen Code auf schädlichen Websites anzugeben.
Genaue Formatierungsregeln
Die genauen Regeln lauten:
- Die Nachricht beginnt mit einem optionalen, für Menschen lesbaren Text, der einen vier- bis zehnstelligen alphanumerischen String mit mindestens einer Zahl enthält. Die letzte Zeile ist für die URL und das Einmalpasswort reserviert.
- Dem Domainteil der URL der Website, die die API aufgerufen hat, muss
@
vorangestellt werden. - Die URL muss ein
#
enthalten, gefolgt vom Einmalpasswort. Die Anzahl der Zeichen darf höchstens 140 betragen.
Die Verwendung dieses Formats bietet einige Vorteile:
- Das Einmalkennwort ist an die Domain gebunden. Wenn der Nutzer andere Domains als die in der SMS-Nachricht angegebene verwendet, wird der Vorschlag für den Einmalcode nicht angezeigt. So wird auch das Risiko von Phishing-Angriffen und potenziellen Kontoübernahmen verringert.
- Der Browser kann das Einmalkennwort jetzt zuverlässig extrahieren, ohne auf unzuverlässige Heuristiken angewiesen zu sein.
Wenn eine Website autocomplete="one-time-code"
verwendet, schlägt Safari unter iOS 14 oder höher das Einmalpasswort gemäß den folgenden Regeln vor.
Dieses SMS-Nachrichtenformat bietet auch Vorteile für andere Browser als Safari. Chrome, Opera und Vivaldi für Android unterstützen die regelgebundenen Einmalcodes mit der WebOTP API, jedoch nicht über autocomplete="one-time-code"
.
WebOTP API verwenden
Die WebOTP API bietet Zugriff auf das in einer SMS empfangene Einmalkennwort. Wenn Sie navigator.credentials.get()
mit dem Typ otp
(OTPCredential
) aufrufen, wobei transport
sms
enthält, wartet die Website auf eine SMS, die den ursprungsgebundenen Einmalcodes entspricht, bis sie zugestellt und vom Nutzer autorisiert wird. Sobald das Einmalkennwort an JavaScript übergeben wurde, kann es von der Website in einem Formular verwendet oder direkt an den Server gesendet werden.
navigator.credentials.get({
otp: {transport:['sms']}
})
.then(otp => input.value = otp.code);
Hier finden Sie eine detaillierte Anleitung zur Verwendung der WebOTP API. Sie können auch das folgende Snippet kopieren und einfügen. Achten Sie darauf, dass Sie in Ihrem <form>
ein action
- und ein method
-Attribut festlegen.
// Feature detection
if ('OTPCredential' in window) {
window.addEventListener('DOMContentLoaded', e => {
const input = document.querySelector('input[autocomplete="one-time-code"]');
if (!input) return;
// Cancel the WebOTP API if the form is submitted manually.
const ac = new AbortController();
const form = input.closest('form');
if (form) {
form.addEventListener('submit', e => {
// Cancel the WebOTP API.
ac.abort();
});
}
// Invoke the WebOTP API
navigator.credentials.get({
otp: { transport:['sms'] },
signal: ac.signal
}).then(otp => {
input.value = otp.code;
// Automatically submit the form when an OTP is obtained.
if (form) form.submit();
}).catch(err => {
console.log(err);
});
});
}