nana開発者ブログ

音楽SNSアプリ"nana"開発チームのブログです。

AndroidアプリにFirebase AuthenticationによるTwitter認証を導入した話

はじめまして。
開発チームで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認証する際のOAuthProviderforce_loginというパラメータを使います。
force_logintrueに設定することで、ユーザに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ではStagingProduction はアプリの applicationIdが同じになっています。
これはGoogle Play Billing Libraryを使った課金テストを Stagingアプリでも行えるように、アプリ作成当初からこのようになっていました。
この問題の真因は上述のStagingProductionapplicationIdが同一であることと、アプリ署名ファイルも同じものを使って署名していた点でした。
Firebaseではプロジェクトごとにアプリケーションを識別するために、applicationIdとアプリ署名の2つをセットで一意に識別しています。
そのため、複数のFirebaseプロジェクトに同一のapplicationIdとアプリ署名のセットを登録することはできません。
つまり、StagingapplicationIdもしくはアプリ署名をProductionと別のものにする必要があります。
上記の制約については、下記のリファレンスに記載されています。 support.google.com

補足

ここでの問題はもう1つあり、導入編の環境構築で記載したとおりStagingのFirebaseプロジェクトにはアプリ署名のフィンガープリントが表示されており正しく登録されているように見えていました。
しかし、google-services.jsonをダウンロードしてみるとAuthenticationの設定がなく正しく登録されていないような出力となっていました。
おそらく以前は、Firebaseでのアプリケーション登録時に同一のapplicationIdとアプリ署名を複数プロジェクトで登録できなくする入力チェックがなかったのではないかと思います。(現在は入力時にエラーが表示されます)

解決策

先述のとおりStagingは課金テストを行える必要があり、applicationIdを変更するとGoogle Play Consoleへの登録作業など必要な工程が増えるため、今回はアプリ署名をStaging専用のものを作成して使用することにしました。 アプリ署名を作成しCIの設定修正やFirebaseへの登録を行うことで正常にTwitter認証を行えるようになりました。

最後に

nanaでは、技術的な挑戦は歓迎されており今後も新しい技術に取り組んでいきます。
これからも得た知見などを発信していきたいと思います。
同じ課題に取り組まれる方の参考になれば幸いです。


最初から大きな案件にチャレンジさせてもらえる環境です! 一緒にチャンレジしたい方はぜひ一度お話を聞いてみませんか?

www.wantedly.com