Proving Ownership of a Flow Account

[Previous << Interaction Templates](https://qiita.com/flowcadence/items/e49102ecf2109f9e55bb)
[Next >> Scripts](https://qiita.com/flowcadence/items/ef8373ed9471362f7132)

https://qiita.com/flowcadence/items/3073d69c6e9895e68b5a#reference-2020832ebee1810a325a

<h1>Proving Ownership of a Flow Account</h1>

アプリケーション開発者が共通して抱く要望は、ユーザーがオンチェーンのアカウントを管理(コントロール)していることを証明できること([注1](#注1), [注3](#注3))です。オンチェーンのアカウントの所有権を証明するということは、アプリケーションのバックエンド側でユーザーを認証する方法ということになります。幸いにも、FCLはこれを実現する方法を提供しています。

ユーザー認証の際、FCL対応の一部のウォレットは、FCLの`account-proof`(アカウント証明)サービスをサポートすることを選択します。ウォレットがこのサービスをサポートし、ユーザーがメッセージデータの署名を承認した場合、`account-proof`(アカウント証明)データと署名が返され、ユーザーがオンチェーンのアカウントを管理(コントロール)していることを証明するために使用できます。

アプリケーション開発者が`account-proof`サービスを使用してユーザーを認証する方法について説明していきます。

<h3>Authenticating a user using account-proof</h3>

ウォレットプロバイダーのaccount-proof(アカウント証明)サービスを使用してユーザーを認証するためには、アプリケーションの中で FCLコンフィグレーションに、`fcl.accountProof.resolver` を設定して2つの情報を設定します。

`fcl.accountProof.resolver` はFCLによってアプリケーションサーバーからアカウント証明(account proof)データを取得するために使用される、非同期のresolver関数です。これは、アプリケーションコンフィグレーションの `fcl.accountProof.resolver` keyの下にセットします。resolvedされたデータは、一意なアプリケーション識別子（`appIdentifier`）とランダムな
`nonce` を含めます。このデータは、ユーザーによる署名のためにウォレットに対し送信されます。ユーザーが承認し、署名が成功した場合、その署名はクライアントに対して`account-proof`(アカウント証明)サービスのdataフィールド内に返されます。

**Application Identifier**

アプリケーション識別子とは、あなたのアプリケーション名を一意に識別する人間が読める文字列です。この識別子は、ユーザーが署名リクエストの承認を求められた際に、ウォレットに表示されます。これにより、ユーザーはリクエストの送信元を比較し、悪意のあるフィッシング詐欺を検知しやすくなり、アプリケーションと署名プロセスの信頼性が向上します。

**Random Nonce**

`appIdentifier`に加えて、アプリケーションは**最低32バイトのランダムなnonce**を16進文字列として必ず提供します。

何らかの理由であなたのアプリケーションバックエンドが認証中に`account-proof`(アカウント証明)をリクエストしたくない場合は、`null`のレスポンスを送信する必要があります。FCLが`accountProof.resolver`から`null`のレスポンスを受信した場合、ウォレットによる認証プロセスを継続はしますが、account-proof(アカウント証明)は要求されず、署名が返されません。

> ネットワークまたはサーバーエラーが発生した場合、FCLは認証プロセスをキャンセルし、rejectのpromiseを返します。

```ruby
import {config} from "@onflow/fcl"

type AccountProofData {
  /* e.g. "Awesome App (v0.0)" - A human readable string to identify your application during signing */
  appIdentifier: string;  

  /* e.g. "75f8587e5bd5f9dcc9909d0dae1f0ac5814458b2ae129620502cb936fde7120a" - minimum 32-byte random nonce as hex string */
  nonce: string;          
}

type AccountProofDataResolver = () => Promise<AccountProofData | null>;

config({
  "fcl.accountProof.resolver": accountProofDataResolver
})
```

以下は、アプリケーションがaccount-proof(アカウント証明)サービスを使用する手順の推奨順序です。
* ユーザーは、FCL を使用してあなたのアプリケーション(のクライアント)経由で認証を行いたいとここで考えます。このプロセスは、`fcl.authenticate()` への呼び出しによって開始されます。`fcl.accountProof.resolver` が設定されている場合、FCL はアカウント証明データ（`appIdentifier`と`nonce`）を取得しようとし、あなたのサーバーに対し、新しいアカウント証明認証プロセスをトリガーします。
* あなたのアプリケーションサーバーは、[(ローカルのエントロピーソースを使用して)**最低 32 バイトのランダムなnonce**を生成し](#注2)、それをクライアント(アプリケーション)に送信します。サーバーは、将来の検索用にチャレンジ(the challenge)を保存します。
* FCL が`account-proof`データを正常に取得した場合、ウォレットとのセキュアチャネル上で認証プロセスを続行します。FCL は、`appIdentifier`と`nonce`を`FCL:VIEW:READY:RESPONSE`の一部、または HTTP POST リクエストボディの一部とします。 リゾルバ関数の呼び出しでnonceを取得できなかった場合、FCLは認証プロセスをキャンセルします。
* ウォレットがアカウント証明をサポートしており、ユーザーがウォレットでの認証を承認した場合、ウォレットは`account-proof`サービスをそのレスポンスで返します。

`account-proof`(アカウント証明)サービス内のデータは次のよう形です。
```ruby
{
  f_type: "Service",                    /* Its a service! */
  f_vsn: "1.0.0",                       /* Follows the v1.0.0 spec for the service */
  type: "account-proof",                /* The type of service it is */
  method: "DATA",                       /* Its data! */
  uid: "awesome-wallet#account-proof",  /* A unique identifier for the service */
  data: {
    f_type: "account-proof",
    f_vsn: "2.0.0"

    /* The user's address (8 bytes, i.e 16 hex characters) */
    address: "0xf8d6e0586b0a20c7",                 

    /* Nonce signed by the current account-proof (minimum 32 bytes in total, i.e 64 hex characters) */
    nonce: "75f8587e5bd5f9dcc9909d0dae1f0ac5814458b2ae129620502cb936fde7120a",

    signatures: [CompositeSignature],
  }
}
```
* あなたのアプリケーションのクライアントは、あなたのアプリケーションサーバーとの間でセキュアなチャネルを開始し、`account-proof`データを中継し、あなたのサーバーでユーザーを認証します。その後、クライアントとサーバー間のやり取りは、このチャネルを介して行われます。
* アプリケーションサーバーは`account-proof`のデータ構造を受信し、検証プロセスに入ります。
  - サーバーはFlowのアドレスが既存のアプリケーションアカウントに一致しているかどうかを確認し、ユーザーがログインする必要があるか、あるいは新規アカウントの作成が必要かを判断します。この2つのケースをどのように管理するかは、アプリケーション次第です。
  -  サーバーはチャレンジを検索します。nonceが見つからない、あるいはnonceが期限切れの場合は、認証リクエストを拒否し、それ以外は続行します。
  -  サーバーは、`account-proof`データ構造内の`CompositeSignature`が、nonceとオンチェーン・アカウントに関する有効な署名を含んでいるかどうかを判断します（この方法の詳細については、以下のセクションを参照）。
  -  検証が成功した場合、`nonce`を削除するか、それを期限切れとしてマークし、オンチェーンのアドレスで定義されたアプリケーションのアカウントは正常にログインされます。そうでない場合、認証は失敗し、`nonce`は削除されません。

**Verification**
あなたのアプリケーションは、FCLが提供するユーティリティを使用して、署名と`account-proof`のデータを検証することができます:
```ruby
import { AppUtils } from "@onflow/fcl"

  const accountProofData = {
    accountProof.address,   /* address of the user authenticating */
    accountProof.nonce,     /* nonce */
    accountProof.signatures /* signatures */
  }
  
  const isValid = await AppUtils.verifyAccountProof(
    appIdentifier,
    accountProofData
  )
```
<h1>Implementation considerations:</h1>

* 認証では、FlowアドレスがユーザーのアプリケーションアカウントのIDであると想定しています。既存のユーザーがプロファイルに Flow アドレスを持たない場合、またはユーザーがプロファイルに保存されているものとは異なる Flow アドレスを使用して認証を行うことを選択した場合、ユーザーのアカウントが見つからないので、新規ユーザーを作成するプロセスを考えるでしょう。 既存ユーザーのプロファイルに対し Flow アドレスを更新して FCL 認証を可能にするなど他の認証方法を考えることを、あなたのアプリケーションは検討してください。
* このドキュメントで説明されている`account-proof`のフローでバックエンドは、nonceを生成する時点で、ユーザーアカウントのアドレスを知りません。このため、nonceは特定の Flow アドレスに対して関連付けられることがありません。バックエンドは、各nonceに有効期限を設定して、有効なnonceのプールが無限に増大しないようにするべきです。あなたのアプリケーションはさらに、悪意のある試みを軽減する処置を実装し、スケーラブルな認証プロセスを維持できるようにすることが推奨されます。
<h4>注1</h4>

* FCLの`account-proof`は、ユーザーがFlowアドレスを管理していることを証明する機能を提供します。他の認証、承認、セッション管理などすべての側面は、アプリケーションに委ねられています。安全なユーザー認証システムを構築するためのリソースは他にも数多くあります。アプリケーションの開発者は、自分達のユースケースに何が最適かを慎重に検討し、業界のベストプラクティスに従うべきです。
<h4>注2</h4>

* ランダムなnonceを生成する為には、安全なエントロピーソースを使用することが重要です。このソースは、以前に生成されたnonceを調べてもnonceが予測できないことを保証する必要があります。さらに、バックエンドは独自のローカルソースを使用し、公開された利用可能なソースに依存しないようにするべきです。少なくとも32バイトのnonceを使用することで、nonceの衝突が発生する可能性は極めて低くなります。
* アプリケーション識別子`appIdentifier`は、あなたのバックエンドによって定義された定数です。バックエンドが署名を検証する時は、期待された`appIdentifier`を使用することが重要であり、`account-proof`とともに渡される識別子に依存しないことが重要です。この理由のため、`appIdentifier`は`account-proof`データには含まれていません。
<h4>注3</h4>

* FCL認証が成功すると、ユーザーが完全にFlowアカウントを制御していることが証明されます。つまり、ユーザーはアカウントの総ウエイトに足し合わせると一致する重みを持つ1つまたは複数のアカウントキーを制御していることになります。ユーザーが総ウエイトに足し合わせると一致する重みを持つキーを制御していない場合、認証は失敗します。

*Last updated on **Nov 21, 2024** by **Jordan Ribbink***

翻訳元

https://developers.flow.com/tools/clients/fcl-js/proving-authentication

***
<b>[Previous << Interaction Templates](https://qiita.com/flowcadence/items/e49102ecf2109f9e55bb)
</b>

[Flow blockchain / Cadence version1.0ドキュメント](https://qiita.com/flowcadence/items/3073d69c6e9895e68b5a) (Proving Ownership of a Flow Account)

<b>[Next >> Scripts](https://qiita.com/flowcadence/items/ef8373ed9471362f7132)</b>