#01 アカウント管理 | Game Server Services(GS2)

https://www.youtube.com/watch?v=GdlPDIHsF3k

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100723/204e1218-b7de-ee63-a4aa-e4f818fe7c59.png)

第一回は GS2 でアカウント管理をする手順について解説します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100723/24c21763-9c8c-ccde-9180-bf8425dc0bf3.png)

アカウント管理を担う GS2-Account の機能について、まずは解説します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100723/9a00d2d6-74bf-b7b0-80ea-083ba827d620.png)

GS2-Account が提供するアカウントシステムは 匿名アカウント という仕組みで提供されます。
匿名アカウントとは、一般的なWebサイトのようにサインアップ手順を経ずに、システムが発行したユーザーIDパスワードで個人を特定することで動作します。
これによって、ゲームプレイヤーにゲームをダウンロードしてすぐにゲームプレイを開始できる快適さを提供することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100723/ce90baa4-69d5-2f58-27f5-03cc58e20941.png)

匿名アカウントの弱点は ”ゲームプレイヤーは自分のアカウント情報を知らない” ということです。
そのため、デバイスが故障したり、新しいデバイスでゲームをプレイする時に、以前使用していたアカウントでゲームを再開することができません。

そこで用意された機能が「引き継ぎ機能」です。
「引き継ぎ機能」は匿名アカウントに対して、ソーシャルアカウントなどの他のアカウントの情報を紐づけることで設定が可能です。
以降は同じソーシャルアカウントで引き継ぎ処理を行うことで、匿名アカウントでのログイン情報が復元できるため、先ほど挙げたような問題を解消できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100723/0ceb06a0-65c1-1081-9f86-f0749ef20896.png)

GS2 におけるアカウント認証の流れを解説します。

最初に、ゲームは GS2-Account に対してアカウントの作成APIを呼び出します。
すると、ユーザーIDとパスワードが発行され、結果が応答されます。

ゲームは発行されたアカウント情報をセーブデータとして保存します。
次回以降はこの保存したアカウント情報を読み込んでログインすることで、同じアカウントでログインできるようになります。

次に、ログイン処理を行います。ログイン処理は2ステップで構成されます。
まずは、GS2-Account にユーザーIDとパスワードを指定して認証APIを呼び出します。
認証に成功すると、GS2-Account は暗号鍵を管理する GS2-Key に対してアカウント情報の署名を作成するようAPIを呼び出します。
ゲームにはアカウント情報＋署名情報が応答されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100723/106fcb74-0ff7-e7d9-594e-57757194e8da.png)

次に、GS2-Auth のログインAPIを呼び出します。この時先ほど認証処理で得られたアカウント情報と署名情報を送信します。
GS2-Auth は再びアカウント情報の署名計算を GS2-Key に依頼します。
得られた署名と送られてきた署名が一致することを確認し、一致した場合アクセストークンを発行します。

これでログイン処理は完了です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100723/979f0b6c-7a86-9b1d-f7b0-9589c00d983e.png)

GS2-Auth から得られたアクセストークンとはなんでしょうか？

APIを呼び出すごとにユーザーIDとパスワードを送信してしまうと、認証処理が毎回必要になってしまいます。
アクセストークンにはユーザーIDが含まれており、そのユーザーIDで認証基盤によって正しく認証されたことを証明する役割があります。
つまり、アクセストークンは ユーザーID＋パスワード と同じような特性があります。

しかし、アクセストークンには一般的に有効期限が設けられています。GS2では1時間の有効期限があります。
有効期限が切れた場合は再度、認証基盤で認証処理を行なって、新しいアクセストークンを得る必要があります。
これは、パスワードが漏洩した時にはパスワードを変更する対策が取れますが、アクセストークンが漏洩した場合に取れる対策が限られるため、なるべく短い有効期間を設定することで、漏洩した際のリスクを軽減する目的があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100723/44e9b259-c014-78a0-4da3-acb9b2490122.png)

なぜ GS2 の認証処理は GS2-Account と GS2-Auth に分かれているのでしょうか？

それを理解するためには、それぞれの役割について理解する必要があります。
GS2-Account は匿名アカウントや引き継ぎの機能があります。
そして、GS2-Auth にはアクセストークンを発行する機能があります。

ここで重要なのは、アクセストークンさえ得られれば、GS2にログインすることができる ということです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100723/8929af40-8605-3d23-6427-f12a10c58350.png)

GS2-Account を使用せず、GS2-Auth のみ使用して GS2 にログインする例について説明します。

多くのパブリッシャーが独自のコーポレートアカウントを持っています。
そのような独自の認証基盤と GS2 をシームレスに繋ぐために、GS2-Account と GS2-Auth が分かれています。

ここで示す例は、ゲームが独自の認証基盤に対してログイン処理を行うところからスタートしています。
認証基盤は認証に成功したら、GS2-Auth に対して、認証基盤におけるユーザー固有のIDをユーザーIDに指定してアクセストークンの発行APIを呼び出していただくことで、以降GS2でも認証基盤におけるユーザー固有のIDをキーとしてユーザーデータを保持できるようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100723/80c1b4dc-f85f-6ade-20a2-f14d5e22d712.png)

これで GS2 における認証処理の座学は終了です。

それでは、ここからは実装してみましょう

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100723/f242d414-d7d9-2f01-6720-59a7ce38e7c2.png)

GS2 のマネージメントコンソールにアクセスします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100723/e56e1fe7-fcc1-dd30-16dc-fb2230cd8762.png)

最初に GS2-Account の初期設定を行いましょう。
マネージメントコンソールのサイドメニューから Account > Namespaces を選択します。

ネームスペースの一覧が表示されます。
ネームスペースはアカウント情報を保持する領域で、プロジェクト内に複数作成することができます。
今回は “Account” という名前で初期設定のまま設定を進めます。

これで GS2-Account の設定は完了です。

続けて、認証処理で使用する GS2-Key の初期設定をします。
同じくサイドメニューから Key > Namespaces を選択します。

ネームスペースを Key という名前で作成します。
GS2-Account とは異なり、 GS2-Key ではネームスペースを作成するだけでは設定は終わりません。
作成したネームスペースを選択し、暗号鍵を作成します。
“AuthenticationKey” という名前で暗号鍵を作成します。

これで GS2-Key の設定は完了です。

最後に、クレデンシャル(APIキー)の設定をします。
サイドメニューから Identifier > Users を選択します。

”User” という名前でユーザーを作成します。

セキュリティポリシータブを開いて権限を設定します。
セキュリティポリシーはあらかじめ一般的な権限が用意されています。
なかでも ”ApplicationAccess” がゲームプログラムに埋め込んでも安全な権限です。

最後に、クレデンシャル(APIキー)を発行します。
クレデンシャルは GS2-Identifier のユーザーに紐づいて発行され、ユーザーの権限に基づいて呼び出せるAPIが決定します。
発行されたクライアントIDとクライアントシークレットをゲームに組み込んで GS2-SDK を使用します。
クライアントシークレットはページ遷移すると再度確認する手段がなくなりますので、しっかりメモを残すようにしてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100723/9c968e54-ca18-a51c-defe-ac89039e7dbd.png)

```cs
using Cysharp.Threading.Tasks;
using Gs2.Core.Model;
using Gs2.Unity.Core;
using Gs2.Unity.Util;
using UnityEngine;

public class NewBehaviourScript : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        async UniTask Impl()
        {
            Debug.Log("Start");
            
            var profile = new Profile(
                "YourClientId",
                "YourClientSecret",
                new Gs2BasicReopener(),
                Region.ApNortheast1
            );
            await profile.InitializeAsync();
            
            Debug.Log("Initialized");

            var gs2 = new Gs2Domain(profile);
            
            var userId = PlayerPrefs.GetString("UserId");
            var password = PlayerPrefs.GetString("Password");

            if (userId == "" || password == "")
            {
                Debug.Log("Create Account");
                
                var namespaceObject = gs2.Account.Namespace(
                    namespaceName: "Account"
                );
                var createResult = await namespaceObject.CreateAsync(
                );
                var account = await createResult.ModelAsync();
                
                Debug.Log("Save Account");
                
                PlayerPrefs.SetString("UserId", account.UserId);
                PlayerPrefs.SetString("Password", account.Password);
                PlayerPrefs.Save();

                userId = account.UserId;
                password = account.Password;
            }
            
            Debug.Log("Authentication");
            
            var accountObject = gs2.Account.Namespace(
                namespaceName: "Account"
            ).Account(
                userId: userId
            );
            var authenticationResult = await accountObject.AuthenticationAsync(
                keyId: "grn:gs2:ap-northeast-1:xlSzJ6ni-tutorial:key:Key:key:AuthenticationKey",
                password: password
            );
            var body = authenticationResult.Body;
            var signature = authenticationResult.Signature;
            
            Debug.Log("Login");
            
            var accessTokenObject = gs2.Auth.AccessToken(
            );
            var result = await accessTokenObject.LoginAsync(
                keyId: "grn:gs2:ap-northeast-1:xlSzJ6ni-tutorial:key:Key:key:AuthenticationKey",
                body: body,
                signature: signature
            );

            var accessToken = await result.ModelAsync();
        }

        StartCoroutine(Impl().ToCoroutine());
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100723/7d361d23-22ff-9b30-cfd6-35a672d51a7c.png)

マネージメントコンソールで手作業で環境を作ってしまうと、別環境を構築する時に困っちゃう

そんな時に役に立つのが、再現性のある環境構築を実現する GS2-Deploy

次回をお楽しみに