If you’ve been using Moralis for a while, then you know that the transition to Moralis 2.0 is making Moralis servers obsolete. Instead, Moralis is introducing support for self-hosted servers. As a result, devs can now set up a self-hosted Parse Server and utilize Moralis with it. Furthermore, this article illustrates how you can effortlessly set up a self-hosted Parse Server. As we move forward herein, we will initiate this article by setting up a Parse Server first. Then, we will set up the server’s dashboard to access the database. Then finally, we will also integrate Moralis Web3 authentication with the self-hosted Parse Server. Nonetheless, we’re also aware that some of you have no idea what a Parse Server is. So, we will start our discussion by first addressing the basics!
Moralis is the ultimate Web3 development platform. In August 2022, this incredible tool released its renewed version that primarily focuses on three core Web3 features. That includes Web3 authentication, Web3 syncs, and Web3 APIs. Furthermore, a free Moralis account is all you need to utilize all these three features. Moreover, Moralis continues to be all about cross-chain interoperability, and the platform already supports most of the leading programmable blockchains and adds new reputable chains continuously. Also, Moralis even doubled down on its cross-platform interoperability. As such, it now enables you to use any of the legacy development platforms to add Web3 functionality. Hence, creating dapps has never been easier. Speaking of easy, setting up a self-hosted Parse Server and integrating it with Moralis is also not rocket science. Just create your free Moralis account and follow our lead.
What is a Parse Server?
Parse is the originator of Parse Server, an open-source backend as a service framework. It can be deployed to any infrastructure capable of running NodeJS. You can easily deploy and run Parse Server in your own infrastructure. Hence, you can develop and test your applications locally using NodeJS. Moreover, Parse Server uses MongoDB or PostgreSQL as a database.
Aside from accessing Parse Server locally, you can deploy it to a cloud service provider and access it from anywhere and make your app accessible publicly. However, it is imperative to correctly adapt your Parse Server configuration before making it accessible publicly. For more details, make sure to dive deeper into the Parse Server documentation.
What is a Self-Hosted Server?
In order for you to fully understand the meaning of a “self-hosted Parse Server”, let’s also look at what a self-hosted server is. In short, “self-hosted” is an adjective derived from the activity of self-hosting. The latter refers to the act of having and administrating your own server, typically at home. This means hosting your personal data and services instead of relying on third parties. Moreover, self-hosted servers are normally used to host and manage applications. So, a self-hosted Parse Server is a Parse Server that you host yourself locally.
Now that you know what a self-hosted Parse Server is, let’s focus on the tutorial. As mentioned in the introduction, we will show you how to set up Parse Server, its dashboard to access a database, and how to integrate Moralis’ Web3 Auth API. As a result of this tutorial, you will be able to build a simple example dapp. The latter will be able to authenticate users with MetaMask. Moreover, here’s a screenshot of this demo dapp:
As you can see in the image above, our example dapp includes the “Demo Auth parse-server” title and the “Authenticate via MetaMask” button. When users click that button, the backend code prompts users’ MetaMask extensions with our signature request. Hence, users must click the “Sign” button to complete their Web3 login. Furthermore, once authenticated, users get to see their wallets’ details:
As indicated by the above screenshot, our dapp solely focuses on providing functionality. Hence, we didn’t create a neat UI to display the details or utilize the on-chain data in a unique way. We leave it up to you to explore those possibilities. After all, the main goal of this tutorial is to help you set up a self-hosted Parse Server, which includes a database that indexes user logins:
If you look at the screenshot of our demo dapp, you will see that the ID matches the example user:
Hopefully, the above-presented functionality impresses you. If so, you are probably eager to set up a self-hosted Parse Server and implement Moralis’ Web3 Auth API. So, let’s roll up our sleeves and get to it. Nonetheless, it’s worth pointing out that we’ll be building with Express, which is a web framework for NodeJS.
Set Up a Self-Hosted Parse Server
For starters, you need to install the Parse Server package. To do this, use the “yarn add parse-server” command. Then, you need to initialize your Parse Server. As such, create the “parseServer.ts” file and add the following lines of code:
import { ParseServer } from 'parse-server'; export const parseServer = new ParseServer({ databaseURI: config.DATABASE_URI, // Connection string for your MongoDB database cloud: config.CLOUD_PATH, // Absolute path to your Cloud Code appId: config.APPLICATION_ID, // Application ID masterKey: config.MASTER_KEY, // Master key serverURL: config.SERVER_URL, // Server URL });
Now that you’ve initialized your self-hosted Parse Server, it’s time for you to set up your server’s dashboard. Moreover, the latter will enable you to access your database.
Set Up a Self-Hosted Parse Server’s Dashboard
As mentioned above, if you want to access the database, you must set up a dashboard. Hence, use the “yarn add parse-dashboard” command. Also, just like you did with your Parse Server, you need to initialize your dashboard following the same steps. Thus, create the “parseDashboard.ts” file and paste in these lines of code:
import ParseDashboard from 'parse-dashboard'; export const parseDashboard = new ParseDashboard({ apps: [ { appId: config.APPLICATION_ID, // Server Application ID masterKey: config.MASTER_KEY, // Server Master Key serverURL: config.SERVER_URL, // Server URL appName: config.APP_NAME, // Application Name }, ], });
With your self-hosted Parse Server and its dashboard ready, it’s time to integrate Moralis Web3 authentication.
Integrating Moralis Web3 Auth with Parse Server
So, you’re now at the point where you will learn how to integrate the Moralis Web3 Auth API. Furthermore, in this section, your goal will be to have the ability to authenticate users with MetaMask. You also want your self-hosted Parse Server to index authenticated users, as demonstrated above. Also, thanks to the power and simplicity of the Moralis Web3 Auth API, you will not have to worry about your Web3 authentication flow at all. Moreover, you will leverage Parse Server’s 0Auth support to create your custom authentication.
To start the integration process, first install the Moralis SDK using the “yarn add moralis” command. Next, initialize Moralis with these lines of code:
import Moralis from 'moralis'; Moralis.start({ apiKey: 'your_api_key_here', });
Of course, you must replace “your-api-key_here” with your actual Moralis Web3 API key.
Obtain Your Moralis Web3 API Key
In order to get your Moralis Web3 API key, you must first create your free Moralis account. Hence, use the “create your free Moralis account” stated at the outset or visit the Moralis homepage. Moreover, if you decide to visit the homepage, you’ll see the “Start for Free” button as indicated here:
On the next page, you will need to enter your credentials. Also, don’t forget to confirm your account by clicking on the confirmation link that will be sent to your email inbox. So, with your account created, you’ll get to access your Moralis admin area (see the image below). In addition, you’ll need to click on the profile icon in the top-right corner. Moreover, select the “Account Settings” option from the drop-down menu:
Once on the “Account Settings” page, click on the “Keys” tab. Finally, you’ll get to copy your Moralis Web3 API key by using the “copy” icon next to “Web3 Api Key”:
Now replace “your-api-key_here” with your key.
Create Your Authentication Adapter
So, with the Moralis SDK installed and initiated, you must create your own authentication adapter. Moreover, the latter will verify authentication requests in combination with the Moralis Web3 Auth API. Accordingly, create the “MoralisAuthAdapter.ts” file and populate it with the following lines of code:
function validateAuthData(authData: any) { const { message, signature, network, id, authId } = authData; return Moralis.Auth.verify({ message, signature, network, }) .then((result) => { const data = result.toJSON(); if (id === data.profileId && authId === data.id) { authData.chainId = result.result.chain.decimal; authData.nonce = data.nonce; authData.address = result.result.address.checksum; authData.version = data.version; authData.domain = data.domain; authData.expirationTime = data.expirationTime; authData.notBefore = data.notBefore; authData.resources = data.resources; authData.statement = data.statement; authData.uri = data.uri; return; } throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Moralis auth failed, invalid data'); }) .catch(() => { throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Moralis auth failed, invalid data'); }); } function validateAppId() { return Promise.resolve(); } export default { validateAuthData, validateAppId, };
Moreover, in order to properly set up your authentication adapter, you need to add it to your self-hosted Parse Server initializer. As such, update your “parseServer.ts” file accordingly:
import { ParseServer } from 'parse-server'; import MoralisAuthAdapter from './auth/MoralisAuthAdapter'; export const parseServer = new ParseServer({ databaseURI: config.DATABASE_URI, cloud: config.CLOUD_PATH, appId: config.APPLICATION_ID, masterKey: config.MASTER_KEY, serverURL: config.SERVER_URL, auth: { moralis: { module: MoralisAuthAdapter, }, }, });
Note: To avoid confusion, we recommend you follow our lead. Thus, name your authentication adapter “moralis”.
Create Your Authentication Service
With your authentication adapter in place, you also need to create your authentication service. Further, the latter will take care of requesting the message and authentication with Parse Server. So, create the “authService.ts” file and populate it with these lines of code:
import Moralis from 'moralis'; import { authRequests } from '../store'; import { ParseServerRequest } from '../utils/ParseServerRequest'; export async function requestMessage({ address, chain, network }: { address: string; chain: string; network: 'evm' }) { const result = await Moralis.Auth.requestMessage({ address, chain, network, domain: 'defi.finance', statement: 'Please sign this message to confirm your identity.', uri: 'https://defi.finance', expirationTime: '2023-01-01T00:00:00.000Z', timeout: 15, }); const { message, id, profileId } = result.toJSON(); authRequests.set(message, { id, profileId }); return message; } export async function verifyMessage({ network, signature, message }) { const storedData = authRequests.get(message); if (!storedData) { throw new Error('Invalid message'); } const { id: storedId, profileId: storedProfileId } = storedData; const authData = { id: storedProfileId, authId: storedId, message, signature, network, }; // Authenticate const user = await serverRequest.post({ endpoint: `/users`, params: { authData: { moralis: authData, }, }, useMasterKey: true, }); // Update user moralisProfile column await serverRequest.put({ endpoint: `/users/${user.objectId}`, params: { moralisProfileId: storedProfileId, }, useMasterKey: true, }); // Get authenticated user const updatedUser = await serverRequest.get({ endpoint: `/users/${user.objectId}`, useMasterKey: true, }); return updatedUser; }
The “requestMessage” and “verifyMessage” Functions
The code above includes exporting two important functions: “requestMessage” and “verifyMessage“. Further, the former lets you utilize the Moralis Web3 Auth API to request an authentication message. Hence, this gives you a chance to send that message to users. Moreover, they then use their Web3 wallets (e.g., MetaMask) to sign that message. Also, the “requestMessage” function stores “id” and “profileId“, which are the details you’ll use when verifying the message.
On the other hand, the “verifyMessage” function retrieves the stored “id” and “profileId” values and prepares “authData“. The latter will be used in your above-created “moralis” authentication adapter.
Put Everything Together Using Express
These are the lines of code that will tie it all together so that your backend functions correctly:
import Moralis from 'moralis'; import express from 'express'; import cors from 'cors'; import { parseDashboard } from './parseDashboard'; import { parseServer } from './parseServer'; import { errorHandler } from './middlewares/errorHandler'; import config from './config'; const app = express(); Moralis.start({ apiKey: config.MORALIS_API_KEY, }); app.use(express.urlencoded({ extended: true })); app.use(express.json()); app.use(cors()); app.use('/server', parseServer); app.use('/dashboard', parseDashboard); app.use(errorHandler); app.use(express.static('public')); app.listen(config.PORT, () => { console.log(`${config.APP_NAME} is running on port ${config.PORT}`); });
However, if you want to create an example authentication dapp as presented earlier, you also need your client side.
Creating Your Frontend
So, at this point, it’s time to create your frontend. Hence, to make sure that everything functions correctly on the frontend, you need to start by adding the “ethers” and “axios” dependencies:
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script> <script src="https://cdn.ethers.io/lib/ethers-5.2.umd.min.js" type="application/javascript"></script>
Moreover, you need the proper lines of code to retrieve the basic information regarding users’ wallets. Since we decided to use MetaMask, the following does the trick:
const connectToMetamask = async () => { const provider = new ethers.providers.Web3Provider(window.ethereum, 'any'); const [accounts, chainId] = await Promise.all([ provider.send('eth_requestAccounts', []), provider.send('eth_chainId', []), ]); const signer = provider.getSigner(); return { signer, chain: chainId, account: accounts[0] }; };
So, with the final piece of the puzzle in place, you have everything ready to authenticate users with your self-hosted Parse Server. Furthermore, this is the pattern that the authentication flow follows:
- Read basic information about a user’s wallet.
- Your backend function generates a message that needs to be signed by the user.
- The user utilizes MetaMask to sign the message.
- The code sends the signed message to the “verifyMessage” backend function that verifies and authenticates with your Parse Server.
Moreover, this is the function that includes the above-described authentication flow:
const handleAuth = async () => { // Connect to Metamask const { signer, chain, account } = await connectToMetamask(); if (!account) { throw new Error('No account found'); } if (!chain) { throw new Error('No chain found'); } const { message } = await requestMessage(account, chain); const signature = await signer.signMessage(message); const { user } = await verifyMessage(message, signature); renderUser(user); };
Nonetheless, we want you to have the entire code at your disposal. Thus, we made the entire code related to the example project available on GitHub. Explore it, clone it, use it!
How to Set Up a Self-Hosted Parse Server – Summary
We covered quite a distance in this article. We started by ensuring that you all knew what a self-hosted Parse Server is. Then, we showed you how to set it up. You also learned how to set up your Parse Server’s dashboard. We also spiced things up by demonstrating how to integrate Web3 authentication with your Parse Server. Furthermore, this is where you used the power of Moralis and created your own auth adapter and auth service. Finally, you tied your backend together using Express. Last but not least, you also created a simple frontend to actually utilize your new self-hosted Parse Server. As a result, you now know how to set up your Parse Server and use that excellent tool with Moralis. Accordingly, you are ready to start creating some killer dapps.
However, if this was your first rodeo with Web3 development, we recommend you devote some time to practice. Hence, this is where the Moralis blog and the Moralis YouTube channel simplify things. Furthermore, both of these outlets host countless tutorials. In short, they can teach you how to create all sorts of dapps the easy way. Moreover, along the way, you will also learn how to make the most of Moralis and save a ton of development time. Additionally, don’t forget to explore the Moralis documentation, which is a good place to start.
On the other hand, you may be interested in going full-time crypto sooner rather than later. If so, make sure to consider enrolling in Moralis Academy. Aside from top-notch crypto development courses, Moralis Academy is the place to meet some amazing Web3 developers and entrepreneurs. Nonetheless, this is where you can get expert mentorship to overcome any challenges easily.