WebOTP API が iframe 内から OTP を受信できるようになりました。
SMS OTP(ワンタイム パスワード)は、電話番号の確認(認証の 2 段階目など)やウェブでの支払いの確認によく使用されます。しかし、ブラウザと SMS アプリを切り替えて OTP をコピー&ペーストしたり、手動で入力したりすると、ミスが起こりやすく、ユーザー エクスペリエンスの妨げになります。
WebOTP API を使用すると、ウェブサイトは SMS メッセージからワンタイム パスワードをプログラムで取得し、アプリを切り替えることなく、ユーザーが 1 回タップするだけでフォームに自動的に入力できます。SMS は特別な形式で送信元にバインドされるため、フィッシング ウェブサイトが OTP を盗む可能性も軽減されます。
WebOTP でまだサポートされていないユースケースの 1 つに、iframe 内のオリジンをターゲットにするというものがありました。これは通常、特に 3D セキュアでの支払いの確認に使用されます。クロスオリジン iframe をサポートする共通の形式を備えた WebOTP API は、Chrome 91 以降、ネストされたオリジンにバインドされた OTP を配信するようになりました。
WebOTP API の仕組み
WebOTP API 自体は非常にシンプルです。
…
const otp = await navigator.credentials.get({
otp: { transport:['sms'] }
});
…
SMS メッセージは、オリジン バウンドのワンタイム コードでフォーマットする必要があります。
Your OTP is: 123456.
@web-otp.glitch.me #12345
最後の行には、バインドされるオリジンが @
の後に含まれ、その後に OTP が #
の後に含まれています。
テキスト メッセージが届くと、情報バーがポップアップ表示され、電話番号の確認を求めるメッセージが表示されます。ユーザーが Verify
ボタンをクリックすると、ブラウザは OTP をサイトに自動的に転送し、navigator.credentials.get()
を解決します。ウェブサイトは OTP を抽出して、確認プロセスを完了できます。
WebOTP の基本的な使用方法については、WebOTP API を使用してウェブ上で電話番号を確認するをご覧ください。
クロスオリジン iframe のユースケース
クロスオリジン iframe 内のフォームに OTP を入力することは、支払いシナリオでよくあります。一部のクレジットカード発行会社では、支払者の本人確認を行うために追加の確認手順を必要としています。これは 3D セキュアと呼ばれ、通常、フォームは支払いフローの一部であるかのように同じページの iframe 内に表示されます。
次に例を示します。
- ユーザーが
shop.example
にアクセスして、クレジット カードで靴を購入します。 - クレジット カード番号を入力すると、統合された決済プロバイダが
bank.example
のフォームを iframe 内に表示し、ユーザーに電話番号の確認を求めて迅速な購入手続きを行います。 bank.example
は、ユーザーが入力して本人確認を行えるように、OTP を含む SMS をユーザーに送信します。
クロスオリジン iframe から WebOTP API を使用する方法
クロスオリジン iframe 内から WebOTP API を使用するには、次の 2 つの手順が必要です。
- SMS テキスト メッセージで、トップフレームのオリジンと iframe のオリジンの両方をアノテーションします。
- クロスオリジン iframe がユーザーから OTP を直接受け取れるように、権限ポリシーを構成します。
https://web-otp-iframe-demo.stackblitz.io でデモをお試しいただけます。
SMS テキスト メッセージにバインドされたオリジンをアノテーションする
iframe 内から WebOTP API が呼び出された場合、SMS テキスト メッセージには、最上位フレームのオリジン(@
の後に続く)、OTP(#
の後に続く)、iframe のオリジン(@
の後に続く)を含める必要があります。
@shop.example #123456 @bank.exmple
Permissions Policy を構成する
クロスオリジン iframe で WebOTP を使用するには、埋め込み側が otp-credentials 権限ポリシーを介してこの API へのアクセスを許可し、意図しない動作を回避する必要があります。一般に、この目標を達成するには次の 2 つの方法があります。
- HTTP ヘッダー経由:
Permissions-Policy: otp-credentials=(self "https://bank.example")
- iframe の
allow
属性を使用する:
<iframe src="https://bank.example/…" allow="otp-credentials"></iframe>
権限ポリシーを指定する方法のその他の例 をご覧ください。
注意点
ネストレベル
現時点では、Chrome は、祖先チェーンに一意のオリジンが 1 つ以下のクロスオリジン iframe からの WebOTP API 呼び出しのみをサポートしています。次のシナリオでは、
- a.com -> b.com
- a.com -> b.com -> b.com
- a.com -> a.com -> b.com
- a.com -> b.com -> c.com
b.com での WebOTP の使用はサポートされていますが、c.com での使用はサポートされていません。
なお、次のシナリオは需要の不足と UX の複雑さからサポートされていません。
- a.com -> b.com -> a.com(WebOTP API を呼び出す)
相互運用性
Chromium 以外のブラウザ エンジンは WebOTP API を実装していませんが、Safari は input[autocomplete="one-time-code"]
のサポートで同じ SMS 形式を共有しています。Safari では、オリジンにバインドされた 1 回限りのコード形式を含む SMS が一致するオリジンとともに届くと、キーボードで OTP を入力フィールドに入力するよう提案されます。
2021 年 4 月の時点で、Safari は %
を使用した一意の SMS 形式の iframe をサポートしています。しかし、仕様に関する議論の結果、代わりに @
を使用することになったため、サポートされている SMS 形式の実装が収束することを期待しています。
フィードバック
WebOTP API の改善には皆様からのフィードバックが不可欠です。ぜひお試しいただき、ご意見をお聞かせください。
リソース
写真: rupixen.com(Unsplash)