Firebase email-password auth dengan React Native (expo)

Buat dulu sebuah project di firebase https://console.firebase.google.com/u/0/ dengan memilih Add Project

add project

Isikan nama Project, pilih Location, tandai semua pilihan checkbox dan Save Project, lalu akan menuju halaman Dashboard Project atau memilih nama project yang sudah dibuat

Untuk mengaktifkan fitur authentication Email/Password, pada menu sidebar, pilih Authentication, kemudian pada tab Sign-in method pilih provider Email/Password dan enabled, selanjutnya Save

Buat sebuah user pada tab User, dengan memilih tombol Add User, isikan email dan password

Buat sebuah project expo dengan perintah

 expo init firebase-auth

Setting nama aplikasi dan gunakan Yarn jika terinstall, tunggu hingga proses selesai, selanjutnya masuk ke direktori firebase-auth dengan printah

 cd firebase-auth

lakukan instalasi package react-navigation dan firebase dengan perintah

 yarn add firebase react-navigation

Proses authentikasi ini mengikuti alur pada https://reactnavigation.org/docs/en/auth-flow.html dengan sedikit ubahan pada tampilan loginnya. Buat terlebih dahulu folder components, selanjutnya buat file-file berikut pada folder tersebut

  • AuthLoadingScreen.js
  • LoginScreen.js
  • HomeScreen.js
  • Spinner.js

Sekarang ubah App.js dengan script seperti beriku

import React from 'react';
import firebase from "firebase";
import AuthLoadingScreen from "./components/AuthLoadingScreen";
import SignInScreen from "./components/LoginPage";
import HomeScreen from "./components/HomeScreen";
import OtherScreen from "./components/OtherScreen";
import { createSwitchNavigator, createStackNavigator, createAppContainer } from 'react-navigation';

const AppStack = createStackNavigator({ Home: HomeScreen, Other: OtherScreen });
const AuthStack = createStackNavigator({ SignIn: SignInScreen }, { headerMode: 'none' });

const AppContaner =  createAppContainer(createSwitchNavigator(
  {
    AuthLoading: AuthLoadingScreen,
    App: AppStack,
    Auth: AuthStack,
  },
  {
    initialRouteName: 'AuthLoading',
  }
));

export default class App extends React.Component {
  componentWillMount() {
      firebase.initializeApp({
        apiKey: "xxxx",
        authDomain: "xxxx",
        databaseURL: "xxxx",
        projectId: "xxxx",
        storageBucket: "xxxx",
        messagingSenderId: "xxxx"
      });
  }
  
  render() {
    return (
      <AppContaner />
    );
  }
}

perhatikan pada method componentWillMount terdapat firebase.initializeApp({ yang isinya disesuaikan dengan project masing-masing. Data ini diambil dari dashboard Project pada firebase, klik web sehingga muncul konfigurasi project yang sudah dibuat.

AuthLoadingScreen.js digunakan untuk memeriksa user yang login dengan menggunakan observer onAuthStateChanged https://firebase.google.com/docs/auth/web/manage-users , sehingga nantinya jika terdapat user yang login, diarahkan ke halaman Home, jika tidak diarahkan ke halaman Login. Script lengkapnya seperti berikut

import React, { Component } from 'react';
import { View, ActivityIndicator, StatusBar } from 'react-native';
import firebase from "firebase";
export default class AuthLoadingScreen extends Component {
    constructor(props) {
        super(props);
        this._getAuthStateChanged();
    }

    _getAuthStateChanged =  () => {
       firebase.auth().onAuthStateChanged((user)=>{
           if (user) {
               this.props.navigation.navigate('App')
           }else{
               this.props.navigation.navigate('Auth')
           }
       })
    };

    render() {
        return (
            <View>
                <ActivityIndicator />
                <StatusBar barStyle="default" />
            </View>
        );
    }
}

Halaman LoginScreen.js untuk menampilkan dan memproses form login. Sebenarnya isinya adalah halaman login biasa dengan tambahan fungsi signInWithEmailAndPassword yaitu fungsi firebase untuk authentikasi menggunakan email dan password yang diinputkan. Jika proses authentikasi berhasil, maka diarahkan ke halaman Home

import React from 'react';
import { KeyboardAvoidingView, StyleSheet, View, Image, TextInput, Button,Text } from "react-native";
import firebase from "firebase";
import Spinner from "./Spinner";
export default class LoginScreen extends React.Component {
    constructor(props) {
        super(props)
        this.state = { email: '', password: '', error: '', success: '', loading: false };
    }

    _onPressLogin = () => {
        this.setState({ error: '', loading: true });
        const { email, password } = this.state;
        firebase.auth().signInWithEmailAndPassword(email, password)
            .then(data => {
                this.setState({ error: '', success: 'Authentication success!', loading: false });
                this.props.navigation.navigate('App');
                console.log(data.user)
            })
            .catch(e => {
                console.log(e)
                this.setState({ error: 'Authentication failed.', success: '', loading: false });
            });
    }
    _onPressCancel = () => {
        this.setState({ email: '' })
        this.setState({ password: '' })
        this.setState({ error: '', success: '', loading: false });

    }

    renderButtonOrSpinner() {
        if (this.state.loading) {
            return <Spinner />;
        }
        return <Button onPress={this._onPressLogin.bind(this)} title="Log in" />;
    }

    render() {
        return (
            <KeyboardAvoidingView style={styles.container} 
            behavior="padding" enabled >
                <Image source={require('../assets/icon.png')} style={styles.image}></Image>
                <Text style={styles.errorTextStyle}>{this.state.error}</Text>
                <Text style={styles.successTextStyle}>{this.state.success}</Text>
                <TextInput
                    value={this.state.email}
                    onChangeText={(inputan) => this.setState({ email: inputan })}
                    style={styles.email} placeholder="email..."></TextInput>
                <TextInput
                    value={this.state.password}
                    onChangeText={(inputan) => this.setState({ password: inputan })}
                    style={styles.email} placeholder="Password,,," secureTextEntry={true}></TextInput>
                <View style={styles.button}>
                    {this.renderButtonOrSpinner()}
                </View>
                <View style={styles.button}>
                    <Button
                        onPress={this._onPressCancel}
                        title="Cancel"></Button>
                </View>
            </KeyboardAvoidingView>
        )
    };
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: 'skyblue'
    },
    image: {
        width: 120,
        height: 120,
        marginBottom: 40,
    },
    email: {
        backgroundColor: 'white',
        borderRadius: 5,
        width: '90%',
        padding: 5,
        marginBottom: 10,
    },
    button: {
        width: '90%',
        marginBottom: 10,
    },
    errorTextStyle: {
        color: '#E64A19',
        alignSelf: 'center',
        paddingTop: 10,
        paddingBottom: 10,
        fontWeight: 'bold',
    },
    successTextStyle: {
        color: '#33691e',
        alignSelf: 'center',
        paddingTop: 10,
        paddingBottom: 10,
        fontWeight: 'bold',
    }
});

Halaman HomeScreen.js adalah halaman yang tampil setelah login, berisi tombol logout

import React from "react";
import { View, Button, Text} from 'react-native'
import firebase from "firebase";
import Spinner from "./Spinner";
export default class HomeScreen extends React.Component {
    
    static navigationOptions = {
        title: 'Welcome to the app!',
    };

    render() {
        return (
            <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }} >
                <View style={{width:'90%',marginBottom: 10}} >
                <Button title="Actually, sign me out :)" onPress={this._signOut} />
                </View>
            </View>
        );
    }

    _signOut = () => {
        firebase.auth().signOut().then(function () {
            this.props.navigation.navigate('Auth');
        }).catch(function (error) {
            console.log(error)
        });
    };
}

Hasil dari aplikasi dapat dilihat pada video di atas