はじめまして。
開発チームでAndroidエンジニアをしている松崎です。
今回は弊社のプロダクトである「nana」のAndroidアプリで初めて担当したFirebase Authenticationを使ったTwitter認証の機能を実装したお話をします。
なぜFirebase Authenticationを導入したのか
nanaでは以前からTwitter認証に Twitter Kit for Androidを使用していました。
しかしある時期から「Twitterアカウントでのログインに失敗する」というユーザからの問い合わせが増えてきました。
原因について調査を進めたものの有効な解決策が見つけられないまま時間が過ぎてしまっていたこと、Twitter Kit for Androidのサポートが2018年に終了しており使い続けることにリスクがあるだろうということで、思い切ってFirebase Authenticationを使った認証に移行することに決めました。
(当時ググってみた限り、Firebase Authenticationを使ったTwitter認証の事例記事はあまりなく、技術的な挑戦という側面もありました)
nanaの動作環境
本題に入る前に、nanaアプリの動作環境をご紹介します。
- Development : 開発環境
- Staging : リリース前テスト環境
- Production : 本番
Androidアプリでは、それぞれの環境をGradleのProductFlavorで切り分けて管理しています。 また、それぞれの環境のアプリはデバッグアプリで1つのアプリ署名、リリースビルドで1つのアプリ署名をそれぞれ共通で使用しています。
導入
環境構築
Firebaseを初めて使用する場合、アプリへのSDKの追加やFirebaseへのアプリケーションの登録、Firebase AuthenticationのTwitter認証を有効にします。
また、Firebase Authenticationを使うためにはアプリ署名のフィンガープリントをFirebaseに登録する必要があります。
手順は下記のリファレンスを参考にしました。
firebase.google.com
nanaではすでにFirebaseを使用しており、3つの環境(Development
Staging
Production
)のFirebaseプロジェクトの設定も概ね実施されていたため、Twitter認証の有効化のみ行いました。
(このとき、StagingのFirebaseプロジェクトもアプリ署名のフィンガープリントが表面上はきちんと登録されているように見えていました。しかしFirebaseの内部的には不正な登録状態になっており後述するStaging環境でTwitter認証できない
という問題に直面します、、)
実装
基本的には下記のリファレンスに従って既存の処理を置き換えていくだけで、すぐに認証処理が実現できました。 firebase.google.com
ただし、サインアップ / ログイン時に任意のアカウントで認証したい、というユースケースを実現するには少し工夫する必要がありました。
以下に実現方法をご紹介していきます。
サインアップ / ログイン時に任意のアカウントで認証できるようにする
Firebase Authenticationは認証処理をChrome Custom Tabsによって行います。
最初にTwitterアカウントでサインアップ / ログインを行うと、その情報はChromeアプリに保存され以降の認証はその情報を自動的に使いまわして行われます。
そのため、アカウントが切り替えられないという事象に陥ります。
この事象の解決手段として、ログイン時にTwitter認証する際のOAuthProvider
にforce_login
というパラメータを使います。
force_login
をtrue
に設定することで、ユーザにID/PWの入力を強制することができます
val oAuthProvider = OAuthProvider.newBuilder(TwitterAuthProvider.PROVIDER_ID) // アカウントを切り替えるため、ログイン時に過去の認証を使い回さず、毎回ログイン情報を入力させることを強制する .addCustomParameter("force_login", "true") .build() firebaseAuth.startActivityForSignInWithProvider(this, oAuthProvider) .addOnSuccessListener(this::authSuccess) .addOnFailureListener(this::authError);
ハマったところ
Staging環境でTwitter認証できない
問題点
nanaではStaging
と Production
はアプリの applicationId
が同じになっています。
これはGoogle Play Billing Libraryを使った課金テストを Staging
アプリでも行えるように、アプリ作成当初からこのようになっていました。
この問題の真因は上述のStaging
と Production
はapplicationId
が同一であることと、アプリ署名ファイルも同じものを使って署名していた点でした。
Firebaseではプロジェクトごとにアプリケーションを識別するために、applicationId
とアプリ署名の2つをセットで一意に識別しています。
そのため、複数のFirebaseプロジェクトに同一のapplicationId
とアプリ署名のセットを登録することはできません。
つまり、Staging
のapplicationId
もしくはアプリ署名をProduction
と別のものにする必要があります。
上記の制約については、下記のリファレンスに記載されています。
support.google.com
補足
ここでの問題はもう1つあり、導入編の環境構築で記載したとおりStaging
のFirebaseプロジェクトにはアプリ署名のフィンガープリントが表示されており正しく登録されているように見えていました。
しかし、google-services.json
をダウンロードしてみるとAuthenticationの設定がなく正しく登録されていないような出力となっていました。
おそらく以前は、Firebaseでのアプリケーション登録時に同一のapplicationId
とアプリ署名を複数プロジェクトで登録できなくする入力チェックがなかったのではないかと思います。(現在は入力時にエラーが表示されます)
解決策
先述のとおりStaging
は課金テストを行える必要があり、applicationId
を変更するとGoogle Play Consoleへの登録作業など必要な工程が増えるため、今回はアプリ署名をStaging
専用のものを作成して使用することにしました。
アプリ署名を作成しCIの設定修正やFirebaseへの登録を行うことで正常にTwitter認証を行えるようになりました。
最後に
nanaでは、技術的な挑戦は歓迎されており今後も新しい技術に取り組んでいきます。
これからも得た知見などを発信していきたいと思います。
同じ課題に取り組まれる方の参考になれば幸いです。
最初から大きな案件にチャレンジさせてもらえる環境です! 一緒にチャンレジしたい方はぜひ一度お話を聞いてみませんか?