├── public
├── robots.txt
├── favicon.ico
├── logo192.png
├── logo512.png
├── manifest.json
└── index.html
├── src
├── index.js
├── components
│ ├── dashboard.js
│ ├── googleButton.js
│ ├── auth.js
│ ├── signup.js
│ └── signin.js
├── App.js
├── firebase
│ └── index.js
├── index.css
└── context
│ └── userContext.js
├── .gitignore
├── README.md
├── CONTRIBUTING.md
├── package.json
└── LICENSE
/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FullstackSimplified/firebase-auth/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FullstackSimplified/firebase-auth/HEAD/public/logo192.png
--------------------------------------------------------------------------------
/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FullstackSimplified/firebase-auth/HEAD/public/logo512.png
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ReactDOM from "react-dom";
3 | import "./index.css";
4 | import App from "./App";
5 | import { UserContextProvider } from "./context/userContext";
6 |
7 | ReactDOM.render(
8 |
9 |
10 |
11 |
12 | ,
13 | document.getElementById("root")
14 | );
15 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # production
12 | /build
13 |
14 | # misc
15 | .DS_Store
16 | .env.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 |
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 |
--------------------------------------------------------------------------------
/src/components/dashboard.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { useUserContext } from "../context/userContext";
3 |
4 | const Dashboard = () => {
5 | const { user, logoutUser } = useUserContext();
6 | return (
7 |
8 |
Dashboard
9 | Name : {user.displayName}
10 | Email : {user.email}
11 |
12 |
13 | );
14 | };
15 |
16 | export default Dashboard;
17 |
--------------------------------------------------------------------------------
/src/App.js:
--------------------------------------------------------------------------------
1 | import Auth from "./components/auth";
2 | import Dashboard from "./components/dashboard";
3 | import { useUserContext } from "./context/userContext";
4 |
5 | function App() {
6 | const { user, loading, error } = useUserContext();
7 |
8 | return (
9 |
10 | {error &&
{error}
}
11 | {loading ?
Loading...
: <> {user ?
:
} >}
12 |
13 | );
14 | }
15 |
16 | export default App;
17 |
--------------------------------------------------------------------------------
/src/firebase/index.js:
--------------------------------------------------------------------------------
1 | import { initializeApp } from "firebase/app";
2 | import { getAuth } from "firebase/auth";
3 |
4 | const firebaseConfig = {
5 | apiKey: "AIzaSyCzGKXxJ8IUpYRa5xqQkWZOmUChSAlVKMo",
6 | authDomain: "fir-auth-react-e8399.firebaseapp.com",
7 | projectId: "fir-auth-react-e8399",
8 | storageBucket: "fir-auth-react-e8399.appspot.com",
9 | messagingSenderId: "962605851630",
10 | appId: "1:962605851630:web:8a54bce7d9047760a9e4ff",
11 | };
12 |
13 | export const app = initializeApp(firebaseConfig);
14 | export const auth = getAuth(app);
15 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Firebase Authentication in React | Email-Password Auth | Reset Password
2 |
3 | ### This repo shows how to use Firebase Authentication in your React Web App without writing a single code for backend or API.
4 |
5 | ### Youtube Tutorial Link - https://youtu.be/14Nb3qPDtBQ
6 |
7 |
8 |
9 |
10 |
11 | #### 📚 Materials/References:
12 |
13 | React Context API : https://youtu.be/DQxQQydJg3k
14 |
15 | React refs and forwardRefs: https://youtu.be/gwFfzIaKnAU
16 |
17 | Firebase: https://firebase.google.com
18 |
19 | Firebase Auth: https://firebase.google.com/docs/auth/web/start
20 |
21 |
--------------------------------------------------------------------------------
/src/components/googleButton.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | const GoogleButton = ({ children, ...buttonProps }) => {
4 | return (
5 |
17 | );
18 | };
19 |
20 | export default GoogleButton;
21 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | ## Contributing Guidelines
2 |
3 | Here are some suggestions you should be following while contributing to this repository:
4 |
5 |
6 | :bulb: First of all, read the contributing guidelines.\
7 | :bulb: Always check properly if the issue you wish to create,already exist or not.\
8 | :bulb: Ask for the issue that you plan to complete.\
9 | :bulb: Commit message should be of the stated syntax.\
10 | :bulb: Add comments to codes.\
11 | :bulb: When naming the functions or variables use meaningfull name instead of a1,a2,a3.\
12 | :bulb: Every PR would be reviewed before it gets merged.
13 |
--------------------------------------------------------------------------------
/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/src/components/auth.js:
--------------------------------------------------------------------------------
1 | import React, { useState } from "react";
2 | import Signin from "./signin";
3 | import Signup from "./signup";
4 | import GoogleButton from "./googleButton";
5 | import { useUserContext } from "../context/userContext";
6 |
7 | const Auth = () => {
8 | const [index, setIndex] = useState(false);
9 | const toggleIndex = () => {
10 | setIndex((prevState) => !prevState);
11 | };
12 | const { signInWithGoogle } = useUserContext();
13 |
14 | return (
15 |
16 | {!index ?
:
}
17 |
18 | Continue with Google
19 |
20 |
21 | {!index ? "New user? Click here " : "Already have an acount?"}
22 |
23 |
24 | );
25 | };
26 |
27 | export default Auth;
28 |
--------------------------------------------------------------------------------
/src/components/signup.js:
--------------------------------------------------------------------------------
1 | import React, { useRef } from "react";
2 | import { useUserContext } from "../context/userContext";
3 |
4 | const Signup = () => {
5 | const emailRef = useRef();
6 | const nameRef = useRef();
7 | const psdRef = useRef();
8 | const { registerUser } = useUserContext();
9 |
10 | const onSubmit = (e) => {
11 | e.preventDefault();
12 | const email = emailRef.current.value;
13 | const name = nameRef.current.value;
14 | const password = psdRef.current.value;
15 | if (email && password && name) registerUser(email, password, name);
16 | };
17 |
18 | return (
19 |
20 |
New User
21 |
27 |
28 | );
29 | };
30 |
31 | export default Signup;
32 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-firebase-auth",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@testing-library/jest-dom": "^5.14.1",
7 | "@testing-library/react": "^11.2.7",
8 | "@testing-library/user-event": "^12.8.3",
9 | "firebase": "^9.1.3",
10 | "react": "^17.0.2",
11 | "react-dom": "^17.0.2",
12 | "react-router-dom": "^5.3.0",
13 | "react-scripts": "4.0.3",
14 | "web-vitals": "^1.1.2"
15 | },
16 | "scripts": {
17 | "start": "react-scripts start",
18 | "build": "react-scripts build",
19 | "test": "react-scripts test",
20 | "eject": "react-scripts eject"
21 | },
22 | "eslintConfig": {
23 | "extends": [
24 | "react-app",
25 | "react-app/jest"
26 | ]
27 | },
28 | "browserslist": {
29 | "production": [
30 | ">0.2%",
31 | "not dead",
32 | "not op_mini all"
33 | ],
34 | "development": [
35 | "last 1 chrome version",
36 | "last 1 firefox version",
37 | "last 1 safari version"
38 | ]
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Fullstack Simplified
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/components/signin.js:
--------------------------------------------------------------------------------
1 | import React, { useRef } from "react";
2 | import { useUserContext } from "../context/userContext";
3 |
4 | const Signin = () => {
5 | const emailRef = useRef();
6 | const psdRef = useRef();
7 | const { signInUser, forgotPassword } = useUserContext();
8 |
9 | const onSubmit = (e) => {
10 | e.preventDefault();
11 | const email = emailRef.current.value;
12 | const password = psdRef.current.value;
13 | if (email && password) signInUser(email, password);
14 | };
15 |
16 | const forgotPasswordHandler = () => {
17 | const email = emailRef.current.value;
18 | if (email)
19 | forgotPassword(email).then(() => {
20 | emailRef.current.value = "";
21 | });
22 | };
23 |
24 | return (
25 |
34 | );
35 | };
36 |
37 | export default Signin;
38 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
17 |
18 |
27 | React App
28 |
29 |
30 |
31 |
32 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
4 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
5 | sans-serif;
6 | -webkit-font-smoothing: antialiased;
7 | -moz-osx-font-smoothing: grayscale;
8 | }
9 |
10 | code {
11 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
12 | monospace;
13 | }
14 |
15 | .App {
16 | display: flex;
17 | align-items: center;
18 | justify-content: center;
19 | min-height: 100vh;
20 | flex-direction: column;
21 | }
22 |
23 | input {
24 | padding: 12px;
25 | margin: 12px;
26 | font-size: 14px;
27 | border: 1px solid #ccc;
28 | box-shadow: 0 1px 4px #ccc;
29 | border-radius: 6px;
30 | font-size: 18px;
31 | width: 93%;
32 | }
33 |
34 | button {
35 | background-color: teal;
36 | border: none;
37 | color: white;
38 | padding: 12px;
39 | margin: 12px 0;
40 | box-shadow: 0 1px 6px #ccc;
41 | width: 100%;
42 | border-radius: 6px;
43 | font-size: 18px;
44 | cursor: pointer;
45 | }
46 |
47 | .container {
48 | box-shadow: 0 1px 6px #ccc;
49 | border-radius: 6px;
50 | display: flex;
51 | align-items: center;
52 | justify-content: center;
53 | flex-direction: column;
54 | width: 400px;
55 | padding: 22px;
56 | }
57 |
58 | .container > p {
59 | cursor: pointer;
60 | margin: 12px;
61 | }
62 |
63 | .form {
64 | width: 100%;
65 | }
66 |
67 | .form > h2 {
68 | text-align: center;
69 | }
70 |
71 | .form > form {
72 | display: flex;
73 | align-items: center;
74 | justify-content: center;
75 | flex-direction: column;
76 | }
77 |
78 | .form > form > p {
79 | cursor: pointer;
80 | }
81 |
82 | .error {
83 | background-color: tomato;
84 | color: white;
85 | border-radius: 6px;
86 | padding: 6px 12px;
87 | font-weight: bold;
88 | max-width: 400px;
89 | margin-bottom: 18px;
90 | }
91 |
92 | button .google-icon-wrapper {
93 | display: flex;
94 | align-items: center;
95 | justify-content: center;
96 | }
97 |
98 | button .google-icon {
99 | margin-right: 20px;
100 | }
101 |
--------------------------------------------------------------------------------
/src/context/userContext.js:
--------------------------------------------------------------------------------
1 | import { createContext, useContext, useState, useEffect } from "react";
2 | import {
3 | signInWithEmailAndPassword,
4 | createUserWithEmailAndPassword,
5 | onAuthStateChanged,
6 | signOut,
7 | updateProfile,
8 | sendPasswordResetEmail,
9 | signInWithPopup,
10 | GoogleAuthProvider,
11 | } from "firebase/auth";
12 | import { auth } from "../firebase";
13 |
14 | export const UserContext = createContext({});
15 |
16 | export const useUserContext = () => {
17 | return useContext(UserContext);
18 | };
19 |
20 | export const UserContextProvider = ({ children }) => {
21 | const [user, setUser] = useState(null);
22 | const [loading, setLoading] = useState(false);
23 | const [error, setError] = useState("");
24 |
25 | useEffect(() => {
26 | setLoading(true);
27 | const unsubscribe = onAuthStateChanged(auth, (res) => {
28 | if (res) {
29 | setUser(res);
30 | } else {
31 | setUser(null);
32 | }
33 | setError("");
34 | setLoading(false);
35 | });
36 | return unsubscribe;
37 | }, []);
38 |
39 | const registerUser = (email, password, name) => {
40 | setLoading(true);
41 | createUserWithEmailAndPassword(auth, email, password)
42 | .then(() =>
43 | updateProfile(auth.currentUser, {
44 | displayName: name,
45 | })
46 | )
47 | .then((res) => console.log(res))
48 | .catch((err) => setError(err.message))
49 | .finally(() => setLoading(false));
50 | };
51 |
52 | const signInUser = (email, password) => {
53 | setLoading(true);
54 | signInWithEmailAndPassword(auth, email, password)
55 | .then((res) => console.log(res))
56 | .catch((err) => setError(err.code))
57 | .finally(() => setLoading(false));
58 | };
59 |
60 | const logoutUser = () => {
61 | signOut(auth);
62 | };
63 |
64 | const signInWithGoogle = () => {
65 | setLoading(true);
66 | setError("");
67 |
68 | signInWithPopup(auth, new GoogleAuthProvider())
69 | .then((res) => console.log(res))
70 | .catch((err) => setError(err.code))
71 | .finally(() => setLoading(false));
72 | };
73 |
74 | const forgotPassword = (email) => {
75 | return sendPasswordResetEmail(auth, email);
76 | };
77 |
78 | const contextValue = {
79 | user,
80 | loading,
81 | error,
82 | signInUser,
83 | registerUser,
84 | logoutUser,
85 | forgotPassword,
86 | signInWithGoogle,
87 | };
88 | return (
89 | {children}
90 | );
91 | };
92 |
--------------------------------------------------------------------------------