🦄

ログイン状態の保持(idTokenの更新) - UnityでSDKなしでFirebaseを使う

2021/07/04に公開

この投稿はUnityでSDKなしでFirebaseを使うの一部です。

これまで、様々な認証方法について解説してきましたが、認証に成功した場合に取得できるidTokenは有効期限が1時間しかありません。idTokenの有効期限が切れた際にユーザーにパスワードなどを入力させずに、有効なidTokenを再取得する事でユーザーから見た際にログイン状態が保たれているようにする方法を解説していきます。

idTokenは一般的なAccess TokenとRefresh Tokenを使った認証のAccess Tokenにあたるものですという説明がわかりやすい方も多いかと思います。

途中で出てくるソースコードの全体は以下にあります。
https://github.com/satouso0401/firebase-unity-not-use-sdk/tree/main/Assets/Scenes/Authentication

RefreshTokenの取得

idTokenの更新に使うRefresh Tokenを取得します。これまで紹介してきた様々なサインアップやサインインのレスポンスにRefresh Tokenが含まれていますが、今回はメールアドレスによるサインアップを例に解説していきます。

以下のサンプルコードではRefresh Tokenを変数に保存していますが、実際のコードではローカルストレージなどに保存することで、アプリの再起動を跨いでもログイン状態を保持できます。

RefreshIdTokenScript.cs
private string _apiKey = "APIキーを設定してください";
private static string _refreshToken;

public void GetRefreshToken()
{
    var email = "assafnativ@example.com";
    var password = "dolphins";
    WebClient wc = new WebClient();
    wc.Headers[HttpRequestHeader.ContentType] = "application/json";
    var url = $"https://identitytoolkit.googleapis.com/v1/accounts:signUp?key={_apiKey}";
    var requestBody = new FirebaseApi.EmailPasswordAuthRequest(email, password).ToJson();
    var response = wc.UploadString(new Uri(url), requestBody);
    var authResult = FirebaseApi.EmailPasswordAuthResponse.FromJson(response);
    _refreshToken = authResult.refreshToken;

    Debug.Log($"GetRefreshToken idToken: {authResult.idToken}");
    Debug.Log($"GetRefreshToken refreshToken: {authResult.refreshToken}");
    Debug.Log($"GetRefreshToken expiresIn: {authResult.expiresIn}");
}

idTokenの更新

RefreshTokenを使って新しいidTokenを取得します。他のAPIとContentTypeとリクエストボディーの形式が違う事以外は特に難しいところないAPIです。

RefreshIdTokenScript.cs
public void RefreshIdToken()
{
    WebClient wc = new WebClient();
    NameValueCollection nvs = new NameValueCollection();
    wc.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded";
    var url = $"https://securetoken.googleapis.com/v1/token?key={_apiKey}";
    nvs.Add("grant_type", "refresh_token");
    nvs.Add("refresh_token", _refreshToken);
    var response = wc.UploadValues(new Uri(url), nvs);
    var idTokenResult = FirebaseApi.RefreshIdTokenResponse.FromJson(Encoding.UTF8.GetString(response));
    // ドキュメントを読む限りRefresh Tokenは時間経過では無効にはならないので、
    // 一度サインアップ時に受け取ったRefresh Tokenは使いまわせるはずだが(実際古いRefresh Tokenでも問題なく使える)、
    // idTokenの更新した際のレスポンスのrefresh_tokenは毎回変わるので念のため新しいものに置き換える
    // https://firebase.google.com/docs/auth/admin/manage-sessions?hl=ja
    _refreshToken = idTokenResult.refresh_token;

    Debug.Log($"RefreshIdToken idToken: {idTokenResult.id_token}");
    Debug.Log($"RefreshIdToken refreshToken: {idTokenResult.refresh_token}");
    Debug.Log($"RefreshIdToken expiresIn: {idTokenResult.expires_in}");
}

参考

https://cloud.google.com/identity-platform/docs/use-rest-api?hl=ja#section-refresh-token
https://firebase.google.com/docs/auth/admin/manage-sessions?hl=ja

Discussion