WebOTP API を使用してクロスオリジンの iframe 内で OTP フォームに入力する

WebOTP API が iframe 内から OTP を受信できるようになりました。

SMS OTP(ワンタイム パスワード)は、認証の 2 つ目のステップとして、またはウェブでの支払いの確認など、電話番号の確認に一般的に使用されます。ただし、ブラウザと SMS アプリを切り替えて OTP をコピー&ペーストまたは手動で入力すると、ミスが生じやすく、ユーザー エクスペリエンスが低下します。

WebOTP API を使用すると、ウェブサイトは SMS メッセージからワンタイム パスワードをプログラムで取得し、アプリを切り替えることなくユーザーのフォームにワンタップするだけで自動的に入力できます。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 メッセージは、送信元にバインドされた 1 回限りのコードをフォーマットする必要があります。

Your OTP is: 123456.

@web-otp.glitch.me #12345

最後の行には、@ で始まるバインド先のオリジンと、# で始まる OTP が含まれています。

テキスト メッセージが届くと、情報バーがポップアップ表示され、電話番号の確認を求めるメッセージが表示されます。ユーザーが Verify ボタンをクリックすると、ブラウザは OTP を自動的にサイトに転送し、navigator.credentials.get() を解決します。ウェブサイトは OTP を抽出して確認プロセスを完了できます。

WebOTP の基本的な使用方法については、WebOTP API を使用してウェブ上で電話番号を確認するをご覧ください。

クロスオリジン iframe のユースケース

支払いシナリオでは、クロスオリジンの iframe 内のフォームに OTP を入力するのが一般的です。一部のクレジット カード発行会社では、支払者の真正性を確認するために追加の確認手順が必要です。これは 3D Secure と呼ばれ、通常、フォームは支払いフローの一部であるかのように、同じページの iframe 内に表示されます。

次に例を示します。

  • ユーザーが shop.example にアクセスして、クレジット カードで靴を購入します。
  • クレジット カード番号を入力すると、統合された支払いプロバイダが iframe 内に bank.example のフォームを表示し、ユーザーに電話番号の確認を求めて、迅速な購入手続きを促します。
  • bank.example は、OTP を含む SMS をユーザーに送信します。ユーザーは、OTP を入力して本人確認を行うことができます。

クロスオリジン iframe から WebOTP API を使用する方法

クロスオリジン iframe 内から WebOTP API を使用するには、次の 2 つのことを行う必要があります。

  • SMS テキスト メッセージで、トップフレームのオリジンと iframe オリジンの両方にアノテーションを付けます。
  • クロスオリジン iframe がユーザーから OTP を直接受け取れるように、権限ポリシーを構成します。
iframe 内の WebOTP API の動作。

デモは https://web-otp-iframe-demo.stackblitz.io で試すことができます。

バウンド送信元を SMS テキスト メッセージにアノテーションする

WebOTP API が iframe 内から呼び出される場合は、SMS テキスト メッセージに、@ の後にトップフレームのオリジン、# の後に OTP、@ の後に iframe オリジンを含める必要があります。

@shop.example #123456 @bank.exmple

権限ポリシーを構成する

クロスオリジン 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.comUnsplash