LoginSignup
18
15

More than 3 years have passed since last update.

Expo + Firebase Auth覚え書き

Last updated at Posted at 2019-10-18

はじめに

Expo + Firebaseで、下記のような一般的な構成のユーザー認証機能を実装してみたいと思います。

  • メールアドレス/パスワードでログイン
  • メールアドレス/パスワードでユーザー新規登録(初めての方)
  • Googleアカウントを使ってログイン
  • ログアウト

1. 基本設定

Firebaseのコンソール画面でWebアプリを追加し、スニペットをコピーしてfirebaseConfigをファイル化しておきます。Githubにアップされないように、今回は.envに記載したものをreact-native-dotenvで読むこむようにします。

.env
FIREBASE_API_KEY=<apiKey>
FIREBASE_AUTH_DOMAIN=<authDomain>
FIREBASE_DATABASE_URL=<databaseURL>
FIREBASE_PROJECT_ID=<projectId>
FIREBASE_STORAGE_BUCKET=<storageBucket>
FIREBASE_MESSAGING_SENDER_ID=<messagingSenderId>
FIREBASE_APP_ID=<appId>
FIREBASE_MEASUREMENT_ID=<measurementId>
firebaseConfig.js
import {
  FIREBASE_API_KEY,
  FIREBASE_AUTH_DOMAIN,
  FIREBASE_DATABASE_URL,
  FIREBASE_PROJECT_ID,
  FIREBASE_STORAGE_BUCKET,
  FIREBASE_MESSAGING_SENDER_ID,
  FIREBASE_APP_ID,
  FIREBASE_MEASUREMENT_ID
} from 'react-native-dotenv';

export default {
  apiKey: FIREBASE_API_KEY,
  authDomain: FIREBASE_AUTH_DOMAIN,
  databaseURL: FIREBASE_DATABASE_URL,
  projectId: FIREBASE_PROJECT_ID,
  storageBucket: FIREBASE_STORAGE_BUCKET,
  messagingSenderId: FIREBASE_MESSAGING_SENDER_ID,
  appId: FIREBASE_APP_ID,
  measurementId: FIREBASE_MEASUREMENT_ID
};

これを使ってクライアント側でfirebaseモジュールを初期化し、
auth()メソッドでAuthクラスのインスタンスを取得します。

firebase.js
import firebase from 'firebase';
import firebaseConfig from './firebaseConfig';

firebase.initializeApp(firebaseConfig);

export const auth = firebase.auth();
export default firebase;

onAuthStateChangedで認証状況が変化したらユーザー情報をstateに保持するようにしておきます。
シンプルなRedux実装に組み込むとしたらこのような感じになるかと思います。

redux.js
auth.onAuthStateChanged((user) => {
  console.log('auth state changed', user);
  const current = store.getState().user.data;
  if (!current && user) {
    store.dispatch({
      type: 'SUCCESS_AUTH_USER',
      data: user
    });
  } else if (current && !user) {
    store.dispatch({
      type: 'SIGN_OUT_USER'
    });
  }
});

2. メールアドレス/パスワードで新規登録

Firebaseのコンソール画面で「開発」→「Authentication」→「ログイン方法」→「ログインプロパイダ」から「メール / パスワード」を有効にします。この画面で有効なログイン方法を設定することができます。
firebase.png

画面コンポーネント内、stateにemailpasswordの値があり、ボタンを押したらauthUserアクションをdipatchするとします。

redux.js
export const authUser = (email, password) => (dispatch) => {
  dispatch({
    type: 'START_AUTH_USER'
  });
  auth.createUserWithEmailAndPassword(email, password)
    .catch(({ message }) => {
      dispatch({
        type: 'FAIL_AUTH_USER',
        message
      });
    });
};

createUserWithEmailAndPasswordメソッドにメールアドレスとパスワードを渡すだけです。
これでユーザーが新規登録され、ユーザーオブジェクト(user)がstateにsetされます。
Firebaseのコンソール画面でユーザーが追加されているのがわかるはずです。

3. ログアウト

FirebaseAuthではデフォルトだと認証状態が保持されるような設定になっています(詳しくはこちら)。
このままでは開発しにくいので、ログアウト機能を先に実装しておきたいと思います。ボタンを押したらsignOutアクションをdispatchするとします。

redux.js
export const signOut = () => (dispatch) => {
  dispatch({
    type: 'START_SIGN_OUT_USER'
  });
  auth.signOut()
    .catch(({ message}) => {
      Alert.alert(message);
    });
};

4. メールアドレス/パスワードでログイン

今度は先ほど作成したユーザーにログインしてみます。こちらも新規登録と同様に、

redux.js
export const signIn = (email, password) => (dispatch) => {
  dispatch({
    type: 'START_AUTH_USER'
  });
  auth.signInWithEmailAndPassword(email, password)
    .catch(({ message}) => {
      dispatch({
        type: 'FAIL_AUTH_USER',
        message
      });
    });
};

ここまでは非常に簡単です。

5. Googleアカウントを使用してログイン

Googleログインについては2019年10月現在、2通りの方法がありますが、最新の方法はExpoClientでの開発に対応していませんので、ひとまず非推奨の旧式の方法を紹介します。

こちらの方法はFirebaseでは完結せず、Developpers Consoleでプロジェクトを作成し、認証情報を追加する必要があります。
「認証情報」タブ→「認証情報を作成」→「OAuthクライアントID」を選択しクライアントIDを作成します。Androidの場合はパッケージ名を、iOSの場合はバンドルIDhost.exp.exponentと入力します。
googleclientid.png

作成したクライアントIDはJSから使用するので、.envファイルに追記しておきます。

GOOGLE_AUTH_IOS_CLIENT_ID=<IOS_CLIENT_ID>
GOOGLE_AUTH_ANDROID_CLIENT_ID=<ANDROID_CLIENT_ID>

また、「OAuth同意画面」タブから最低限サポートメールアドレスを設定しておきましょう。これがないと認証エラーが発生します。
google.png

ではアプリ側です。
認証に必要なexpo-google-app-authモジュールをインストールします。

$ yarn add expo-google-app-auth

authGoogleアクションをdispatchするとして、実装してみます。

redux.js
import Google from 'expo-google-app-auth';

export const authGoogle = () => (dispatch) => {
  dispatch({
    type: 'START_AUTH_USER'
  });
  Google.logInAsync({
    behavior: 'web',
    iosClientId: GOOGLE_AUTH_IOS_CLIENT_ID,
    androidClientId: GOOGLE_AUTH_ANDROID_CLIENT_ID,
    scopes: ['profile', 'email']
  }).then((result) => {
    if (result.type === 'success') {
      const { idToken, accessToken } = result;
      const credential = firebase.auth.GoogleAuthProvider.credential(idToken, accessToken);
      auth.signInWithCredential(credential)
        .catch(({ message }) => {
          dispatch({
            type: 'FAIL_AUTH_USER',
            message
          });
        });
    } else {
      dispatch({
        type: 'FAIL_AUTH_USER',
        message: result.type
      });
    }
  }).catch(({ message }) => {
      dispatch({
        type: 'FAIL_AUTH_USER',
        message
      });
    });
};

実行すると、アプリ画面にはダイアログが表示された後Googleのログイン画面が表示されます。
これでGoogleアカウントと作成したAuthユーザー(既存ユーザーでも)が紐づけられます。

Github

Authenticationを含め、メールアドレス・電話番号認証やFirestoreなども使用したサンプル
https://github.com/mildsummer/expo-auth-practice

参考

Getting started with Firebase Authentication on React Native
Firebaseアプリをデプロイ後、Googleログインしようとすると403エラーがてたときの対処方法。

18
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
15