Sign in¶
Now let's implement a sign in page.
fireauth
├── .env.development
├── .firebaserc
├── .git
│ └── ...
├── .gitignore
├── .vscode
│ ├── settings.json
│ └── tasks.json
├── README.md
├── firebase-debug.log
├── firebase.json
├── firestore-debug.log
├── firestore.indexes.json
├── firestore.rules
├── functions
│ ├── .gitignore
│ ├── index.js
│ ├── package-lock.json
│ └── package.json
├── jsconfig.json
├── next.config.mjs
├── package-lock.json
├── package.json
├── src
│ ├── app
│ │ ├── Home.jsx
│ │ ├── layout.js
│ │ ├── page.js
│ │ ├── signin
│ │ │ ├── SignInForm.js
│ │ │ └── page.js
│ │ └── signup
│ │ ├── SignUpForm.js
│ │ └── page.js
│ └── firebase
│ └── firebase.js
└── ui-debug.log
import { SignInForm } from "./SignInForm"
export default function SignupPage() {
return (
<>
<div>Sign in page</div>
<SignInForm />
</>
)
}
"use client"
import { auth } from "@/firebase/firebase"
import { signInWithEmailAndPassword } from "firebase/auth"
import { useRouter } from "next/navigation"
import { useState } from "react"
export function SignInForm() {
const [email, setEmail] = useState("")
const [password, setPassword] = useState("")
const router = useRouter()
const handleFormSubmit = (event) => {
event.preventDefault()
signInWithEmailAndPassword(auth, email, password)
.then((userCredential) => {
router.push("/")
})
.catch((error) => {
console.log("Error:", error)
})
}
return (
<form onSubmit={handleFormSubmit}>
<label>Email:</label>
<input
type="text"
value={email}
onChange={(event) => setEmail(event.target.value)}
/>
<label>Password:</label>
<input
type="password"
value={password}
onChange={(event) => setPassword(event.target.value)}
/>
<button type="submit">Sign in</button>
</form>
)
}
The sign in code and functionality is very similar to the sign up functionality. In short, when a user signs in
- The
signInWithEmailAndPassword()
function is invoked. - A pair of
POST
requests are made toidentitytoolkit.googleapis.com
.- The first
POST
request hits theaccounts:signInWithPassword
endpoint. If the response is good (200), it returns the user'sidToken
as a JWT. - The second
POST
request hits theaccounts:lookup
endpoint.
- The first
router.push("/")
redirects the user to the home page.
Sign out¶
Now let's implement the Sign out button.
"use client"
import { auth } from "@/firebase/firebase"
import { onAuthStateChanged, signOut } from "firebase/auth"
import Link from "next/link"
import { useEffect, useState } from "react"
export function Home() {
const [authUser, setAuthUser] = useState(undefined)
useEffect(() => {
const unsubscribe = onAuthStateChanged(auth, (user) => {
setAuthUser(user)
})
return unsubscribe
}, [])
const handleSignOut = () => {
signOut(auth)
}
return (
authUser === undefined
? <div>Loading...</div>
: (
authUser
? <button onClick={ handleSignOut }>Sign out</button>
: <>
<Link href="/signup">Sign up</Link>
<span> | </span>
<Link href="/signin">Sign in</Link>
</>
)
)
}
Let's see it in action, paying close attention to the IndexedDB.
Notice the sign out mechanism deletes the user data from the IndexedDB.