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"
ちょっと時間がなくなってしまったので続きは後日やるか。気が向いたら追記する。