React Native + Firebaseのログイン機能の実装(メールアドレスと電話番号)
どうも、サトウダイキです。
今日はReact NativeでのFirebaseのログインの実装について書いていきます。4つの方法を実装していきます。
- メールアドレス
- 電話番号
- Facebookアカウント
- Googleアカウント
この記事ではメールアドレスと電話番号について書きます。続きはこちらで。
https://blog.hatena.ne.jp/ducklingsinc/ducklings.hateblo.jp/edit
※Expoを利用しています。Versionは36です。2020年2月の時の実装です。
メールアドレス
まずはメールアドレスとパスワードのログインから実装していきます。
Firebaseの設定
Firebaseのプロジェクを作成します。
下記URLからFirebaseプロジェクトを作成します。
ログイン - Google アカウント
画面の指示通り進めていけば作成できます。
[Authentication]→[ログイン方法]→[メール / パスワード] の順でクリック。 有効にするにタブを移動します。メールリンク(パスワードなしでログイン)も有効にしてもOKです。
続いて、アプリの作成を行います。
[Project Overview] → [アプリを追加] → [Web]をクリック
アプリ名を入力して「アプリを登録」をクリック
firebaseConfigを値をコピーしておきます。これでWebブラウザでのFirebase側の設定は終わりです。
コードの実装
ここからはコーディングです。
ターミナルを立ち上げて、firebaseをinstallします。
色々な記事を読むと、react-native-firebaseを使っているコードと、firebaseを使っているコードがあります。どちらでも実装できますが、今回はfirebaseを使います。
react-native-firebase - npm
firebase - npm
yarn add firebase
configファイルの実装
次にconfigファイルを作成します。
src/configs/firebase.js
import firebase from 'firebase'; export const firebaseConfig = { apiKey: '----', authDomain: ----', databaseURL: ----', projectId: ----', storageBucket: ----', messagingSenderId: ----', appId: ----', measurementId: ----', }; export default firebase;
※ ----の部分はfirebaseは自身のfirebaseアプリの設定をしてください。 先ほどコピーしたfirebaseConfigの値を貼り付けます。
ロジックの実装
ロジック部分のコードです。
src/utils/auth.ts
import firebase from '../configs/firebase'; // メールアドレスでユーザ登録 export const emailSignUp = (email: string, password: string): void => { firebase .auth() .createUserWithEmailAndPassword(email, password) .then(user => { if (user) { console.log('Success to Signup'); } }) .catch(error => { console.log(error); }); }; export default firebase;
firebaseが予め用意している、createUserWithEmailAndPasswordにemailとpasswordを渡すだけです。
UIの実装
src/utils/auth.ts
import React, { useState } from 'react'; import { View, StyleSheet, TextInput, Button } from 'react-native'; import { emailSignUp, } from '../utils/auth'; const styles = StyleSheet.create({ container: { flex: 1, alignItems: 'center', justifyContent: 'center', padding: 16, }, textInput: { fontSize: 14, color: 'black', width: '100%', borderBottomWidth: 1, borderBottomColor: 'black', margin: 16, }, }); const SignUpScreen: React.FC = (): JSX.Element => { const [email, setEmail] = useState(); const [password, setPassword] = useState(); return ( <View style={styles.container}> <TextInput style={styles.textInput} value={email} onChangeText={(text: string): void => setEmail(text)} editable maxLength={50} placeholder="Email" autoCapitalize="none" keyboardType="email-address" returnKeyType="done" /> <TextInput style={styles.textInput} value={password} onChangeText={(text: string): void => setPassword(text)} editable maxLength={20} placeholder="Password" autoCapitalize="none" secureTextEntry returnKeyType="done" /> <Button title="登録" onPress={(): void => emailSignUp(email, password)} /> </View> ); }; export default SignUpScreen;
特別、難しい処理は何もしていないです。これで終わりです。
確認
シミュレータを立ち上げ、メールアドレスとパスワードを入力して、登録ボタンを押します。
正しく設定されると、firebaseにユーザが登録されています。これでメールアドレスでの登録は完了です。
電話番号登録
続いて電話番号を使ったログイン方法についてです。
Webブラウザのfirebaseに移動して、Authenticationから電話番号を有効にします。
テスト用の電話番号はまだ登録しないで大丈夫です。これは、1度成功した後にログインの動作を省くために使います。
承認済みドメインの追加
そのまま画面を下にスクロールしていき、[認証済ドメイン]の設定を行います。これ設定忘れるとハマりますので、注意してください。設定する値は、IPアドレスです。
reCAPTYACの設定
電話番号のログインの実装にはreCAPTYACが必要です。これはfirebaseへの不正のログインを防ぐためです。
reCAPTYACとは、「私はロボットではありません」といったあれです。
ただ、2020年2月時点では、React NativeとFirebaseでのreCAPTYACをうまい具合にやってくれるものが用意されていないので、自分で実装するしかありません。ということで、実際に作っていきます。
まずはターミナルを立ち上げfirebase-toolsをインストールします。
npm install -g firebase-tools firebase login
続いて、実装中のアプリのカレントディレクトに移動して、下記を実行。
firebase init
initiを押した後、上下方向キーを使い、hostingを選択し、スペースを押下
? What do you want to use as your public directory? (public) と聞かれたので、(これは皆さんの好きな場所でokです)
? Which project do you want to add? 対処のプロジェクト
? Configure as a single-page app (rewrite all urls to /index.html)? (y/N) これを一旦y
すると下記が自動で生成されます。
- firebase.json
- .firebaserc
- public/index.html
captchaの実装
public/captcha.htmlを新規作成します。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Welcome to Firebase Hosting</title> <!-- update the version number as needed --> <script defer src="/__/firebase/7.8.0/firebase-app.js"></script> <!-- include only the Firebase features as you need --> <script defer src="/__/firebase/7.8.0/firebase-auth.js"></script> <script defer src="/__/firebase/7.8.0/firebase-database.js"></script> <script defer src="/__/firebase/7.8.0/firebase-messaging.js"></script> <script defer src="/__/firebase/7.8.0/firebase-storage.js"></script> <!-- initialize the SDK after all desired features are loaded --> <script defer src="/__/firebase/init.js"></script> <style media="screen"> body { background: #ECEFF1; color: rgba(0,0,0,0.87); font-family: Roboto, Helvetica, Arial, sans-serif; margin: 0; padding: 0; } </style> </head> <body> <p>Please, enter captcha for continue<p/> <button id="continue-btn" style="display:none">Continue to app</button> <script> function getToken(callback) { const containerId = 'captcha'; const container = document.createElement('div'); container.id = containerId; document.body.appendChild(container); var captcha = new firebase.auth.RecaptchaVerifier(containerId, { 'size': 'normal', 'callback': function(token) { callback(token); }, 'expired-callback': function() { callback(''); } }); captcha.render().then(function() { captcha.verify(); }); } function sendTokenToApp(token) { const baseUri = decodeURIComponent(location.search.replace(/^\?appurl\=/, '')); const finalUrl = location.href = baseUri + '/?token=' + encodeURIComponent(token); const continueBtn = document.querySelector('#continue-btn'); continueBtn.onclick = function() { window.open(finalUrl, '_blank'); }; continueBtn.style.display = 'block'; } document.addEventListener('DOMContentLoaded', function() { getToken(sendTokenToApp); }); </script> </body> </html>
よりfirebaseのバージョン部分はindex.htmlと同一のを使ってください。
ターミナルを立ち上げてデプロイします。
firebase deploy
成功するとfirebaseのコンソールでこんな感じになります。
パッケージのインストール
さて、ここからは実装に入ります。まずは必要なものをインストールします。
yarn add expo yarn add expo-web-browser
ロジックの実装
auth.tsに電話番号ログイン処理を追記します。
import { Linking } from 'expo'; import * as WebBrowser from 'expo-web-browser'; // 電話番号で登録 export const phoneSignUp = async ( phoneNumber: string ): Promise<firebase.auth.ConfirmationResult | null> => { const captchaUrl = `https://APPNAME.firebaseapp.com/captcha.html?appurl=${Linking.makeUrl( '' )}`; let token: string | null = null; const listener = ({ url }): void => { WebBrowser.dismissBrowser(); const tokenEncoded = Linking.parse(url).queryParams.token; if (tokenEncoded) token = decodeURIComponent(tokenEncoded); }; Linking.addEventListener('url', listener); await WebBrowser.openBrowserAsync(captchaUrl); Linking.removeEventListener('url', listener); if (token) { // fake firebase.auth.ApplicationVerifier const captchaVerifier = { type: 'recaptcha', verify: () => Promise.resolve(token), }; try { const confirmationResult = await firebase .auth() .signInWithPhoneNumber(phoneNumber, captchaVerifier); return confirmationResult; } catch (e) { console.warn(e); return null; } } return null; };
※APPNAMEの箇所は書き換えが必要です。
UIの実装
SignUpScreen.tsxを追記します。
import { emailSignUp, *phoneSignUp* } from '../utils/auth'; ---中略--- const [phoneNumber, setPhoneNumber] = useState(''); const [confirmResult, setConfirmResult] = useState(null); const onPressPhoneSignUp = async (): Promise<void> => { const result = await phoneSignUp(phoneNumber); if (result) { setConfirmResult(result); navigation.navigate('VerificationCode', { confirmResult: result }); } else { console.log('error'); } }; ---中略--- <TextInput style={styles.textInput} value={phoneNumber} onChangeText={(text: string): void => setPhoneNumber(text)} editable maxLength={50} placeholder="Phone" autoCapitalize="none" keyboardType="phone-pad" returnKeyType="done" /> <Button title="PhoneSignUp" onPress={onPressPhoneSignUp} /></b>
VerificationCodeScreen
import React, { useState } from 'react'; import { View, Text, StyleSheet, TextInput, Button } from 'react-native'; import { NavigationStackProp } from 'react-navigation-stack'; const styles = StyleSheet.create({ container: { flex: 1, alignItems: 'center', justifyContent: 'center', padding: 16, }, textInput: { fontSize: 14, color: 'black', width: '100%', borderBottomWidth: 1, borderBottomColor: 'black', margin: 16, }, }); const VerificationCodeScreen: React.FC<{ navigation: NavigationStackProp }> = ({ navigation, }): JSX.Element => { const [code, setCode] = useState(''); const onPressConfirmCode = (): void => { if (code.length) { const { params = {} } = navigation.state; params.confirmResult .confirm(code) .then(user => { console.log('Code Confirmed!'); }) .catch(error => console.log(`Code Confirm Error: ${error.message}`)); } }; return ( <View style={styles.container}> <Text>Enter verification code below:</Text> <TextInput style={styles.textInput} value={code} onChangeText={(value): void => setCode(value)} editable maxLength={50} placeholder="Code" autoCapitalize="none" keyboardType="numeric" returnKeyType="done" /> <Button title="Confirm Code" color="#841584" onPress={onPressConfirmCode} /> </View> ); }; export default VerificationCodeScreen;
電話番号を入力して、登録を押す→入力した電話番号に確認コードが飛ぶ。確認コードを入力。こういった流れになります。
電話番号は国際コードから入れなければいけません。また先頭の0も消します。080-1234-5678だとしたら、+818012345678と入力します。
今回はここまで。次回はFacebookログインと、Googleログインについて書いていきます。
続きはこちら
https://tech.maricuru.com/entry/2020/02/09/212813 tech.maricuru.com