FlutterでFirebaseAuthentication[Twitter認証]を行う

前提

前回までの記事を通して、Google認証によるFirebaseAuthenticationの実装ができていることが前提です。

以上の記事を通した方はある程度簡単に実装できるかと思いますので試してみましょう!

Twitterにて開発者登録を行う

まずはTwitterにて開発者登録を行う必要があります。

https://developer.twitter.com/ja/apply-for-access

こちらのサイトから進めていきます。基本英語なので分かりにくいですが、電話番号認証や開発者情報の入力等こなしていきます。
こちらのサイトが参考にしやすいでしょう。

https://qiita.com/kei2ro/items/17fac4502119e9918763

APIキーの取得

開発者登録が終わったら、Twitter側でプロジェクトの作成を行い、APIキーを取得します。これも細かい分は他の先人の知恵が検索すると出てくるのでそちらを参考にしてください。TwitterからAPIキー、APIシークレットをFirebase側に、FirebaseからコールバックURLをTwitter側に設定してください。

また、Twitter側のコールバックは複数設定する必要があります。

一番上はFirebaseから持ってきたコールバックURL、2番目はtwitterkit-[twitterのAPIキー]://、3番目はtwittersdk:// 固定文字列です。
下までスクロールしてSaveを忘れず押してくださいね。

サインアウト処理の実装,前回作成処理のリネーム

前回までの記事をみてもらうと分かりますが、Googleログインはできますがログアウト処理を実装していないので先に準備しておきましょう。また、前回のメソッド名のままだとGoogleとTwitterどちらなのか分かりにくいのでメソッド名も変えます。

まずはサインアウト処理から。

  static Future<bool> signOut() async {
    final FirebaseAuth _auth = FirebaseAuth.instance;
    try {
      await _auth.signOut();
      return true;
    } catch (e) {
      print(e);
      return false;
    }
  }

signOutは共通で良いみたいです。サインアウトできているかどうかは、
(await _auth.currentUser()).displayName をprintする様にすると確認できます。連続でこのメソッドを通ると、二度目はcurrentUserがnullになってます。
また、Google認証のメソッドに
「googleCurrentUser = await _googleSignIn.signInSilently();」という記述があります。これが前回の入力を使って自動でログインしてくれる機能です。もしデバッグの邪魔ならコメントアウトする様にしましょう。

そして前回作成したGoogle認証を行うメソッドsignIn()をsignInWithGoogle()に変更しました。

とりあえずボタン類の作成

前回作成したGoogle認証ボタンを参考に、Twitter認証ボタンとサインアウトボタンを作成してみてください。自分は前回の分含めこんな感じにしてます。

          RaisedButton(
            child: Text('Sign in Google'),
            onPressed: () {
              FirebaseAuthHelper.signInWithGoogle()
                  .then((FirebaseUser user) => _showResultDialog(user))
                  .catchError((e) => print(e));
            },
          ),
          RaisedButton(
            child: Text('Sign in Twitter'),
            onPressed: () {
              FirebaseAuthHelper.signInWithTwitter()
                  .then((FirebaseUser user) => _showResultDialog(user))
                  .catchError((e) => print(e));
            },
          ),
          RaisedButton(
            child: Text('Sign out'),
            onPressed: () {
              FirebaseAuthHelper.signOut()
                  .then((bool isOK) => _showSignOutResultDialog(isOK))
                  .catchError((e) => print(e));
            },
          ),

signInWithTwitter()はまだ実装していないのでエラーが出ます。また、サインアウト結果を表示するメソッドは

void _showSignOutResultDialog(bool isOK) {
    String resultText = "ログアウトしました。";
    if (!isOK) resultText = "ログアウト失敗";
    showDialog(
        context: context,
        builder: (_) {
          return AlertDialog(
            title: Text(resultText),
          );
        });
  }

こんな感じです。まあこの辺は自分がデバッグしやすい様に変えてください。FirebaseのSignOut処理は返り値がvoidなので、特に表示に使えそうな情報はありません。

Twitter認証処理の作成

本題です。pubspec.yamlにflutter_twitterを追加します。

dependencies:
  flutter:
    sdk: flutter
  firebase_core:
  firebase_auth:
  google_sign_in:
  flutter_twitter: //追加

今までの記事を通して行った場合、この様な記述になっているはずです。保存してパッケージをインストールしましょう。

先にコーディングを行いますが、設定が足りておらずiOSでビルドできません。その辺りを前提に作業を行ってください。

static Future<FirebaseUser> signInWithTwitter() async {
    final String apiKey = "Twitterで取得したAPIキー";
    final String apiSecret = "Twitterで取得したAPIシークレット";

    final TwitterLogin _twitterLogin =
        new TwitterLogin(consumerKey: apiKey, consumerSecret: apiSecret);
    final FirebaseAuth _auth = FirebaseAuth.instance;

    try {
      final _twitterLoginResult = await _twitterLogin.authorize();
      final _currentUserTwitterSession = _twitterLoginResult.session;
      if (_currentUserTwitterSession == null) return null;
      AuthCredential _authCredential = TwitterAuthProvider.getCredential(
          authToken: _currentUserTwitterSession.token,
          authTokenSecret: _currentUserTwitterSession.secret);
      final FirebaseUser _user =
          (await _auth.signInWithCredential(_authCredential)).user;
      return _user;
    } catch (e) {
      print(e);
      return null;
    }
  }

Google認証の処理とほとんど変わりません。

iOSビルドエラー対処

一旦、flutter cleanコマンドを実行しておいてください。
このタイミングでビルドするとエラーが出る様に。

Error output from CocoaPods:
↳

    [!] Automatically assigning platform `iOS` with version `8.0` on target
    `Runner` because no platform was specified. Please specify a platform for
    this target in your Podfile. See
    `https://guides.cocoapods.org/syntax/podfile.html#platform`.

どうもiOSのバージョンに関する設定がされていないと怒られている様です。ios/podfileを開き、一番上の方でコメントアウトされているので設定しましょう。flutter_twitterはiOSバージョンが10.1以上でないとエラーが出てしまうので自分はとりあえず10.1以上を許可する様にしました。

# Uncomment this line to define a global platform for your project
platform :ios, '10.1'

このpodfileについて自分は詳しくないですが、どうも普段はFlutterがいい感じにしてくれてたみたいですね。

試してみる

ここまでで動くはずです。試してみましょう。まずはiOSです。

次はAndroidです。ビルドこそ通りますがエラーが出てます。とりあえず動作確認はできるのでいったん放置します。

注意:/Users/yuya/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_twitter-1.1.3/android/src/main/java/com/roughike/fluttertwitterlogin/fluttertwitterlogin/TwitterLoginPlugin.javaは非推奨のAPIを使用またはオーバーライドしています。
注意:詳細は、-Xlint:deprecationオプションを指定して再コンパイルしてください。
Android 認証画面

長かったですね。お疲れ様でした。

まとめ

Google認証と違って情報がほとんどなく、英語圏のサイトをみてもどれが正統派な実装なのか分かりません。今回はFlutterでTwitter認証をできる様にするための方法の一つとして公開しますが、これが正解かは分かりません。とりあえずこんな感じなんだと思ってもらえたら幸いです。

今回身に染みましたが英語力って大事ですね。勉強しなければ。。。