Expo + ReactNativeで認証機能の実装を試してみる。本当はTwitter認証を実装したいんだけど、公式の情報がFacebook認証だったので、まずはFacebook認証を実装する。
プロジェクトを準備
まずは空っぽのプロジェクトを初期化する。テンプレートはblankを選択。
$ expo init ExpoFirebaseAuth
アプリケーションを起動してみる。
$ cd ExpoFirebaseAuth $ yarn start
ここまではいつもどおりなので楽勝。
FirebaseとFacebook側の設定
認証用にFacebookアプリを登録する。細かい手順は省く。
https://developers.facebook.com/apps/
設定 -> ベーシックで表示されているアプリIDとapp secretをメモっておく。
Firebaseプロジェクトも登録しておく。 https://console.firebase.google.com/u/0/
Authentication -> Sign-in method画面でFacebookを有効にして、Facebookアプリから取得したアプリケーションIDとアプリシークレットを設定する。
OAuthリダイレクトURIが表示されているので、これをFacebook側に設定する。
Facebookログイン -> 設定 -> 有効なOAuthリダイレクトURI
認証機能を実装する
公式の情報はここだが、若干わかりづらい。
https://docs.expo.io/guides/using-firebase/
この辺のエントリも参考にした。
- https://qiita.com/mizchi/items/d21b792e1b9ca5a00546
- https://mozy-ok.hatenablog.com/entry/2019/02/23/190135
まずは必要なパッケージをインストールする。yarnやnpmではなくexpo install
を使うことでexpoに対応したバージョンを入れてくれるらしい。
最新のfirebaseパッケージでexpoを動かすとエラーになってしまうが、その辺を気にしなくて済む。
$ expo install firebase expo-facebook
App.tsx
import React, { Component } from 'react'; import * as Facebook from 'expo-facebook'; import { StyleSheet, Button, View } from 'react-native'; import firebaseApp from './firebase'; import * as firebase from 'firebase'; // Listen for authentication state to change. firebaseApp.auth().onAuthStateChanged((user) => { console.log(user); if (user != null) { console.log("We are authenticated now!"); } // Do other things }); export default class App extends Component { async loginWithFacebook() { await Facebook.initializeAsync( '<FACEBOOK_APP_ID>', ); const { type, token } = await Facebook.logInWithReadPermissionsAsync( { permissions: ['public_profile'] } ); if (type === 'success') { // Build Firebase credential with the Facebook access token. const credential = firebase.auth.FacebookAuthProvider.credential(token); // Sign in with credential from the Facebook user. firebaseApp.auth().signInWithCredential(credential).catch((error) => { console.log(error) // Handle Errors here. }); } } render() { return ( <View style={styles.container}> <Button title="Sign in with Facebook" onPress={ this.loginWithFacebook } /> </View> ) } } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#fff', alignItems: 'center', justifyContent: 'center', }, });
firebase.ts
import * as firebase from 'firebase'; // Initialize Firebase const firebaseConfig = { apiKey: "<API_KEY>", authDomain: "<AUTH_DOMAIN>", databaseURL: "<DATABASE_URL>", projectId: "<PROJECT_ID>", storageBucket: "<STORAGE_BUCKET>", messagingSenderId: "<MESSAGING_SENDER_ID>", appId: "<APP_ID>" }; const firebaseApp = firebase.initializeApp(firebaseConfig); export default firebaseApp
解決済みだけどこのエラーにハマった。
Unhandled promise rejection: TypeError: undefined is not an object (evaluating '_firebase.default.auth.FacebookAuthProvider.credential')
下記によると、FacebookAuthProvider
はstaticなメンバらしく、初期化されたfirebaseApp
インスタンスを使用してfirebaseApp.auth.FacebookAuthProvider
と記述しても動かない。
https://stackoverflow.com/questions/52203891/expo-firebase-auth-provider-is-undefined
そこをクリアしたらまた次のエラーにハマった。あちこち設定を変えてみても全然解決せずに困った。
Error: Unsuccessful debug_token response from Facebook: {"error":{"message":"(#100) The App_id in the input_token did not match the Viewing App","type":"OAuthException","code":100,"fbtrace_id":"ABE3G467m_GWeSVlBcrCBIj"}}
下記エントリのおかげでようやく原因がわかった。なんと、Facebook認証をしようとしたときに、自分が設定したFacebookアプリのAPP_IDではなく、ExpoクライアントアプリのAPP_IDが飛んでしまうそうな。
どないなっとんねん。Expo37からの変更点って書いてあるのでバージョン下げれば動くのかな。まだ試してない。
https://qrunch.net/@katsukiniwa/entries/SFko1lS4jGtcgEAS?ref=qrunch
これを回避するには、開発モードではなくstandaloneモードでビルドすれば良いらしい。
app.json
{ "expo": { "name": "HelloWorld", "slug": "ExpoFirebaseAuth", "platforms": [ "ios", "android", "web" ], "version": "1.0.0", "orientation": "portrait", "icon": "./assets/icon.png", "splash": { "image": "./assets/splash.png", "resizeMode": "contain", "backgroundColor": "#ffffff" }, "updates": { "fallbackToCacheTimeout": 0 }, "assetBundlePatterns": [ "**/*" ], "ios": { "supportsTablet": true, "bundleIdentifier": "com.expofirebase.auth", "buildNumber": "1.0.0" } } }
ビルドしてみる。
$ expo build:ios
Authentication with Apple Developer Portal failed! Reason: Unknown reason, raw: "Unauthorized Access"
ちょっと時間がなくなってしまったので続きは後日やるか。気が向いたら追記する。