flutter界隈での鬼門はtwitterAuth認証でしょう。情報がない&パッケージがメンテされていないで毎回時間がかかってしまう。
当ブログでもだいぶ前に記事書いてますが、その内容だとflutter2では使えないですし、何よりiOSでストアへアップする際の審査申請で弾かれてしまいます。[UIWebView問題]
有名どころは「twitter_login」や「flutter_twitter_login」でしょうか。今回、どちらも使えなかったので最終的に自作することになりました。(いろんな記事を参考してます)
ちなみに、FirebaseAuthに必要な細かい必須処理等は省いています。その辺りは別記事を読んでください。
実装
まずはpubspec.yaml。多分大事なのはこれらです。他にもいるかも。バージョンは適宜最新版が使えるかどうか試してみてください。
firebase_core: ^1.0.3
firebase_auth: ^1.0.2
provider:
oauth1: ^2.0.0
webview_flutter: ^2.0.4
早速、今回の実装コードを晒していきます。たびたび出てくるConstValuesはstaticに設定を定義しているだけなので、各自固定文字列に変更する等行ってください。
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:oauth1/oauth1.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:provider/provider.dart';
class TwitterAuthUtil {
static Future<TwitterAuthResult> login(BuildContext context) async {
TwitterAuthResult result = await Navigator.push(context, MaterialPageRoute(builder: (context) => TwitterAuthStarter()));
return result;
}
}
class TwitterAuthStarter extends StatelessWidget {
TwitterAuthStarter();
@override
Widget build(context) {
return ChangeNotifierProvider(
create: (context) => TwitterAuthController(),
child: TwitterAuthPage(),
);
}
}
class TwitterAuthController with ChangeNotifier {
bool isFirst = true;
bool isDisposed = false;
Widget webView = CircularProgressIndicator();
@override
void dispose() {
isDisposed = true;
super.dispose();
}
void changeIsFirst(bool first) {
isFirst = first;
notifyListeners();
}
void changeWebView(Widget value) {
webView = value;
notifyListeners();
}
}
class TwitterAuthPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
String callbackURI = ConstValues.callbackURI;
final state = Provider.of<TwitterAuthController>(context);
if (state.isFirst) {
state.changeIsFirst(false);
Future(() async {
final clientCredentials = ClientCredentials(ConstValues.apiKey, ConstValues.apiSecret);
final twitterPlatform = Platform(
'https://api.twitter.com/oauth/request_token',
'https://api.twitter.com/oauth/authorize',
'https://api.twitter.com/oauth/access_token',
SignatureMethods.hmacSha1,
);
//トークンをリクエスト後、認証ページURIをリクエスト。
Authorization oauth = Authorization(clientCredentials, twitterPlatform);
var requestTokenResponse = await oauth.requestTemporaryCredentials(callbackURI);
var authorizationPage = oauth.getResourceOwnerAuthorizationURI(requestTokenResponse.credentials.token);
var webView = WebView(
initialUrl: authorizationPage,
onPageStarted: (String url) async {
// コールバック監視
if (url.startsWith(callbackURI)) {
final queryParameters = Uri.parse(url).queryParameters;
final oauthToken = queryParameters['oauth_token'];
final oauthVerifier = queryParameters['oauth_verifier'];
if (null != oauthToken && null != oauthVerifier) {
var response = await oauth.requestTokenCredentials(Credentials(oauthToken, ''), oauthVerifier);
Navigator.pop(context, TwitterAuthResult(true, response.credentials.token, response.credentials.tokenSecret));
} else {
state.changeWebView(Text('login failed'));
}
}
},
);
state.changeWebView(webView);
});
}
return Scaffold(appBar: AppBar(), body: state.webView);
}
}
class TwitterAuthResult {
String token = '';
String tokenSecret = '';
bool isSuccessed = false;
TwitterAuthResult(this.isSuccessed, this.token, this.tokenSecret);
}
上のコードを、自分はTwitterAuthUtil.dartという名前で作成しました。
呼び出す側はこんな感じ。
final authResult = await TwitterAuthUtil.login(context);
String token = authResult.token;
String tokenSecret = authResult.tokenSecret;
なかなかシンプルでいいですね!あとは他の認証と同じようにCredentialからUserを取得していく流れです。
まとめ
一度自分で実装すると、流れもわかっていい勉強になりますね。