├── .DS_Store
├── .github
└── FUNDING.yml
├── .gitignore
├── LICENSE
├── PRIVACY_POLICY.md
├── README.md
├── TERMS_OF_SERVICE.md
├── auth-actions.ts
├── client
├── AuthPages.jsx
├── ProfileButtonStyle.css
├── auth.tsx
├── components.tsx
└── getFirebaseErrors.ts
├── dist
├── authpages
│ ├── forgot-password
│ │ └── page.jsx
│ ├── login
│ │ └── page.jsx
│ └── register
│ │ └── page.jsx
└── middleware.js
├── firebasenextjs-firebase.ts
├── middleware
├── check-user.js
└── firebase-nextjs-middleware.js
├── package-lock.json
├── package.json
├── scripts
├── a_copyComponents.mjs
├── a_setupGcloud.mjs
├── b_setupProject.mjs
├── c_generateServiceAccount.mjs
├── cliUtils.mjs
├── d_setWebApp.mjs
├── e_enableAuth.mjs
├── index.mjs
├── setup.mjs
└── utils
│ └── getEnv.mjs
├── server
├── auth.ts
├── getToken.d.ts
└── getToken.js
├── tsconfig.json
└── utilities
├── createSymlink.mjs
├── deleteSymlink.mjs
└── preparePackage.mjs
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NirmalScaria/firebase-nextjs/f0c02688357cdda245af50434278f80145f9a9d0/.DS_Store
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: [NirmalScaria]
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | firebase-service-account.json
3 | firebase-app-config.js
4 | build
5 | .DS_Store
6 | scripts/oauthDetails.mjs
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 Nirmal Scaria
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/PRIVACY_POLICY.md:
--------------------------------------------------------------------------------
1 | ### Privacy Policy
2 |
3 | #### Introduction
4 |
5 | Welcome to `next-fire-js`! This privacy policy outlines how we handle user data and privacy. We are committed to ensuring your privacy and protecting any information you provide while using our package.
6 |
7 | #### Data Collection
8 |
9 | **No Data Collection**: `next-fire-js` does not collect, store, or process any personal data from users. Our package is designed to facilitate Firebase authentication with Next.js applications without tracking or storing any user information.
10 |
11 | #### Use of OAuth
12 |
13 | **OAuth Authentication**: Our package uses OAuth for authenticating users via Google. This process involves securely communicating with Google servers to authenticate user credentials.
14 |
15 | **No Tracking**: We do not track users during or after the authentication process. The OAuth flow is solely for the purpose of user authentication and session management within your application.
16 |
17 | #### Security
18 |
19 | We prioritize security in our package design to ensure that the authentication process is safe and reliable. However, it is essential for users to follow best practices for securing their Firebase credentials and environment variables when using `next-fire-js`.
20 |
21 | #### Third-Party Services
22 |
23 | `next-fire-js` relies on Firebase for authentication services. Please refer to Firebase's privacy policy for more information on how they handle user data: [Firebase Privacy Policy](https://firebase.google.com/support/privacy).
24 |
25 | #### Changes to This Privacy Policy
26 |
27 | We may update this privacy policy from time to time. Any changes will be posted on this page, and the updated date will be indicated at the top of the policy.
28 |
29 | #### Contact Us
30 |
31 | If you have any questions or concerns about this privacy policy, please contact us at [scaria@scaria.dev].
32 |
33 | ---
34 |
35 | **Effective Date**: July 4, 2024
36 |
37 | **Last Updated**: July 4, 2024
38 |
39 | By using `next-fire-js`, you acknowledge that you have read and understood this privacy policy.
40 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | 
3 |
4 | **Effortless Firebase integration for NextJS**
5 |
6 | Demo : [https://firebase-nextjs.scaria.dev](https://firebase-nextjs.scaria.dev)
7 |
8 |
9 |
10 |
11 | # Setup Instructions
12 |
13 | The setup will automatically take care of configurations and credentials. If you would instead prefer to do it all manually, [Click here](#manual-installation).
14 |
15 | Prerequisite: A firebase project.
16 |
17 | ## 1. Install the package
18 | ```bash
19 | npm install firebase-nextjs
20 | ```
21 |
22 | ## 2. Run the setup script
23 | ```bash
24 | npx firebase-nextjs setup
25 | ```
26 |
27 | This will
28 | - Prompt you to log in with Google.
29 | - You will be asked to select the firebase project you wish to use.
30 | - You will be asked to choose the service account you wish to use. ("firebase-admin-sdk" is recommended)
31 | - Choose an app you wish to use. (Must be a web app) (If an app doesn't exist, you can create it there.)
32 | - This will generate the necessary authentication credentials, and store it to the project.
33 | - With this, basic setup is complete.
34 |
35 | ## 3. Setup firebase-nextjs Provider
36 |
37 | In the root layout file, (layout.jsx), wrap the whole body in **\**
38 |
39 | ```html
40 | import {FirebaseNextJSProvider} from "firebase-nextjs/client/auth";
41 |
42 |
43 |
44 |
45 | {children}
46 |
47 |
48 | ```
49 |
50 | ## 4. Thats it! Run the project.
51 |
52 | ```bash
53 | npm run dev
54 | ```
55 |
56 | This will require you to sign in to continue. You can use Google Sign In or Email Password Sign In.
57 |
58 | # Access the auth state
59 |
60 | You can access the authentication state, and the user object on client side as well as server side easily. Learn more:
61 | https://firebase-nextjs.scaria.dev/auth
62 |
63 | # Customisation
64 |
65 | firebase-nextjs offers complete customisation of login pages. To learn more, visit:
66 | https://firebase-nextjs.scaria.dev/custom_login
67 |
68 | # Components
69 |
70 | firebase-nextjs comes with many pre built components to help with user authentication and user management. Learn more from:
71 | https://firebase-nextjs.scaria.dev/components
72 |
73 | # Routing
74 |
75 | You can customise the rules for routing, and define which pages are public and which pages are for logged in users. Learn more at:
76 | https://firebase-nextjs.scaria.dev/routing
77 |
78 | # Moving to production
79 |
80 | Before deploying the app to production, there are few configurations and security measures to be done. Read more at:
81 | https://firebase-nextjs.scaria.dev/production
82 |
83 | # For Developers
84 |
85 | If you wish to contribute or make changes to the package, follow the below guide
86 |
87 | ## Step 1: Fork and clone the repo
88 |
89 | Fork the repo to your profile and clone the repo locally.
90 |
91 | ## Step 2: Build the package
92 |
93 | Run the command
94 |
95 | ```
96 | npm run build
97 | ```
98 |
99 | This will create a folder 'build' in the directory. It will contain the actual package that you should be using.
100 |
101 | ## Step 3: Link the package to your project
102 |
103 | Create a nextjs project that you wish to test the package with. (Or use your existing NextJS project). Copy the location of the build directory generated from the previous step.
104 |
105 | Run the command
106 | ```
107 | npx link /path/to/build/folder/of/firebase-nextjs
108 | ```
109 |
110 | ## Step 4: Use the package
111 |
112 | Now, the package is linked to your project, and it is exactly as if you have installed the package. **Do not add the package name to package.json.**
113 |
114 | To use the package in your project,
115 | You can import the files just like you would form an installed package.
116 |
117 | Example:
118 | ```
119 | import { ProfileButton } from "firebase-nextjs/client/components";
120 | ```
121 |
122 | To use the npx script
123 | You can run the npx script as usual, and the code in your build folder will be used.
124 | ```
125 | npx firebase-nextjs getenv
126 | ```
127 |
128 | ## Step 5: Modifications
129 |
130 | After you make any modification to the source code, run
131 | ```
132 | npm run build
133 | ```
134 | Thats it and your project will be using the newly built package.
135 |
136 | ## NOTE: Installing other packages
137 |
138 | Whenever you use the command `npm install packagename` to install any package, the npx link will be removed.
139 | Re run the npx command to link to the build directory again.
140 |
141 | ## Contributing
142 |
143 | If you have done any modification that might be useful to others, you are welcome to create a pull request and become a contributor.
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
--------------------------------------------------------------------------------
/TERMS_OF_SERVICE.md:
--------------------------------------------------------------------------------
1 | ### Terms of Service
2 |
3 | #### Introduction
4 |
5 | Welcome to `next-fire-js`. By using our package, you agree to comply with and be bound by the following terms and conditions. Please read these terms carefully before using `next-fire-js`.
6 |
7 | #### Use of Package
8 |
9 | `next-fire-js` is provided as an open-source tool to facilitate the integration of Firebase Authentication with Next.js applications. By using this package, you agree to adhere to all applicable laws and regulations.
10 |
11 | #### No Guarantees
12 |
13 | `next-fire-js` is provided "as is" without any guarantees or warranties of any kind. We do not guarantee that the package will meet your requirements, be error-free, or operate without interruptions.
14 |
15 | #### Disclaimer of Warranties
16 |
17 | To the fullest extent permitted by applicable law, `next-fire-js` disclaims all warranties, express or implied, including, but not limited to, implied warranties of merchantability, fitness for a particular purpose, and non-infringement. We do not warrant that the package will be free from defects or that any defects will be corrected.
18 |
19 | #### Limitation of Liability
20 |
21 | In no event shall `next-fire-js` or its contributors be liable for any direct, indirect, incidental, special, consequential, or punitive damages arising out of your use of, or inability to use, the package, even if advised of the possibility of such damages.
22 |
23 | #### Indemnification
24 |
25 | You agree to indemnify and hold harmless `next-fire-js`, its contributors, and its affiliates from and against any and all claims, liabilities, damages, losses, or expenses arising out of or in any way connected with your use of the package.
26 |
27 | #### Changes to Terms
28 |
29 | We reserve the right to modify these terms of service at any time. Any changes will be posted on this page, and the updated date will be indicated at the top of the terms. Your continued use of `next-fire-js` after any changes signifies your acceptance of the updated terms.
30 |
31 | #### Governing Law
32 |
33 | These terms shall be governed by and construed in accordance with the laws of India, without regard to its conflict of law principles.
34 |
35 | #### Contact Us
36 |
37 | If you have any questions or concerns about these terms of service, please contact us at [scaria@scaria.dev].
38 |
39 | ---
40 |
41 | **Effective Date**: July 4, 2024
42 |
43 | **Last Updated**: July 4, 2024
44 |
45 | By using `next-fire-js`, you acknowledge that you have read and understood these terms of service and agree to be bound by them.
46 |
--------------------------------------------------------------------------------
/auth-actions.ts:
--------------------------------------------------------------------------------
1 | import { auth } from "./firebasenextjs-firebase";
2 | import {
3 | createUserWithEmailAndPassword,
4 | signInWithEmailAndPassword,
5 | sendPasswordResetEmail,
6 | sendEmailVerification,
7 | updatePassword,
8 | signInWithPopup,
9 | GoogleAuthProvider,
10 | } from "firebase/auth";
11 |
12 | export const doCreateUserWithEmailAndPassword = async (email: string, password: string) => {
13 | return createUserWithEmailAndPassword(auth, email, password);
14 | };
15 |
16 | export const doSignInWithEmailAndPassword = (email: string, password: string) => {
17 | return signInWithEmailAndPassword(auth, email, password);
18 | };
19 |
20 | export const doSignInWithGoogle = async () => {
21 | const provider = new GoogleAuthProvider();
22 | const result = await signInWithPopup(auth, provider);
23 | return result;
24 | };
25 |
26 | export async function doSignOut({ persist }: { persist: boolean }) {
27 | await auth.signOut();
28 | if (persist) {
29 | window.location.reload();
30 | }
31 | else {
32 | window.location.href = "/";
33 | }
34 | }
35 |
36 | export const doPasswordReset = (email: string) => {
37 | return sendPasswordResetEmail(auth, email);
38 | };
39 |
40 | export const doPasswordChange = (password: string) => {
41 | return updatePassword(auth.currentUser!, password);
42 | };
43 |
44 | export const doSendEmailVerification = () => {
45 | return sendEmailVerification(auth.currentUser!, {
46 | url: `${window.location.origin}/home`,
47 | });
48 | };
49 |
--------------------------------------------------------------------------------
/client/AuthPages.jsx:
--------------------------------------------------------------------------------
1 | import ForgotPasswordPage from "/components/firebase-nextjs/ForgotPasswordPage";
2 | import LoginPage from "/components/firebase-nextjs/LoginPage";
3 | import RegisterPage from "/components/firebase-nextjs/RegisterPage";
4 | export default async function AuthPages({ searchParams }) {
5 | const path = searchParams.path;
6 | if (path == "/login") {
7 | return
8 | }
9 | if (path == "/register") {
10 | return
11 | }
12 | if (path == "/forgot-password") {
13 | return
14 | }
15 | }
--------------------------------------------------------------------------------
/client/ProfileButtonStyle.css:
--------------------------------------------------------------------------------
1 | .profileLogout {
2 | padding-left: 13px;
3 | padding-right: 13px;
4 | padding-top: 13px;
5 | padding-bottom: 10px;
6 | font-size: 14px;
7 | font-weight: 400;
8 | color: #000000aa;
9 | cursor: pointer;
10 | display: flex;
11 | flex-direction: row;
12 | gap: 5px;
13 | justify-items: center;
14 | background-color: transparent;
15 | transition: all 0.3s;
16 | }
17 |
18 | .profileLogout:hover {
19 | color: #000000;
20 | background-color: #00000009;
21 | }
--------------------------------------------------------------------------------
/client/auth.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | import React, { useContext, useState, useEffect } from "react";
3 | import { auth } from "../firebasenextjs-firebase";
4 | import { onAuthStateChanged } from "firebase/auth";
5 | import { User } from "firebase/auth";
6 | import { getToken } from "../server/getToken";
7 |
8 | type FirebaseNextJSContextType = {
9 | userLoggedIn: boolean;
10 | isEmailUser: boolean;
11 | currentUser: User | null;
12 | };
13 |
14 | const FirebaseNextJSContext = React.createContext({
15 | userLoggedIn: false,
16 | isEmailUser: false,
17 | currentUser: null,
18 | } as FirebaseNextJSContextType);
19 |
20 | export function getUserCS() {
21 | return useContext(FirebaseNextJSContext);
22 | }
23 |
24 | export function FirebaseNextJSProvider({ children }: { children: React.ReactNode }) {
25 | const [currentUser, setCurrentUser] = useState(null);
26 | const [userLoggedIn, setUserLoggedIn] = useState(false);
27 | const [isEmailUser, setIsEmailUser] = useState(false);
28 | const [loading, setLoading] = useState(true);
29 |
30 | useEffect(() => {
31 | const unsubscribe = onAuthStateChanged(auth, initializeUser);
32 | return unsubscribe;
33 | }, []);
34 |
35 | async function initializeUser(user: User | null) {
36 | if (user) {
37 |
38 |
39 | const isEmail = user.providerData.some(
40 | (provider) => provider.providerId === "password"
41 | );
42 | setIsEmailUser(isEmail);
43 |
44 | user.getIdToken(true).then(async function (idToken) {
45 | const sessionToken = await getToken({ idToken });
46 | document.cookie = `firebase_nextjs_token=${sessionToken}; expires=${new Date(Date.now() + 3600 * 1000 * 24 * 14).toUTCString()}; path=/;`;
47 | }).catch(async function (error) {
48 | console.error(error)
49 | console.error("FAILED TO GET ID TOKEN")
50 | // document.cookie = "firebase_nextjs_token=";
51 | // await auth.signOut();
52 | // window.location.reload();
53 | });
54 |
55 | setCurrentUser({ ...user });
56 | setUserLoggedIn(true);
57 | } else {
58 | setCurrentUser(null);
59 | setUserLoggedIn(false);
60 | document.cookie = "firebase_nextjs_token=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/;";
61 | }
62 |
63 | setLoading(false);
64 | }
65 |
66 | const value = {
67 | userLoggedIn,
68 | isEmailUser,
69 | currentUser
70 | };
71 |
72 | return (
73 |
74 | {loading ? : children}
75 |
76 | );
77 | }
78 |
--------------------------------------------------------------------------------
/client/components.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | import "./ProfileButtonStyle.css";
3 | import { doSignOut } from "../auth-actions";
4 | import { GoogleAuthProvider, GithubAuthProvider, signInWithPopup, signInWithEmailAndPassword, createUserWithEmailAndPassword, User, signInWithRedirect } from "firebase/auth";
5 | import { auth } from "../firebasenextjs-firebase";
6 | import { getUserCS } from "./auth";
7 | import { decodeFirebaseError } from "./getFirebaseErrors";
8 | import React, { useState } from "react";
9 | import { Popover, PopoverPosition } from "react-tiny-popover";
10 |
11 | /**
12 | *
13 | * @param children - The component that should trigger the sign out.
14 | * @param persistRoute [Optional] - If true, the the user will be redirected to the same page after logging back in. Default is false.
15 | * @returns
16 | */
17 | export function LogoutButton({ children, persistRoute }: { children: React.ReactNode, persistRoute?: boolean }) {
18 | function signOutAction() {
19 | doSignOut({ persist: persistRoute ?? false })
20 | }
21 | return
{children}
22 | }
23 |
24 | export function LoggedInContent({ children }: { children: React.ReactNode }) {
25 | const { currentUser } = getUserCS();
26 | return currentUser ? <>{children}> : null;
27 | }
28 |
29 | export function LoggedOutContent({ children }: { children: React.ReactNode }) {
30 | const { currentUser } = getUserCS();
31 | return currentUser ? null : <>{children}>;
32 | }
33 |
34 |
35 | /**
36 | *
37 | * !! IMPORTANT !!
38 | * If using redirect method, additional configuration is required. Read examples below for more details.
39 | * @param children - The component that should trigger the sign in with Google. If not provided, a default button will be shown.
40 | * @param className - The class name of the button
41 | * @param method - The method of sign in. Can be "popup" or "redirect". Default is "popup". Read examples for more details.
42 | *
43 | * @returns A component that triggers the sign in with Google.
44 | *
45 | * @example
46 | * // 1. Using default UI and popup
47 | * // -------------------------------------
48 | *
49 | *
50 | * @example
51 | * // 2. Custom UI and popup
52 | * // -------------------------------------
53 | *
54 | *
55 | *
56 | *
57 | * @example
58 | * // 3. Using redirect
59 | * // -------------------------------------
60 | *
61 | *
62 | *
63 | * // SETUP (Required only for redirect method):
64 | * // 1. Go to Firebase Console > Authentication > Settings > Authorized Domains
65 | * // 2. Add your domain. (Add "localhost" to test locally).
66 | * // 3. Open "firebase-app-config.json" and copy the authDomain value. (Ex: "your-app.firebaseapp.com")
67 | * // 4. Edit nextjs.config.mjs and add the rewrite rules as shown below.
68 | *
69 | * // nextjs.config.mjs
70 | * const nextConfig = {
71 | * async rewrites() {
72 | * return [
73 | * {
74 | * source: '/__/auth/:path*',
75 | * destination: 'https://your-app.firebaseapp.com/__/auth/:path*',
76 | * },
77 | * ];
78 | * }
79 | *};
80 | *
81 | * export default nextConfig;
82 | *
83 | * // 5. Edit firebase-app-config.json and change the authDomain value to your app's domain.
84 | * // Example: "authDomain": "your-website.com"
85 | * // If locally: "authDomain": "localhost:3000"
86 | *
87 | * // 6. Enforce https. (Required)
88 | * // For localhost, this can be done by changing "next dev" in package.json to "next dev --experimental-https"
89 | *
90 | * // If you come across any issue, please file the issue on GitHub.
91 | * @link https://github.com/NirmalScaria/firebase-nextjs
92 | *
93 | */
94 | export function GoogleSignInButton({ children, className, method = "popup" }: { children?: React.ReactNode, className?: string, method?: "popup" | "redirect" }) {
95 | const doSignInWithGoogle = async () => {
96 | const provider = new GoogleAuthProvider();
97 | const resp = await signInWithPopup(auth, provider);
98 | if (resp) {
99 | setTimeout(() => {
100 | window.location.reload();
101 | }, 2500);
102 | }
103 | };
104 |
105 | const doSignInWithGoogleRedirect = async () => {
106 | const provider = new GoogleAuthProvider();
107 | signInWithRedirect(auth, provider);
108 | };
109 |
110 | function GoogleLogo({ height = 24, width = 24, ...props }) {
111 | return
112 | }
113 |
114 | return