Apple のアカウントでログインができる、「Sign in with Apple」。
実は最近、PlayFab などのサードパーティを使用してログインする場合、Sign in with Apple の実装も「必須」になりました。
すでにリリース済みのアプリも、2020/6末までに対応が必要とのことで、なかなか大変です。
ですが、実装しないといけない割に、「どうやって実装したらいいのか」がちゃんとまとまっていません。
Unity 公式ブログでも実装方法は紹介されているのですが、内容が少し古く、ソースコードや解説も十分とは言えません。
ということで、情報が少なく苦戦しましたが、私が自分で調べて実現しました。
この記事では、Unity において Sign in with Apple を実現し、PlayFab に統合する方法をわかりやすくまとめています。
純粋に Unity に組み込むだけの場合でも、参考になると思います。
読み終える頃には、Sign in with Apple に対する抵抗感もなくなり、スムーズに実装ができるようになっているはずです。
前置きはこれくらいにして、さっそく見ていきましょう。
Sign in with Apple を統合する方法
事前準備
Apple の Developer サイトにログインして、「Sign In with Apple」の機能をつけた Identifier を作成しましょう。
私は以下の情報で登録しました。
「IDENTIFIER」の列はあとで使うので、コピーしておいてください。
次に、PlayFab の管理画面に戻って、アドオンの Apple を有効にします。
先ほどコピーした「IDENTIFIER」を、バンドルIDに設定してください。
トークンの有効期限を設定すると、一定時間(10分)経つと再ログインが必要になり、セキュリティが強化できます。
しかし、ゲームをするのに毎回ログインしていては大変なので、今回は有効期限を無視することにしました。
これで事前準備は完了です。
次からは、Unity 側の処理を見ていきましょう。
オープンソースのダウンロード
Unity 公式でも Sign in with Apple のサンプルが公開されているのですが、圧倒的に評価が低く、使うのをやめました。
調べたところ、評価の良いオープンソースを見つけたので、今回はこちらを使用することにします。
まずは、最新の unitypackage をダウンロードしてください。
ダウンロードできたら、プロジェクトにインポートします。
これができたら、次はPlayFab 側の処理を書いていきましょう。
Apple アカウントをリンクする種類
リンクする方法は、「すでに PlayFab のアカウントを作成しているかどうか」で異なります。
- 未作成:Login With Apple を使用
- 作成済:Link Apple を使用
まだ PlayFab のアカウントを作成していない場合は、アカウントを作成すると同時に Apple とリンクします。
これはゲームに一度もログインしたことがない人のための処理ですね。
一方で、一度はログインしたことがあるけど、あとで Apple とリンクする場合は、リンクする専用の処理を呼び出します。
ということで、実際の処理を見てきましょう。
PlayFab 側の呼び出し処理
まずは、Login With Apple から見てみます。
public static void LoginWithApple(byte[] identityToken)
{
PlayFabClientAPI.LoginWithApple(new LoginWithAppleRequest
{
CreateAccount = true,
IdentityToken = Encoding.UTF8.GetString(identityToken),
TitleId = PlayFabSettings.TitleId
}
, result =>
{
Debug.Log("Login With Apple Success!!");
}
, error => { Debug.Log(error.GenerateErrorReport()); });
}
すごくシンプルなのですが、1つだけ解決にかなり時間をかけたところがあります。
それが以下の部分。
IdentityToken = Encoding.UTF8.GetString(identityToken),
PlayFab 側の IdentityToken は JWT の文字列で渡す必要があるのですが、オープンソース内部で保持されているのは、Base64 byte配列でした。
この byte配列を JWT の形式に変換する処理が、上記というわけですね。
JWTは「Json Web Token」の略で、「ジョット」と読むそうです。(読めない)
私も深いところまでは理解できていませんが、簡単にいうと
- クライアント側で生成できない、複雑な文字列
- 文字列を解析して、内容を検証することができる
という感じです。
さらに詳しく知りたい人は、JWTの概要と使い所も参照してみてください。
リンクする専用の処理も同様で、特に解説は不要でしょう。
public static void LinkApple(byte[] identityToken)
{
PlayFabClientAPI.LinkApple(new LinkAppleRequest
{
IdentityToken = Encoding.UTF8.GetString(identityToken)
}
, result =>
{
Debug.Log("Link Apple Success!!");
}
, error => { Debug.Log(error.GenerateErrorReport()); });
}
リンクする場合は、Startメソッドなどであらかじめログインしておく必要がありますが、ここでは割愛します。
PlayFab 側の実装はこれで完了です。
オープンソースへの組み込み
先ほど作成した処理を、ログイン成功後の処理に差し込んであげれば準備は完了です。
private void AttemptQuickLogin()
{
var quickLoginArgs = new AppleAuthQuickLoginArgs();
// Quick login should succeed if the credential was authorized before and not revoked
this._appleAuthManager.QuickLogin(
quickLoginArgs,
credential =>
{
// If it's an Apple credential, save the user ID, for later logins
var appleIdCredential = credential as IAppleIDCredential;
if (appleIdCredential != null)
{
PlayerPrefs.SetString(AppleUserIdKey, credential.User);
// この1行を追加!!
PlayFabController.LoginWithApple(appleIdCredential.IdentityToken);
// この1行を追加!!
}
this.SetupGameMenu(credential.User, credential);
},
error =>
{
// If Quick Login fails, we should show the normal sign in with apple menu, to allow for a normal Sign In with apple
Debug.LogWarning("Quick Login Failed " + error.ToString());
this.SetupLoginMenuForSignInWithApple();
});
}
IAppleIDCredential で持っている、IdentityToken を渡してあげるのがポイントです。
ビルドして実行
実行すると、以下のように画面が変わっていきます。
ユーザー名やメールアドレスなどは隠していますが、最後の画面が出ればOKです。
また、PlayFab の管理画面では、先ほどの「Username」が紐付いていることが確認できます。(塗りつぶしたのでわかりにくい)
ひと通りの流れとしては以上です。
トークンの中身について
ここからは、アカウントに紐付けるトークンが正しいか検証する方法について解説していきます。
公式の開発ドキュメントによると、トークンでは以下のことを確認すべきと言っています。
- サーバーの公開鍵を使用して JWS E256 署名を確認
- nonce 認証を確認
- iss フィールドが「https://appleid.apple.com」であることを確認
- aud フィールドが開発者のものであることを確認
- 時刻が exp トークンの値より前であることを確認
aud とか exp とかについては、公式の「Generate and validate tokens」で解説されています。
しかし、実際は少し違うかな?と感じたので以下にまとめてみました。
kid | 「86D88Kf」固定 |
---|---|
alg | 「RS256」固定 |
iss | 「https://appleid.apple.com」固定 |
aud | バンドルID |
exp | トークンの有効期限(エポック秒) |
iat | トークンが発行された時刻(エポック秒) |
sub | ユーザー名 |
c_hash | 認証コードのハッシュ値 |
Emailアドレス(どこのアドレスかは謎) | |
email_verified | Emailが認証されたか |
is_private_email | private なアドレスかどうか(謎) |
auth_time | 認証された時刻(iat と同じでは?) |
nonce_supported | nonceのサポートがされているか |
ちなみに、kid は https://appleid.apple.com/auth/keys から取得されていると思われます。
デバッグで JWT の生データを取り、jwt.ioというサイトで見てみると、以下のように中身を確認することができます。
こう見ると、ちゃんと中身が入っていることが確認できますね。
具体的な値を確認すると、exp(有効期限)は、ちゃんと iat(発行時刻)の10分後に設定されていました。
サイト上でマウスカーソルを合わせるとツールチップで値がわかるので、実際に確認してみてください。
トークンを検証する方法
ここからは、実際にトークンを検証する方法について解説していきます。
試しに、「aud フィールドが開発者のものであることを確認する」というケースを見てみましょう。
PlayFab の管理画面で、うっかり違うバンドルIDを入力してしまったとします。
すると、PlayFab と連携する際に以下のエラーが出るようになっています。
Audience validation failed. Audiences: 'com.nekojoker.signinwithapple'.
Did not match: validationParameters.ValidAudience: 'com.nekojoker.signinwithapple1234’.
つまり、ある程度は PlayFab 側でトークンを検証してくれている、ということがわかりますね。
全部を確認したわけではありませんが、そこまで厳密にチェックをしなくてもよさそうです。
という人もいるかと思いますので、どうやったらチェックができそうかも検証してみました。
ここからは、具体的にチェックするにはどうしたらいいのかについて解説していきます。
NuGet の導入
JWT はそのままでは中身の解析ができないので、解析できる形式に変換して上げる必要があります。
Microsoft からライブラリが提供されているので、今回はそれを使用していきます。
まずは、NuGet を Unity で使いたいので、専用のパッケージをインポートします。
以下からダウンロードしてください。
ダウンロードができたら、インポートしましょう。
そのあと、「Nuget > Manage NuGet Packages」と進んでいきます。
続いて、System.IdentityModel.Tokens.Jwt をインストールしていきます。
- 「jwt」と入力する
- 右の Search ボタンを押す
- Install ボタンを押す
これでモジュールを使用する準備が整いました。
JWT を解析する
インストールした System.IdentityModel.Tokens.Jwt の使い方についてです。
上の方でまとめた alg や kid を値として取り出すことができれば、そこから解析ができます。
以下の例は、それぞれの値を取り出す処理の例です。
public void OutputJwt()
{
// IdentityToken をもってくる処理は割愛
var utf8Str = Encoding.UTF8.GetString(appleIdCredential.IdentityToken);
var handler = new JwtSecurityTokenHandler();
var tokenS = handler.ReadToken(utf8Str) as JwtSecurityToken;
tokenS.Claims.ToList().ForEach(x => Debug.Log(x.Type.ToString() + ":" + x.Value));
}
この JsonSecurityTokenHandler というのが、JWT をうまいこと読み込んでくれるクラスです。
実際に実行した結果が以下になりました。
一つずつ値を取り出すことができたので、いろいろと検証はできそうですね。
最後に
Sign in with Apple を PlayFab と統合する方法について解説しました。
実装が必須になっているわりに、情報が少なく難易度も高い気がします。
私もまだまだ理解が足りない部分があるので、記事内容で変なところがあれば教えていただけると嬉しいです。
また、この記事で紹介しきれなかった点や、さらに詳しい情報は以下のサイトで学習できるので、合わせてご覧ください。
かなり調べて厳選したサイトなので、必ず役に立つはずです。
この記事で少しでも Sign in with Apple がスムーズに実装できる助けになれば幸いです。
PlayFab のことをもっと皆さんに知ってもらいたくて、合計500ページ以上にもなる書籍を5冊に分けて執筆しました。
私の知識をすべて詰め込んでいるので、ゲーム開発をさらに加速させたい方はぜひご覧ください。
このチュートリアルに従ってAppleでログインを実装することはできません。理解を深めるために、ソースコードを共有していただけますか?
申し訳ありませんが、サンプルのソースコードは公開していません。
うまくいかない場合は、記事で参照している GitHub のリポジトリもあわせて参照してみてください。
https://github.com/lupidan/apple-signin-unity