better-auth: デバイス認証の承認画面で、リクエスト元のクライアントや権限情報が表示されない問題

## 影響を受ける可能性はありますか?

`better-auth`のバージョンが`1.3.8-beta.3`から`1.7.0-rc.3`(`1.7.0-rc.3`は含まない)の範囲で、かつ`deviceAuthorization()`プラグインを有効にしている場合、影響を受ける可能性があります。この範囲には、すべての1.6バージョンが含まれます。

以下のすべての条件に該当する場合にのみ、影響を受けます。

- 攻撃者がデバイス認証のリクエストを開始できる:`validateClient`が設定されていない、または攻撃者が有効なパブリッククライアントを使用できる。
- 承認を行う前に、承認画面で、サーバーから確認された情報に基づいて、どのクライアントがリクエストを行っているか、およびリクエストしている正確な権限情報が表示されない。
- ユーザーが、自身が開始したものではなく、所有しているデバイスと照合できないコードや認証リンクを承認してしまう可能性がある。
- アプリケーションが、デバイス認証フローから返されるセッショントークンを受け入れる(例えば、bearerプラグイン経由で)。

`deviceAuthorization()`プラグインを有効にしていない場合は、影響を受けません。

## 概要

デバイス認証プラグインを使用すると、ユーザーは別のデバイスで短いコードを承認することで、あるデバイスにサインインできます。影響を受けるバージョンでは、ユーザーに表示される承認情報から、リクエスト元のクライアントと、リクエストされている権限情報が省略されています。そのため、公式の承認画面の例では、一般的なリクエストとコードのみが表示され、ユーザーは自身のデバイスからのリクエストと、攻撃者からのリクエストを区別できません。

## 影響

サインイン済みのユーザーを騙して、攻撃者のコードを承認させると、攻撃者はそのユーザーの有効なBetter Authセッショントークンを取得できます。攻撃者は、そのトークンを使用して、ユーザーのアカウントからアクセス可能なデータを読み取ったり、変更したりすることができます。この攻撃には、有効化されたデバイス認証フロー、攻撃者が作成したリクエスト、およびユーザーが積極的に承認する必要があり、ユーザーの操作なしにサインインを回避できるものではありません。

## 修正

この問題の修正は、最初に`1.7.0-rc.3`でリリースされました。`better-auth@1.7.0`以降のバージョンにアップデートしてください。1.6のバージョンには、この修正が含まれていません。

アップグレード後、`GET /device` は、リクエストを行ったクライアントの `client_id` と `scope` を、リクエストの所有者であるサインイン済みアカウントに返します。独自の承認ページを作成した場合は、そのページを更新して、そのクライアントと関連する権限を表示し、情報が読み込まれるまで承認機能を無効にしておいてください。

## ワークアラウンド

まだアップグレードできない場合は、以下の操作を行ってください。

- `deviceAuthorization()` を無効にするか、`/device/code` への信頼できないアクセスをブロックします。
- 厳格な `validateClient` の許可リストを設定します。許可リストだけに頼ることは避けてください。許可リストは、フローを開始できるユーザーを制限しますが、ユーザーに不足している承認情報を与えるわけではありません。
- 独自の承認エンドポイントを構築します。このエンドポイントは、信頼できるサーバー側のストレージから保留中のリクエストを読み込み、検証されたクライアント識別子を信頼できる表示名にマッピングする必要があります。正確に要求された権限とユーザーコードを表示します。この情報が読み込まれるまで、承認機能を無効にしておいてください。
- ユーザーに、予期しないデバイスからのリクエストは拒否するように指示します。ユーザーは、現在、自分が所有するデバイスに同じコードが表示されている場合にのみ、承認を行うべきです。

## 技術的な詳細

デバイスは、`/device/code` を呼び出すことでフローを開始します。プラグインは、クライアント識別子と、要求されたスコープを、保留中のリクエストとともに保存します。承認前には、`GET /device` は、ユーザーコードとステータスのみを返します。これは、リクエストの所有者であるユーザーアカウントのサインインセッションであっても同様です。そのレスポンスから構築された承認ページでは、どのクライアントがアクセスを要求したか、またはどのような権限を要求しているかを表示できません。承認後、元のデバイスコードは、`/device/token` で Better Auth セッショントークンと交換できます。

RFC 8628は、このリモートフィッシングのシナリオについて説明しています。サーバーは、ユーザーに対して、デバイスの利用を許可している旨を伝え、そのデバイスがユーザーの所有物であることを確認するように促すことを推奨しています。また、ユーザーがなりすましを検知するのに役立つデバイス情報を表示することも推奨されています。クライアントの許可リストは、フローを開始できるユーザーを制限しますが、ユーザーが不足している承認情報を得ることはできません。したがって、有効なパブリッククライアントであっても、その識別子と要求された権限が表示されない場合、影響を受ける可能性があります。

影響を受けるパッケージ:
- npm (JavaScript) better-auth: 影響を受けるバージョンは、1.3.8-beta.3以上、1.7.0-rc.3未満。1.7.0-rc.3で修正済み。