Unity+Firebase+Googleでログイン機能を実装する

cocone connectでクライアントエンジニアをしている田中です。

ログイン機能を実装する際にGoogle,Twitter,Instagramアカウントとの連携を行いました。

長くなるので今回はFirebaseとGoogle連携について要点のみ共有させていただければと思います。

※FirebaseやGoogleのサービス登録は済んでいる前提となります。

シーケンス図

シーケンス図

使用するSDK

 

unitypackageが欲しい場合は以下を参照してください。
https://github.com/googlesamples/google-signin-unity/pull/126#issuecomment-702019117

インストールの注意点

依存関係パッケージ(External Dependency Manager)が上記2つのパッケージに入っているので、firebase-unity-sdkに内包されたもののみインストールしてください。

google-signin-unityはバージョンが古いので両方いれると重複エラーが発生します。

注意点

  • FirebaseSDKとUnityバージョンは依存関係にあるので、うまくいかない場合はFirebaseSDKのバージョンを変える必要があります。
  • google-signin-unityは公式サポートが終了しているので、フォークされたものを使用します。
  • Assets/GoogleSignIn/Editor/GoogleSignInDependencies.xmlの15行目のversionを5.0.2で固定します。
  • cocoapodsはgem製を使用します。
    • sudo gem install cocoapods -n /usr/local/bin

実装例

using UnityEngine;
using System.Threading.Tasks;
using Google;
using UniRx;

public class FirebaseManager
{
    public static readonly string GOOGLE_CLIENT_ID = "クライアントID";

    static FirebaseManager _fm = new FirebaseManager();

    // Auth.CurrentUserに認証情報
    public Firebase.Auth.FirebaseAuth Auth { get; private set; }

    // Android向け 最新のGooglePlay開発者サービスアプリがインストールされているかチェックに使用する
#if UNITY_ANDROID && !UNITY_EDITOR
    Firebase.DependencyStatus _dependencyStatus = Firebase.DependencyStatus.UnavailableOther;
#endif

    public static FirebaseManager Instance()
    {
        return _fm;
    }

    /// <summary>
    /// Google SignIn、Firebaseの初期化
    /// </summary>
    public void Init()
    {
#if !UNITY_EDITOR
        StartWithSignInGoogle();
#endif

#if UNITY_ANDROID && !UNITY_EDITOR
        // GooglePlay開発者サービスアプリがインストールされているかチェックする
        Firebase.FirebaseApp.CheckAndFixDependenciesAsync().ContinueWithOnMainThread(task =>
        {
            _dependencyStatus = task.Result;
            if (_dependencyStatus == Firebase.DependencyStatus.Available)
            {
                // Firebase認証の初期化処理
                Auth = Firebase.Auth.FirebaseAuth.DefaultInstance;
                Debug.Log("Setting up Firebase Auth");
            }
            else
            {
                Debug.LogError("Could not resolve all Firebase dependencies: " + _dependencyStatus);
            }
        });
#elif UNITY_IOS && !UNITY_EDITOR
        Auth = Firebase.Auth.FirebaseAuth.DefaultInstance;
#endif
    }

    /// <summary>
    /// Google SignInの設定
    /// </summary>
    private void StartWithSignInGoogle()
    {
        GoogleSignIn.Configuration = new GoogleSignInConfiguration
        {
            RequestIdToken = true,
            // Copy this value from the google-service.json file.
            // oauth_client with type == 3
            RequestEmail = true,
            WebClientId = GOOGLE_CLIENT_ID
        };
    }

    /// <summary>
    /// Google認証
    /// </summary>
    public void SignInGoogle()
    {
        GoogleSignIn.DefaultInstance.SignIn().ContinueWith(task =>
        {
            if (task.IsCanceled)
            {
                Debug.LogError("GoogleSignIn was canceled.");
            }
            else if (task.IsFaulted)
            {
                Debug.LogError("GoogleSignIn was error.");
            }
            else
            {
                Firebase.Auth.Credential credential = Firebase.Auth.GoogleAuthProvider.GetCredential(((Task<GoogleSignInUser>)task).Result.IdToken, null);
                Auth.SignInWithCredentialAsync(credential).ContinueWith(task =>
                {
                    if (task.IsCanceled)
                    {
                        Debug.LogError("SignInWithCredentialAsync was canceled.");
                        return;
                    }
                    if (task.IsFaulted)
                    {
                        Debug.LogError("SignInWithCredentialAsync encountered an error: " + task.Exception);
                        return;
                    }
                    Firebase.Auth.FirebaseUser newUser = task.Result;
                    SignUpServerWithFirebaseToken(newUser);
                });
            }
        });
    }

    /// <summary>
    /// FirebaseのIDトークンを更新してサーバーにサインアップorサインインする
    /// </summary>
    /// <param name="user">Firebase認証で取得できる認証情報</param>
    void SignUpServerWithFirebaseToken(Firebase.Auth.FirebaseUser user)
    {
        user.TokenAsync(true).ContinueWith(task =>
        {
            if (task.IsCanceled)
            {
                Debug.LogError("TokenAsync was canceled.");
                return;
            }
            if (task.IsFaulted)
            {
                Debug.LogError("TokenAsync encountered an error: " + task.Exception);
                return;
            }
            string token = task.Result;
            // メインスレッドに戻す
            MainThreadDispatcher.Post(_ => /*tokenを使用してログイン*/Debug.Log(token), null);
        });
    }

    /// <summary>
    /// IDトークンの更新を行う
    /// </summary>
    /// <remarks>
    /// CurrentUserに更新トークンがあり、そこからIDトークンを取得できる(IDトークンの期限は1時間)
    /// CurrentUserは一度認証されるとローカル端末に保存されて永続化されている
    /// </remarks>
    public void UpdateToken()
    {
        Auth.CurrentUser.TokenAsync(true).ContinueWith(task =>
        {
            if (task.IsCanceled)
            {
                Debug.LogError("TokenAsync was canceled.");
                return;
            }
            if (task.IsFaulted)
            {
                Debug.LogError("TokenAsync encountered an error: " + task.Exception);
                return;
            }
            string token = task.Result;
            MainThreadDispatcher.Post(_ => /*IDtokenをローカルに保存する*/Debug.Log(token), null);
        });
    }
}

使用例

アプリ開始時

FirebaseManager().Instance().Init()

Googleログイン時

SignInGoogle()

IDを更新したいタイミング(例えば自社サーバーからトークン切れのエラーが返却された際など)

UpdateToken()

所感

Firebaseのドキュメントを確認しても、各プラットフォームのTokenをどうやって取得するのかについて書かれていません。

Web版のSDKはFirebaseのログインに成功するとRefreshTokenを返すのですが、
「Unity版はRefreshTokenにあたるものがCurrentUserに保存されて永続化されている」
という事は明記してほしかった。。。
(RefreshTokenを保存しようとしてプロパティを探していました)

Googleログインをネイティブコードで実装するのは実装コストが高いこともあってSDKを使用したのですが、依存関係の問題でかなり調査が必要になりました。

 

色々とエラーが出ていたわけですが、上記の方法で解決出来ます。
お役に立てば幸いです。

 


ココネでは一緒に働く仲間を募集中です。

ご興味のある方は、ぜひこちらの採用特設サイトをご覧ください。

https://www.cocone.co.jp/recruit/contents/

Category

Tag

%d人のブロガーが「いいね」をつけました。