Sign in with Server Action
You can follow the official firebase/auth
guide (opens in a new tab) to handle operations like signInWithEmailAndPassword
or signOut
.
refreshCookiesWithIdToken
The refreshCookiesWithIdToken
method updates browser cookies with the latest authenticated credentials based on the idToken
. This method works with Server Actions and Middleware. After performing Firebase operations in a Server Action, you can use this method to refresh the browser cookies with updated credentials.
Example loginAction and LoginPage
Note for Vercel users: The firebase/auth
library isn't fully compatible with Vercel environments when used inside Server Actions.
If you get a ReferenceError: document is not defined
, move the firebase/auth
import to a client component.
Below is a simple example of a login page client component that lets users sign in using a Server Action and the refreshCookiesWithIdToken
method.
First, let’s define our Server Action:
'use server';
import {refreshCookiesWithIdToken} from 'next-firebase-auth-edge/lib/next/cookies';
import {signInWithEmailAndPassword} from 'firebase/auth';
import {cookies, headers} from 'next/headers';
import {redirect} from 'next/navigation';
// See starter example for implementation: https://github.com/awinogrodzki/next-firebase-auth-edge/tree/main/examples/next-typescript-starter
import {getFirebaseAuth} from '@/app/auth/firebase';
import {authConfig} from '@/config/server-config';
export async function loginAction(username: string, password: string) {
const credential = await signInWithEmailAndPassword(
getFirebaseAuth(),
username,
password
);
const idToken = await credential.user.getIdToken();
// Since Next.js 15, `headers` and `cookies` functions return a Promise, hence we precede the calls with `await`.
await refreshCookiesWithIdToken(
idToken,
await headers(),
await cookies(),
authConfig
);
redirect('/');
}
Next, create LoginPage client component that will call login action:
'use client';
import * as React from 'react';
interface LoginPageProps {
loginAction: (email: string, password: string) => void;
}
export default function LoginPage({loginAction}: LoginPageProps) {
const [email, setEmail] = React.useState('');
const [password, setPassword] = React.useState('');
let [isLoginActionPending, startTransition] = React.useTransition();
async function handleSubmit(event: React.FormEvent) {
event.preventDefault();
event.stopPropagation();
startTransition(() => loginAction(email, password));
}
return (
<div>
<h1>Login</h1>
<form onSubmit={handleSubmit}>
<input
required
value={email}
onChange={(e) => setEmail(e.target.value)}
name="email"
type="email"
placeholder="Email address"
/>
<br />
<input
required
name="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
type="password"
placeholder="Password"
minLength={8}
/>
<button disabled={isLoginActionPending} type="submit">
Submit
</button>
</form>
</div>
);
}
Lastly, let's use LoginPage inside page.tsx
Server Component:
import LoginPage from './LoginPage';
import {loginAction} from './login';
export default function Page() {
return <LoginPage loginAction={loginAction} />;
}