Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/thirdweb-example/firebase-auth
Integrate sign in with Ethereum using thirdweb Auth into your Firebase application
https://github.com/thirdweb-example/firebase-auth
auth firebase web2
Last synced: about 1 month ago
JSON representation
Integrate sign in with Ethereum using thirdweb Auth into your Firebase application
- Host: GitHub
- URL: https://github.com/thirdweb-example/firebase-auth
- Owner: thirdweb-example
- License: apache-2.0
- Created: 2022-09-09T03:34:01.000Z (over 2 years ago)
- Default Branch: main
- Last Pushed: 2024-04-12T00:25:40.000Z (9 months ago)
- Last Synced: 2024-04-12T07:11:49.397Z (9 months ago)
- Topics: auth, firebase, web2
- Language: TypeScript
- Homepage: https://firebase-auth.thirdweb-example.com/
- Size: 290 KB
- Stars: 17
- Watchers: 1
- Forks: 10
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE.md
Awesome Lists containing this project
README
> [!Important]
> This repository is referencing the `mumbai` chain.
>
> `Mumbai` [is deprecated since 08/04/2024](https://blog.thirdweb.com/deprecation-of-mumbai-testnet/), meaning the code in this repository will no longer work out of the box.
>
> You can still use this repository, however you will have to switch any references to `mumbai` to another chain.# thirdweb Auth + Firebase
This template shows you can use thirdweb Auth as a custom authentication provider for Firebase, and automatically create a document in the `users` Firestore collection when a user signs up successfully.
## Pre-requisites
- [Create a Firebase project](https://firebase.google.com/docs/web/setup#create-project)
- [Register your Firebase app](https://firebase.google.com/docs/web/setup#register-app)
- [Create and export a service account as a JSON file](https://firebase.google.com/docs/admin/setup#initialize-sdk)
- Make sure to enable Firebase Authentication as we'll be using the [Custom Authentication](https://firebase.google.com/docs/auth/web/custom-auth?hl=en&authuser=0) method and create a [Cloud Firestore](https://firebase.google.com/docs/firestore/quickstart?hl=en&authuser=0) database within your project.## Set Up
To begin with, let's create a new Next.js project with the SDK configured:
```bash
npx thirdweb create app --next --ts
```From within the created directory, we need to install `@thirdweb-dev/auth`, `firebase` and `firebase-admin`:
```bash npm2yarn
npm install @thirdweb-dev/auth firebase firebase-admin
```### Configure Firebase
We'll use environment variables to store our Firebase configuration.
Create a `.env.local` file in the root of your project and add the corresponding values from your Firebase project:
```
NEXT_PUBLIC_API_KEY=
NEXT_PUBLIC_AUTH_DOMAIN=
NEXT_PUBLIC_PROJECT_ID=
NEXT_PUBLIC_STORAGE_BUCKET=
NEXT_PUBLIC_MESSAGING_SENDER_ID=
NEXT_PUBLIC_APP_ID=
FIREBASE_PRIVATE_KEY=
FIREBASE_CLIENT_ID=
FIREBASE_PRIVATE_KEY_ID=
FIREBASE_CLIENT_EMAIL=
```Most of the above environment variables can be found in the settings page of your Firebase project (after adding a Web app to your project), or in the service role JSON file you created and downloaded earlier.
Create a new directory called `lib` and create two helper scripts to initialize Firebase in the browser and server:
- [lib/initFirebase.ts](https://github.com/thirdweb-example/firebase-auth/blob/main/lib/initFirebase.ts)
- [lib/initFirebaseAdmin.ts](https://github.com/thirdweb-example/firebase-auth/blob/main/lib/initFirebaseAdmin.ts)Now we have an easy way to access Firebase Auth and Firestore in both client and server environments!
### Configure thirdweb Auth
Finally, to configure thirdweb Auth, we just need to add the `NEXT_PUBLIC_THIRDWEB_AUTH_DOMAIN` evironment variable to the `.env.local` file as follows:
```
NEXT_PUBLIC_THIRDWEB_AUTH_DOMAIN=
```The `NEXT_PUBLIC_THIRDWEB_AUTH_DOMAIN` is used to prevent phishing attacks - and is usually set to the domain of your project like `example.com`. You can read more about it in the [thirdweb Auth Documentation](https://portal.thirdweb.com/auth/how-auth-works/sign-in-with-wallet#domain).
### ThirdwebProvider
Inside the `pages/_app.tsx` file, configure the `authConfig` option:
```ts title="pages/_app.tsx"
import type { AppProps } from "next/app";
import { ThirdwebProvider } from "@thirdweb-dev/react";// This is the chain your dApp will work on.
const activeChain = "mumbai";function MyApp({ Component, pageProps }: AppProps) {
return (
);
}export default MyApp;
```## Sign Up / Log In Users
The process of creating users in Firebase by authenticating them with their wallet has two steps:
1. Authenticate the user with their wallet
2. Create a user in Firebase with the knowledge that they own this walletOn the homepage (`pages/index.tsx`), we'll allow the user to connect their wallet and then sign in with Ethereum.
```tsx title="pages/index.tsx"
import React from "react";
import { ConnectWallet, useAddress, useAuth } from "@thirdweb-dev/react";
import { doc, serverTimestamp, setDoc } from "firebase/firestore";
import { signInWithCustomToken } from "firebase/auth";
import initializeFirebaseClient from "../lib/initFirebase";export default function Login() {
const thirdwebAuth = useAuth();
const address = useAddress();
const { auth, db } = initializeFirebaseClient();return (
{address ? (
signIn()}>Sign in with Wallet
) : (
)}
);
}
```The `signIn` function:
1. Makes a request to the `api/auth/login` endpoint to get a custom token from Firebase
2. Signs the user in with the custom token
3. Creates a user in Firestore with the verified user's address```tsx title="pages/index.tsx"
// Note: This function lives inside the Login component above.
const signIn = async () => {
// Use the same address as the one specified in _app.tsx.
const payload = await thirdwebAuth?.login();try {
// Make a request to the API with the payload.
const res = await fetch("/api/auth/login", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ payload }),
});// Get the returned JWT token to use it to sign in with
const { token } = await res.json();// Sign in with the token.
const userCredential = await signInWithCustomToken(auth, token);
// On success, we have access to the user object.
const user = userCredential.user;// If this is a new user, we create a new document in the database.
const usersRef = doc(db, "users", user.uid!);
const userDoc = await getDoc(usersRef);if (!userDoc.exists()) {
// User now has permission to update their own document outlined in the Firestore rules.
setDoc(usersRef, { createdAt: serverTimestamp() }, { merge: true });
}
} catch (error) {
console.error(error);
}
};
```In this function, you'll notice we're calling the `/api/auth/login` endpoint to get a
[custom JWT token from Firebase](https://firebase.google.com/docs/auth/admin/create-custom-tokens#create_custom_tokens_using_the_firebase_admin_sdk).Let's take a look at that API route.
### Auth API Route
Create a folder that lives in the `/pages/api/auth` directory called `login.ts`.
This API route is responsible for:
1. Verifying the payload provided by the client
2. Once the payload is verified, creating a [custom token](https://firebase.google.com/docs/auth/admin/create-custom-tokens#create_custom_tokens_using_the_firebase_admin_sdk)
for the user to sign in to Firebase with.```ts title="pages/api/auth/login.ts"
import { NextApiRequest, NextApiResponse } from "next";
import { verifyLogin } from "@thirdweb-dev/auth/evm";
import initializeFirebaseServer from "../../../lib/initFirebaseAdmin";const login = async (req: NextApiRequest, res: NextApiResponse) => {
// Grab the login payload the user sent us with their request.
const payload = req.body.payload;const { address, error } = await verifyLogin(
process.env.NEXT_PUBLIC_THIRDWEB_AUTH_DOMAIN as string,
payload
);
if (!address) {
return res.status(401).json({ error });
}// Initialize the Firebase Admin SDK.
const { auth } = initializeFirebaseServer();// Generate a JWT token for the user to be used on the client-side.
const token = await auth.createCustomToken(address);// Send the token to the client-side.
return res.status(200).json({ token });
};export default login;
```You'll now be able to use Firebase Authentication to authenticate users with their wallets!
### Firestore Rules (Optional)
You'll likely want to add a [security rule](https://firebase.google.com/docs/firestore/security/get-started)
to your Firestore database that only allows users to update their documents.```cel title="firestore.rules"
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// The wildcard expression {userId} makes the userId variable available in rules.
match /users/{userId} {
// Only allow users to update their own documents.
allow create, update, delete: if request.auth != null && request.auth.uid == userId;
// But anybody can read their profile.
allow read;
}
}
}
```### Viewing the Result
When you click the "Sign in with Ethereum" button and successfully sign in, you'll be signed up as a user in Firebase and a new document will be created in your `users` collection in Firestore:
You can now use all the functionality of Firebase Authentication and Firestore to build your app!
## What's Next?
- [Get the current Firebase user](https://github.com/thirdweb-example/firebase-auth/blob/main/lib/useFirebaseUser.ts)
- [Read the current user's document from Firestore](https://github.com/thirdweb-example/firebase-auth/blob/main/lib/useFirebaseUserDocument.ts)
- [Sign out](https://github.com/thirdweb-example/firebase-auth/blob/main/pages/index.tsx#L84-L89)