gemini/autocal/frontend/components/auth/AuthContext.tsx (76 lines of code) (raw):
/**
* Copyright 2025 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
"use client";
import { CodeResponse } from "@react-oauth/google";
import { createContext, ReactNode, useContext, useEffect, useState } from "react";
import { GoogleOAuthProvider } from "@react-oauth/google";
import { GoogleAuthProvider, signInWithCredential, signOut, UserCredential } from "firebase/auth";
import { firebaseAuth } from "@/libs/firebase/client/clientApp";
import { getSession, processSignin, removeSession } from "@/libs/auth/auth";
interface Props {
children?: ReactNode;
}
interface AuthContext {
firebaseUser: UserCredential | null;
handleLogin(response: Omit<CodeResponse, "error" | "error_description" | "error_uri">): void;
error: string;
loading: boolean;
logOut: () => void;
}
const AuthContext = createContext({} as AuthContext);
export default function AuthContextProvider({ children }: Props) {
const [firebaseUser, setFirebaseUser] = useState<UserCredential | null>(null);
const [error, setError] = useState<string>("");
const [loading, setLoading] = useState<boolean>(true);
useEffect(() => {
async function loadSession() {
try {
const t = await getSession();
if (t) {
await loadFirebaseUser(t);
}
} finally {
setLoading(false);
}
}
loadSession();
}, []);
async function loadFirebaseUser(t: string) {
const credential = GoogleAuthProvider.credential(t);
const p = await signInWithCredential(firebaseAuth, credential);
setFirebaseUser(p);
}
async function handleLogin(response: Omit<CodeResponse, "error" | "error_description" | "error_uri">) {
if (response?.code) {
try {
// Verify tokens on server side:
const t = await processSignin(response.code);
loadFirebaseUser(t);
} catch (error) {
console.error(error);
setError(`${error}`);
}
}
}
async function logOut() {
const s = removeSession();
setFirebaseUser(null);
signOut(firebaseAuth);
await s;
}
return (
<GoogleOAuthProvider clientId={process.env.NEXT_PUBLIC_CLIENT_ID!}>
<AuthContext.Provider
value={{
firebaseUser,
handleLogin,
error,
loading,
logOut,
}}
>
{children}
</AuthContext.Provider>
</GoogleOAuthProvider>
);
}
export function Auth(): AuthContext {
return useContext(AuthContext);
}