Kosaku Kurino

Kosaku Kurino

【React Native】ExpoでFirebase AuthenticationのSNS認証を利用する方法

まえがき

CRNA(create-react-native-app)で作成したアプリケーションで、Firebase AuthenticationのSNS認証を行う方法をまとめます。 →こちらで紹介しているGoogleの認証方法はExpo側で廃止予定なようです。。。

GoogleアカウントとFacebookアカウントでのSNS認証を解説します。

準備

npm install create-react-native-app -g
create-react-native-app firebaseAuthSample
cd firebaseAuthSample
npm install firebase --save

Facebook認証

Facebook - Expo Documentationに実装の仕方が書かれています。

流れとして、Expo Client AppでFacebook認証を利用できるよう設定し、Expo APIで取得できるトークンでクレデンシャルを作成し、作成したクレデンシャルでログインを行います。

1. Facebook for DeveloperでIOSのBundle IDとAndroidのKey Hashesを登録する

Facebook for Developersでアプリを作成し、設定のベーシックからIOSのBundle IDAndroidのKey Hashesを登録しましょう。

IOSのBundle IDはhost.exp.Exponent、AndroidのKey HashesはrRW++LUjmZZ+58EbN5DVhGAnkX4=です。

アプリIDはあとで使うので、メモしておきましょう。

2. Firebase consoleでIOSアプリとAndroidアプリを登録する

Firebase console で「+アプリを追加」からIOSアプリとAndroidアプリを追加し、IOSアプリのバンドルIDAndroidアプリのパッケージ名host.exp.exponentを登録しましょう。

スクリーンショット 2019-01-16 1.09.52.png

3. Facebook認証を実装する

どこからでもすぐ呼び出せる用、認証処理を関数化して実装します。 Expo APIでトークンを取得、Firebase APIでトークンからクレデンシャルを取得、Firebase APIでクレデンシャルを利用してFacebook認証をさせます。

import * as firebase from 'firebase'
import * as Expo from 'expo'

const FACEBOOK_APPID = '<app id>'

const config = {
  apiKey: '<api key>',
  authDomain: '<domain>',
  databaseURL: '<database url>',
  projectId: '<project id>',
  storageBucket: '<sotarge bucket>',
  messagingSenderId: '<id>'
}

firebase.initializeApp(config)

export const authFacebook = async () => {
  try {
    const { type, token } = await Expo.Facebook.logInWithReadPermissionsAsync(
      FACEBOOK_APPID,
      { permissions: ['public_profile'] }
    )

    if (type === 'success') {
      const credential = firebase.auth.FacebookAuthProvider.credential(token)
      return firebase.auth().signInAndRetrieveDataWithCredential(credential).catch((error) => console.log(error))
    }
    else {
      return { cancelled: true }
    }
  }
  catch (e) {
    return { error: true }
  }
}

Expo APIのExpo.Facebook.loginWithReadPermissionsAsync(appId, options)で先ほどメモしたアプリIDを使用して、「token」と「type」を取得します。

※「type」には認証結果が入ります。

const { type, token } = await Expo.Facebook.logInWithReadPermissionsAsync(
  FACEBOOK_APPID,
  { permissions: ['public_profile'] }
)

「type」で認証結果をチェックして、Firebase APIのfirebase.auth.FacebookAuthProvider.credential(token)で「token」を使用して、「credential」を取得します。

Firebase APIのfirebase.auth().signInAndRetrieveDataWithCredential(credential)で「credential」を使用して、Facebook認証処理を走らせます。

if (type === 'success') {
  const credential = firebase.auth.FacebookAuthProvider.credential(token)
  return firebase.auth().signInAndRetrieveDataWithCredential(credential).catch((error) => console.log(error))
}
else {
  return { cancelled: true }
}

Google認証

Google - Expo Documentationに実装の仕方が書かれています。

流れとして、Expo Client AppでGoogle認証を利用できるよう設定し、Expo APIで取得できるトークンでクレデンシャルを作成し、作成したクレデンシャルでログインを行います。

Facebook認証の時と同じ手順です。

1. Google Developer ConsoleでIOSのバンドルIDとAndroidのパッケージ名を登録する

Google Developer Consoleで「認証情報を作成」→「OAuth クライアント ID」にてIOSのバンドルIDAndroidのパッケージ名を登録する。

IOS用とAndroid用にOAuth クライアント IDを2つ作成してください。

スクリーンショット 2019-01-16 1.30.43.png

IOS(OAuth クライアント ID)のバンドルIDとAndroid(OAuth クライアント ID)のパッケージ名はhost.exp.exponentです。

また、Android(OAuth クライアント ID)には署名証明書フィンガープリントの項目があるので、ターミナルでopenssl rand -base64 32 | openssl sha1 -cを実行し、表示された文字を入力してください。

IOSとAndroidのクライアントIDはあとで使うので、メモしておきましょう。

署名証明書フィンガープリントはA1:B2:C3...のような形式です。

2. Firebase consoleでIOSアプリとAndroidアプリを登録する

こちらはFacebook認証の2. Firebase consoleでIOSアプリとAndroidアプリを登録すると全く同じなので省略します。

※Facebook認証実装の際すでにアプリを登録しているのであれば、スキップして大丈夫です。

3. Google認証を実装する

どこからでもすぐ呼び出せる用、認証処理を関数化して実装します。 Expo APIでトークンを取得、Firebase APIでトークンからクレデンシャルを取得、Firebase APIでクレデンシャルを利用してGoogle認証をさせます。

※Facebook認証の時と仕組みは変わりません。

import * as firebase from 'firebase'
import * as Expo from 'expo'

const GOOGLE_IOS_CLIENTID = '<google ios client id>'
const GOOGLE_ANDROID_CLIENTID = '<google android client id>'

const config = {
  apiKey: '<api key>',
  authDomain: '<domain>',
  databaseURL: '<database url>',
  projectId: '<project id>',
  storageBucket: '<sotarge bucket>',
  messagingSenderId: '<id>'
}

firebase.initializeApp(config)

export const authGoogle = async () => {
  try {
    const { type, idToken, accessToken } = await Expo.Google.logInAsync({
      behavior: 'web',
      iosClientId: GOOGLE_IOS_CLIENTID,
      androidClientId: GOOGLE_ANDROID_CLIENTID,
      scopes: ['profile', 'email'],
    })

    if (type === "success") {
      const credential = firebase.auth.GoogleAuthProvider.credential(idToken, accessToken)
      return firebase.auth().signInAndRetrieveDataWithCredential(credential).catch((error) => console.log(error))
    }
    else {
      return { cancelled: true }
    }
  }
  catch (e) {
    return { error: true }
  }
}

Expo APIのExpo.Google.logInAsync(options)で先ほどメモしたIOSのクライアントIDとAndroidのクライアントIDを使用して、「idToken」と「accessToken」と「type」を取得します。

※「type」には認証結果が入ります。

const { type, idToken, accessToken } = await Expo.Google.logInAsync({
  behavior: 'web',
  iosClientId: GOOGLE_IOS_CLIENTID,
  androidClientId: GOOGLE_ANDROID_CLIENTID,
  scopes: ['profile', 'email'],
})

「type」で認証結果をチェックして、Firebase APIのfirebase.auth.GoogleAuthProvider.credential(idToken, accessToken)で「idToken」と「accessToken」を使用して、「credential」を取得します。

Firebase APIのfirebase.auth().signInAndRetrieveDataWithCredential(credential)で「credential」を使用して、Google認証処理を走らせます。

if (type === "success") {
  const credential = firebase.auth.GoogleAuthProvider.credential(idToken, accessToken)
  return firebase.auth().signInAndRetrieveDataWithCredential(credential).catch((error) => console.log(error))
}
else {
  return { cancelled: true }
}

まとめ

ExpoでFirebase AuthenticationのSNS認証を実装するときは、Expo APIで各プロバイダーのトークンを取得し、Firebase APIでトークンからクレデンシャルを取得して、クレデンシャルにて認証させれば実装できるみたいです。