├── .gitignore ├── README.md ├── app.vue ├── components └── AuthFirebase.vue ├── composables ├── useFirebase.ts └── useStates.ts ├── nuxt.config.ts ├── package-lock.json ├── package.json ├── pages ├── firebase.vue ├── index.vue └── secret.vue ├── plugins ├── auth.ts └── firebaseAuth.client.ts ├── server ├── api │ ├── auth.ts │ ├── me.ts │ └── secret.ts └── middleware │ └── user-middleware.ts └── tsconfig.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.log 3 | .nuxt 4 | nuxt.d.ts 5 | .output 6 | .env -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Nuxt 3 / Firebase Auth Starter 2 | 3 | Nuxt 3 Getting Started 4 | https://v3.nuxtjs.org/getting-started/introduction 5 | 6 | Get Started with Firebase Authentication on Websites 7 | https://firebase.google.com/docs/auth/web/start 8 | 9 | ## Setup 10 | 11 | Make sure to install the dependencies 12 | 13 | ``` 14 | npm install 15 | ``` 16 | 17 | ## Development 18 | 19 | Start the development server on http://localhost:3000 20 | 21 | ``` 22 | npm run dev 23 | ``` 24 | 25 | ## Production 26 | 27 | Build the application for production: 28 | 29 | ``` 30 | npm run build 31 | ``` 32 | -------------------------------------------------------------------------------- /app.vue: -------------------------------------------------------------------------------- 1 | 32 | 33 | 65 | 66 | 70 | -------------------------------------------------------------------------------- /components/AuthFirebase.vue: -------------------------------------------------------------------------------- 1 | 41 | 42 | 49 | 50 | -------------------------------------------------------------------------------- /composables/useFirebase.ts: -------------------------------------------------------------------------------- 1 | //https://firebase.google.com/docs/auth/web/start 2 | 3 | import { 4 | getAuth, 5 | createUserWithEmailAndPassword, 6 | signInWithEmailAndPassword, 7 | onAuthStateChanged, 8 | } from "firebase/auth"; 9 | 10 | export const createUser = async (email, password) => { 11 | const auth = getAuth(); 12 | const credentials = await createUserWithEmailAndPassword( 13 | auth, 14 | email, 15 | password 16 | ).catch((error) => { 17 | const errorCode = error.code; 18 | const errorMessage = error.message; 19 | }); 20 | return credentials; 21 | }; 22 | 23 | export const signInUser = async (email, password) => { 24 | const auth = getAuth(); 25 | const credentials = await signInWithEmailAndPassword( 26 | auth, 27 | email, 28 | password 29 | ).catch((error) => { 30 | const errorCode = error.code; 31 | const errorMessage = error.message; 32 | }); 33 | return credentials; 34 | }; 35 | 36 | export const initUser = async () => { 37 | const auth = getAuth(); 38 | const firebaseUser = useFirebaseUser(); 39 | firebaseUser.value = auth.currentUser; 40 | 41 | const userCookie = useCookie("userCookie"); 42 | 43 | const router = useRouter(); 44 | 45 | onAuthStateChanged(auth, (user) => { 46 | if (user) { 47 | // User is signed in, see docs for a list of available properties 48 | // https://firebase.google.com/docs/reference/js/firebase.User 49 | } else { 50 | //if signed out 51 | router.push("/"); 52 | } 53 | 54 | firebaseUser.value = user; 55 | 56 | // @ts-ignore 57 | userCookie.value = user; //ignore error because nuxt will serialize to json 58 | 59 | $fetch("/api/auth", { 60 | method: "POST", 61 | body: { user }, 62 | }); 63 | }); 64 | }; 65 | 66 | export const signOutUser = async () => { 67 | const auth = getAuth(); 68 | const result = await auth.signOut(); 69 | return result; 70 | }; 71 | -------------------------------------------------------------------------------- /composables/useStates.ts: -------------------------------------------------------------------------------- 1 | export const useFirebaseUser = () => useState("firebaseUser", () => null); 2 | -------------------------------------------------------------------------------- /nuxt.config.ts: -------------------------------------------------------------------------------- 1 | import { defineNuxtConfig } from "nuxt3"; 2 | 3 | // https://v3.nuxtjs.org/docs/directory-structure/nuxt.config 4 | export default defineNuxtConfig({ 5 | publicRuntimeConfig: { 6 | FIREBASE_API_KEY: process.env.FIREBASE_API_KEY, 7 | }, 8 | privateRuntimeConfig: { 9 | FIREBASE_API_KEY: process.env.FIREBASE_API_KEY, 10 | }, 11 | }); 12 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "dev": "nuxi dev", 5 | "build": "nuxi build", 6 | "start": "node .output/server/index.mjs" 7 | }, 8 | "devDependencies": { 9 | "nuxt3": "latest" 10 | }, 11 | "dependencies": { 12 | "bulma": "^0.9.3", 13 | "firebase": "^9.6.8" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /pages/firebase.vue: -------------------------------------------------------------------------------- 1 | 41 | 42 | 69 | 70 | -------------------------------------------------------------------------------- /pages/index.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 25 | 26 | 28 | -------------------------------------------------------------------------------- /pages/secret.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /plugins/auth.ts: -------------------------------------------------------------------------------- 1 | export default defineNuxtPlugin(() => { 2 | addRouteMiddleware('auth', () => { 3 | const { $auth } = useNuxtApp() 4 | 5 | console.log($auth?.currentUser) 6 | 7 | if(!$auth?.currentUser?.uid) { 8 | return navigateTo('/') 9 | } 10 | }) 11 | }) -------------------------------------------------------------------------------- /plugins/firebaseAuth.client.ts: -------------------------------------------------------------------------------- 1 | import { initializeApp } from "firebase/app"; 2 | import { 3 | getAuth, 4 | } from "firebase/auth"; 5 | 6 | export default defineNuxtPlugin((nuxtApp) => { 7 | 8 | const config = useRuntimeConfig(); 9 | 10 | const firebaseConfig = { 11 | apiKey: config.FIREBASE_API_KEY, 12 | }; 13 | 14 | // Initialize Firebase 15 | const app = initializeApp(firebaseConfig); 16 | 17 | initUser(); 18 | 19 | const auth = getAuth(); 20 | 21 | nuxtApp.vueApp.provide('auth', auth); 22 | nuxtApp.provide('auth', auth); 23 | 24 | }); 25 | -------------------------------------------------------------------------------- /server/api/auth.ts: -------------------------------------------------------------------------------- 1 | import type { IncomingMessage, ServerResponse } from "http"; 2 | import { useBody } from 'h3' 3 | 4 | export default async (req: IncomingMessage, res: ServerResponse) => { 5 | 6 | if(req.method !== 'POST') return 'Must be post request' 7 | 8 | const { user } = await useBody(req) // only for POST request 9 | 10 | // @ts-ignore 11 | req.user = user; 12 | 13 | return { updated: true } 14 | }; 15 | -------------------------------------------------------------------------------- /server/api/me.ts: -------------------------------------------------------------------------------- 1 | import type { IncomingMessage, ServerResponse } from "http"; 2 | 3 | export default async (req: IncomingMessage, res: ServerResponse) => { 4 | 5 | // @ts-ignore 6 | const user = req.user; 7 | 8 | return user ? user : "User is signed out" 9 | }; 10 | -------------------------------------------------------------------------------- /server/api/secret.ts: -------------------------------------------------------------------------------- 1 | import type { IncomingMessage, ServerResponse } from 'http' 2 | 3 | export default async (req: IncomingMessage, res: ServerResponse) => { 4 | 5 | // @ts-ignore 6 | const user = req.user; 7 | 8 | if(user) { 9 | res.statusCode = 200 10 | res.end('This is a top secret message from the API') 11 | } 12 | res.statusCode = 400 13 | res.end('Must be signed in to read secret message') 14 | } -------------------------------------------------------------------------------- /server/middleware/user-middleware.ts: -------------------------------------------------------------------------------- 1 | import type { IncomingMessage, ServerResponse } from "http"; 2 | import { useCookie } from 'h3' 3 | 4 | export default async (req: IncomingMessage, res: ServerResponse) => { 5 | const userCookie = useCookie(req, "userCookie"); 6 | 7 | // @ts-ignore 8 | req.user = userCookie; 9 | }; 10 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | // https://v3.nuxtjs.org/concepts/typescript 3 | "extends": "./.nuxt/tsconfig.json" 4 | } 5 | --------------------------------------------------------------------------------