Skip to content

Commit da55400

Browse files
PrasoonPrasoon
Prasoon
authored and
Prasoon
committed
Firebase email password authentication in React web app
1 parent 86c90c1 commit da55400

16 files changed

+2083
-96
lines changed

package-lock.json

Lines changed: 1790 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@
66
"@testing-library/jest-dom": "^5.14.1",
77
"@testing-library/react": "^11.2.7",
88
"@testing-library/user-event": "^12.8.3",
9+
"firebase": "^9.1.3",
910
"react": "^17.0.2",
1011
"react-dom": "^17.0.2",
12+
"react-router-dom": "^5.3.0",
1113
"react-scripts": "4.0.3",
1214
"web-vitals": "^1.1.2"
1315
},

src/App.css

Lines changed: 0 additions & 38 deletions
This file was deleted.

src/App.js

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,14 @@
1-
import logo from './logo.svg';
2-
import './App.css';
1+
import Auth from "./components/auth";
2+
import Dashboard from "./components/dashboard";
3+
import { useUserContext } from "./context/userContext";
34

45
function App() {
6+
const { user, loading, error } = useUserContext();
7+
58
return (
69
<div className="App">
7-
<header className="App-header">
8-
<img src={logo} className="App-logo" alt="logo" />
9-
<p>
10-
Edit <code>src/App.js</code> and save to reload.
11-
</p>
12-
<a
13-
className="App-link"
14-
href="https://reactjs.org"
15-
target="_blank"
16-
rel="noopener noreferrer"
17-
>
18-
Learn React
19-
</a>
20-
</header>
10+
{error && <p className="error">{error}</p>}
11+
{loading ? <h2>Loading...</h2> : <> {user ? <Dashboard /> : <Auth />} </>}
2112
</div>
2213
);
2314
}

src/App.test.js

Lines changed: 0 additions & 8 deletions
This file was deleted.

src/components/auth.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import React, { useState } from "react";
2+
import Signin from "./signin";
3+
import Signup from "./signup";
4+
5+
const Auth = () => {
6+
const [index, setIndex] = useState(false);
7+
const toggleIndex = () => {
8+
setIndex((prevState) => !prevState);
9+
};
10+
return (
11+
<div className="container">
12+
{!index ? <Signin /> : <Signup />}
13+
<p onClick={toggleIndex}>
14+
{!index ? "New user? Click here " : "Already have an acount?"}
15+
</p>
16+
</div>
17+
);
18+
};
19+
20+
export default Auth;

src/components/dashboard.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import React from "react";
2+
import { useUserContext } from "../context/userContext";
3+
4+
const Dashboard = () => {
5+
const { user, logoutUser } = useUserContext();
6+
return (
7+
<div>
8+
<h1>Dashboard </h1>
9+
<h2>Name : {user.displayName}</h2>
10+
<h2>Email : {user.email}</h2>
11+
<button onClick={logoutUser}>Log out</button>
12+
</div>
13+
);
14+
};
15+
16+
export default Dashboard;

src/components/signin.js

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
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+
<div className="form">
26+
<h2> Login </h2>
27+
<form onSubmit={onSubmit}>
28+
<input placeholder="Email" type="email" ref={emailRef} />
29+
<input placeholder="Password" type="password" ref={psdRef} />
30+
<button type="submit">Sign In</button>
31+
<p onClick={forgotPasswordHandler}>Forgot Password?</p>
32+
</form>
33+
</div>
34+
);
35+
};
36+
37+
export default Signin;

src/components/signup.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
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+
<div className="form">
20+
<h2> New User</h2>
21+
<form onSubmit={onSubmit}>
22+
<input placeholder="Email" type="email" ref={emailRef} />
23+
<input placeholder="Name" type="name" ref={nameRef} />
24+
<input placeholder="Password" type="password" ref={psdRef} />
25+
<button type="submit">Register</button>
26+
</form>
27+
</div>
28+
);
29+
};
30+
31+
export default Signup;

src/context/userContext.js

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import { createContext, useContext, useState } from "react";
2+
import {
3+
signInWithEmailAndPassword,
4+
createUserWithEmailAndPassword,
5+
onAuthStateChanged,
6+
signOut,
7+
updateProfile,
8+
sendPasswordResetEmail,
9+
} from "firebase/auth";
10+
import { auth } from "../firebase";
11+
12+
export const UserContext = createContext({});
13+
14+
export const useUserContext = () => {
15+
return useContext(UserContext);
16+
};
17+
18+
export const UserContextProvider = ({ children }) => {
19+
const [user, setUser] = useState(null);
20+
const [loading, setLoading] = useState(false);
21+
const [error, setError] = useState("");
22+
23+
useState(() => {
24+
setLoading(true);
25+
const unsubscribe = onAuthStateChanged(auth, (res) => {
26+
if (res) {
27+
setUser(res);
28+
} else {
29+
setUser(null);
30+
}
31+
setError("");
32+
setLoading(false);
33+
});
34+
return unsubscribe;
35+
}, []);
36+
37+
const registerUser = (email, password, name) => {
38+
setLoading(true);
39+
createUserWithEmailAndPassword(auth, email, password)
40+
.then(() =>
41+
updateProfile(auth.currentUser, {
42+
displayName: name,
43+
})
44+
)
45+
.then((res) => console.log(res))
46+
.catch((err) => setError(err.message))
47+
.finally(() => setLoading(false));
48+
};
49+
50+
const signInUser = (email, password) => {
51+
setLoading(true);
52+
signInWithEmailAndPassword(auth, email, password)
53+
.then((res) => console.log(res))
54+
.catch((err) => setError(err.code))
55+
.finally(() => setLoading(false));
56+
};
57+
58+
const logoutUser = () => {
59+
signOut(auth);
60+
};
61+
62+
const forgotPassword = (email) => {
63+
return sendPasswordResetEmail(auth, email);
64+
};
65+
66+
const contextValue = {
67+
user,
68+
loading,
69+
error,
70+
signInUser,
71+
registerUser,
72+
logoutUser,
73+
forgotPassword,
74+
};
75+
return (
76+
<UserContext.Provider value={contextValue}>{children}</UserContext.Provider>
77+
);
78+
};

src/firebase/index.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
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);

src/index.css

Lines changed: 79 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,89 @@
11
body {
22
margin: 0;
3-
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
4-
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
3+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
4+
"Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
55
sans-serif;
66
-webkit-font-smoothing: antialiased;
77
-moz-osx-font-smoothing: grayscale;
88
}
99

1010
code {
11-
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
11+
font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
1212
monospace;
1313
}
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+
}
45+
46+
.container {
47+
box-shadow: 0 1px 6px #ccc;
48+
border-radius: 6px;
49+
display: flex;
50+
align-items: center;
51+
justify-content: center;
52+
flex-direction: column;
53+
width: 400px;
54+
padding: 22px;
55+
}
56+
57+
.container > p {
58+
cursor: pointer;
59+
margin: 12px;
60+
}
61+
62+
.form {
63+
width: 100%;
64+
}
65+
66+
.form > h2 {
67+
text-align: center;
68+
}
69+
70+
.form > form {
71+
display: flex;
72+
align-items: center;
73+
justify-content: center;
74+
flex-direction: column;
75+
}
76+
77+
.form > form > p {
78+
cursor: pointer;
79+
}
80+
81+
.error {
82+
background-color: tomato;
83+
color: white;
84+
border-radius: 6px;
85+
padding: 6px 12px;
86+
font-weight: bold;
87+
max-width: 400px;
88+
margin-bottom: 18px;
89+
}

0 commit comments

Comments
 (0)