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

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 にアクセスし、クレジット カードで靴を購入しました。
  • クレジット カード番号を入力すると、統合された決済機関が 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 では、オリジンにバインドされたワンタイム コード形式を含む SMS が一致したオリジンで到着するとすぐに、キーボードが OTP を入力フィールドに入力するよう提案します。

2021 年 4 月現在、Safari は % を使用した独自の SMS 形式の iframe をサポートしています。ただし、仕様の説明では最終的に @ を使用することになりましたので、サポートされている SMS 形式の実装が収束することを願っています。

フィードバック

皆様からのフィードバックは WebOTP API の改善に大いに役立ちます。ぜひお試しいただき、ご意見をお寄せください

リソース

写真提供: rupixen.com(出典: Unsplash