Autenticando usuários com Firebase e React
Descubra como o Firebase pode facilitar a integração de usuários.
O Firebase fornece serviços de autenticação que permitem registrar e fazer login de usuários com facilidade. Você pode usar e-mail, senhas, números de telefone e provedores de identidade como Google e Facebook.
Neste tutorial, você aprenderá como usar o Firebase Authentication no React para autenticar usuários usando e-mail e senha. Você armazenará os dados do usuário coletados no Firestore, um banco de dados NoSQL em nuvem também do Firebase.
Observe que este tutorial usa Firebase v9 e React Router v6.
Crie um aplicativo Firebase
Para conectar seu aplicativo ao Firebase, registre-o no Firebase para obter um objeto de configuração. Isto é o que você usará para inicializar o Firebase em seu aplicativo React.
Para criar um aplicativo Firebase, siga as etapas a seguir.
- Acesse o console do Firebase e clique em Criar um projeto.
- Dê um nome ao seu projeto e clique em criar para iniciar o processo.
- Clique no ícone Web (>) na página de visão geral do seu projeto para registrar o aplicativo.
- Dê ao seu aplicativo um nome de sua preferência e clique em Registrar aplicativo. Você não precisa ativar o Firebase Hosting.
- Copie o objeto de configuração em Adicionar SDK do Firebase.
Crie um aplicativo React
Use create-react-app para criar um aplicativo React.
npx create-react-app react-auth-firebase
Navegue até a pasta e inicie o aplicativo.
cd react-auth-firebase
npm run start
Autenticar usuários com funções do Firebase
Antes de usar o Firebase, instale-o.
npm i firebase
Crie um novo arquivo, firebase.js e inicialize o Firebase.
import { initializeApp } from "firebase/app";
const firebaseConfig = {
apiKey: <api_key>,
authDomain:<auth_domain> ,
projectId: <project_id>,
storageBucket: <storage_bucket>,
messagingSenderId: <messaging_sender_id>,
appId: <app_id>
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
Use o objeto de configuração que você copiou ao registrar o aplicativo.
Em seguida, importe os módulos do Firebase que você usará.
import {
getAuth,
createUserWithEmailAndPassword,
signInWithEmailAndPassword,
signOut,
} from "firebase/auth";
import { getFirestore, addDoc, collection } from "firebase/firestore";
const db = getFirestore();
const auth = getAuth();
Para autenticar usuários, você precisa criar três funções: signUp, signIn e signOut.
A função signUp passa o e-mail e a senha para createUserWithEmailAndPassword para registrar um novo usuário. createUserWithEmailAndPassword retorna os dados do usuário que você usará para criar um novo registro de usuário no banco de dados.
const signUp = async (email, password) => {
try {
const userCredential = await createUserWithEmailAndPassword(
auth,
email,
password
);
const user = userCredential.user;
await addDoc(collection(db, "users"), {
uid: user.uid,
email: user.email,
});
return true
} catch (error) {
return {error: error.message}
}
};
Observe que você não está verificando se o e-mail já está em uso antes do registro porque o Firebase cuida disso para você.
A seguir, na função signIn passe o e-mail e a senha para a função signInWithEmailAndPassword para fazer login de um usuário cadastrado.
const signIn = async (email, password) => {
try {
const userCredential = await signInWithEmailAndPassword(
auth,
email,
password
);
const user = userCredential.user;
return true
} catch (error) {
return {error: error.message}
}
};
As funções signUp e signOut retornam true se forem bem-sucedidas e uma mensagem de erro se ocorrer um erro.
A função signOut é bastante simples. Ele chama a função signOut() do Firebase.
const signOut = async() => {
try {
await signOut(auth)
return true
} catch (error) {
return false
}
};
Crie formulários de reação
Os formulários de login e inscrição coletarão o e-mail e a senha do usuário.
Crie um novo componente Signup.js e adicione o seguinte.
import { useState } from "react";
import { Link } from "react-router-dom";
import { signUp } from "./firebase";
const Signup = () => {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [error, seterror] = useState("");
const handleSubmit = async (e) => {
e.preventDefault();
if (password !== password2) {
seterror("Passwords do not match");
} else {
setEmail("");
setPassword("");
const res = await signUp(email, password);
if (res.error) seterror(res.error)
}
};
return (
<>
<h2>Sign Up</h2>
<div>
{error ? <div>{error}</div> : null}
<form onSubmit={handleSubmit}>
<input
type="email"
name="email"
value={email}
placeholder="Your Email"
required
onChange={(e) => setEmail(e.target.value)}
/>
<input
type="password"
name="password"
value={password}
placeholder="Your Password"
required
onChange={(e) => setPassword(e.target.value)}
/>
<button type="submit">Submit</button>
</form>
<p>
already registered? <Link to="/login">Login</Link>
</p>
</div>
</>
);
};
export default Signup;
Aqui você está criando um formulário de inscrição e monitorando o e-mail e a senha usando o estado. Depois de enviar o formulário, o evento onSubmit aciona a função handleSubmit() que chama a função signUp() de firebase.js . Se a função retornar um erro, atualize o estado do erro e exiba a mensagem de erro.
Para o formulário de login, crie Signin.js e adicione o seguinte.
import { useState } from "react";
import { signIn } from "./firebase";
const Login = () => {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [error, seterror] = useState("");
const handleSubmit = async (e) => {
e.preventDefault();
setEmail("");
setPassword("");
const res = await signIn(email, password);
if (res.error) seterror(res.error);
};
return (
<>
{error ? <div>{error}</div> : null}
<form onSubmit={handleSubmit}>
<input
type="text"
name="email"
value={email}
placeholder="Your Email"
onChange={(e) => setEmail(e.target.value)}
/>
<input
type="password"
name="password"
value={password}
placeholder="Your Password"
onChange={(e) => setPassword(e.target.value)}
/>
<input type="submit" value="submit" />
</form>
</>
);
};
export default Login;
O formulário de login é bastante semelhante à página de inscrição, exceto que o envio chama a função signIn().
Por último, crie a página de perfil. Esta é a página para a qual o aplicativo redirecionará os usuários após a autenticação bem-sucedida.
Crie Profile.js e adicione o seguinte.
import { signOut } from "./firebase";
const Profile = () => {
const handleLogout = async () => {
await signOut();
};
return (
<>
<h1>Profile</h1>
<button onClick={handleLogout}>Logout</button>
</>
);
};
export default Profile;
Neste componente, você tem o título Perfil e o botão de logout. O manipulador onClick no botão aciona a função handleLogout que desconecta o usuário.
Crie rotas de autenticação
Para veicular as páginas que você criou no navegador, configure react-router-dom.
Instale react-router-dom:
npm i react-router-dom
Em index.js, configure react-router-dom:
import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import App from "./App";
import Login from "./Login";
import Profile from "./Profile";
ReactDOM.render(
<React.StrictMode>
<BrowserRouter>
<AuthProvider>
<Routes>
<Route path="/" element={<App />} />
<Route path="login" element={<Login />} />
<Route path="profile" element={<Profile />} />
</Routes>
</AuthProvider>
</BrowserRouter>
</React.StrictMode>,
document.getElementById("root")
);
Até este ponto, o aplicativo pode registrar um usuário, inscrevê-lo e desconectá-lo. Então, como você sabe se um usuário está logado ou não?
Na próxima seção deste tutorial, você verá como usar o contexto React para monitorar o status de autenticação de um usuário no aplicativo.
Gerenciar autenticação com React Context API
React Context é uma ferramenta de gerenciamento de estado que simplifica o compartilhamento de dados entre aplicativos. É uma alternativa melhor à perfuração de suporte, onde os dados passam pela árvore de pai para filho até chegarem ao componente que precisa deles.
Criar contexto de autenticação
Na pasta src, adicione o arquivo AuthContext.js e crie e exporte AuthContext.
import { createContext } from "react";
const AuthContext = createContext();
export default AuthContext;
Em seguida, crie o provedor em AuthProvider.js. Isso permitirá que os componentes usem AuthContext.
import { getAuth, onAuthStateChanged } from "firebase/auth";
import { useState, useEffect } from 'react';
import AuthContext from './AuthContext'
const auth = getAuth()
export const AuthProvider = ({ children }) => {
const [user, setUser] = useState(null);
useEffect(() => {
onAuthStateChanged(auth,(user) => {
setUser(user)
})
}, []);
return (
<AuthContext.Provider value={{ user }}>{children}</AuthContext.Provider>
);
};
Aqui, você obtém o valor do usuário usando o método onAuthStateChanged() do Firebase. Este método retorna um objeto de usuário se autenticar o usuário e nulo se não puder. Usando o gancho useEffect(), o valor do usuário é atualizado cada vez que o status de autenticação muda.
Em index.js, envolva as rotas com AuthProvider para garantir que todos os componentes acessem o usuário no contexto:
import { AuthProvider } from "./AuthProvider";
ReactDOM.render(
<React.StrictMode>
<BrowserRouter>
<AuthProvider>
<Routes>
<Route path="/" element={<App />} />
<Route path="login" element={<Login />} />
<Route path="profile" element={<Profile />} />
</Routes>
</AuthProvider>
</BrowserRouter>
,
</React.StrictMode>,
document.getElementById("root")
);
Crie rotas protegidas
Para proteger rotas confidenciais, verifique o status de autenticação de um usuário que tenta navegar para uma página protegida como a página de perfil.
Modifique Profile.js para redirecionar um usuário se ele não estiver autenticado.
import { useContext } from "react";
import AuthContext from "./AuthContext";
import { useNavigate, Navigate } from "react-router-dom";
import { signOut } from "./firebase";
const Profile = () => {
const { user } = useContext(AuthContext);
const navigate = useNavigate();
const handleLogout = async () => {
await signOut();
};
if (!user) {
return <Navigate replace to="/login" />;
}
return (
<>
<h1>Profile</h1>
<button onClick={handleLogout}>Logout</button>
</>
);
};
export default Profile;
O aplicativo renderiza condicionalmente a página de perfil redirecionando o usuário para a página de login se ele não estiver autenticado.
Indo além com a autenticação Firebase
Neste tutorial, você usou o Firebase para autenticar usuários usando email e senha. Você também criou registros de usuário no Firestore. O Firebase fornece funções para trabalhar com provedores de autenticação como Google, Facebook e Twitter.