├── 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 |
22 | 23 | 24 | 25 | 26 |
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 |
26 |

Login

27 |
28 | 29 | 30 | 31 |

Forgot Password?

32 |
33 |
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 | --------------------------------------------------------------------------------