Skip to content

Commit

Permalink
feat: add Auth package and parse-server demo
Browse files Browse the repository at this point in the history
* feat: add Auth package and parse-server demo

chore: remove logs

fix: update statement

docs: update changeset

chore: cleanup

* chore: revert debug changes

* deleted empty file.

* chore: cleanup and improvements

* chore: fixes after merge and refactor

* style: ignore formatting on generated code

Co-authored-by: Bart Tadych <[email protected]>
  • Loading branch information
ErnoW and b4rtaz authored Jul 20, 2022
1 parent 8b8cc4c commit 7f0fc3f
Show file tree
Hide file tree
Showing 61 changed files with 16,648 additions and 106 deletions.
9 changes: 9 additions & 0 deletions .changeset/green-avocados-hear.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
'demo-parse-server-auth-server': minor
'@moralisweb3/test-node': minor
'@moralisweb3/auth': minor
'@moralisweb3/core': minor
'moralis': minor
---

Add Moralis.Auth package to handle authentication via the Moralis Authentication Api. And add a demo project for parse-server
2 changes: 1 addition & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module.exports = {
parser: '@typescript-eslint/parser',
plugins: ['@typescript-eslint', 'jest'],
extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended'],
ignorePatterns: ['**/lib/**/*', '**/*.test.ts', '**/dist/**/*', '**/build/**/*'],
ignorePatterns: ['**/lib/**/*', '**/*.test.ts', '**/dist/**/*', '**/build/**/*', '**/generated/**/*
env: {
browser: true,
es6: true,
Expand Down
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,17 @@ packages/**/lib.esm
packages/**/coverage
coverage/

demos/**/lib
demos/**/build
demos/**/dist


logs/


# Typescript
packages/**/tsconfig.tsbuildinfo
demos/**/tsconfig.tsbuildinfo

# Test coverage
packages/**/coverage
Expand Down
2 changes: 1 addition & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ lib/**/*
dist
coverage/
lib.esm
node_modules
node_modules
16 changes: 16 additions & 0 deletions demos/demo-parse-server-auth/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@

PORT = 1337;

MORALIS_API_KEY = ''

DATABASE_URI = 'mongodb://localhost:27017'

CLOUD_PATH = './cloud/main.js'
APP_NAME = 'Demo Parse Server Auth'

SERVER_ENDPOINT = 'server'
MASTER_KEY = 'MASTER_KEY'
APPLICATION_ID = 'APPLICATION_ID'
SERVER_URL = 'http://localhost:1337/server'

ALLOW_INSECURE_HTTP = 'true'
17 changes: 17 additions & 0 deletions demos/demo-parse-server-auth/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Demo parse-server Auth

## Run locally

1. Run a mongo-db via `yarn dev:db-start` or run your a mongo-db in any other way
2. Copy `.env.example` to `.env` and fill in the values
3. Change the `API_URL` in `public/script.js` to the url of the server api
4. Run `yarn dev` to run the server locally

Now your server is running locally with the following endpoints:

- Client: `localhost:1337` (or any other port you set in `.env`)
- Parse Server: `localhost:1337/server` (or any other port/endpoint you set in `.env`)
- Parse Dashboard: `localhost:1337/dashboard` (or any other port you set in `.env`)
- API: `localhost:1337/api` (or any other port you set in `.env`)

Now you can authenticate via MetaMask as long as you have the MetaMask browser extention installed in the browser.
Empty file.
26 changes: 26 additions & 0 deletions demos/demo-parse-server-auth/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"name": "demo-parse-server-auth-server",
"version": "2.0.0-alpha.2",
"main": "dist/index.js",
"private": true,
"dependencies": {
"dotenv": "^16.0.1",
"envalid": "7.3.1",
"express": "^4.18.1",
"parse-dashboard": "^4.1.4",
"parse-server": "^5.2.4",
"moralis": "^2.0.0-alpha.2",
"@moralisweb3/core": "^2.0.0-alpha.2"
},
"devDependencies": {
"mongodb-runner": "^4.9.0",
"ts-node": "^10.9.1",
"typescript": "^4.7.4"
},
"scripts": {
"dev": "ts-node src/index.ts",
"build": "tsc",
"dev:db-start": "mongodb-runner start",
"dev:db-stop": "mongodb-runner stop"
}
}
27 changes: 27 additions & 0 deletions demos/demo-parse-server-auth/public/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Demo Auth parse-server</title>
<link rel="stylesheet" href="styles.css" />
<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>
</head>
<body>
<header>
<h1>Demo Auth parse-server</h1>
</header>
<main>
<button class="btn" id="auth-metamask">Authenticate via Metamask</button>
<div id="user"></div>
</main>

<!-- Fix for undefined export: https://bobbyhadz.com/blog/typescript-uncaught-referenceerror-exports-is-not-defined -->
<script>
var exports = {};
</script>
<script src="script.js"></script>
</body>
</html>
71 changes: 71 additions & 0 deletions demos/demo-parse-server-auth/public/script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
const AUTH_API_URL = 'http://localhost:1337/api/auth';

const handleApiPost = async (endpoint, params) => {
const result = await axios.post(`${AUTH_API_URL}/${endpoint}`, params, {
headers: {
'content-type': 'application/json',
},
});

return result.data;
};

const requestMessage = (account, chain) =>
handleApiPost('request-message', {
address: account,
chain: chain,
network: 'evm',
});

const verifyMessage = (message, signature) =>
handleApiPost('sign-message', {
message,
signature,
network: 'evm',
});

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] };
};

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);
};

const renderUser = (user) => {
document.getElementById('user').innerHTML = user ? JSON.stringify(user, null, 2) : '';
};

function init() {
document.getElementById('auth-metamask').addEventListener('click', async () => {
handleAuth();
});
}

window.addEventListener('load', () => {
init();
});
31 changes: 31 additions & 0 deletions demos/demo-parse-server-auth/public/styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
html {
font-family: 'Roboto', sans-serif;
}

h1 {
font-size: 2.4rem;
color: rgb(4, 24, 54);
}

.btn {
background-color: #20c8a0;
color: #041836;
border: none;
border-radius: 0.3rem;
padding: 0.8rem 1.5rem;
font-size: 1.2rem;
cursor: pointer;
color: #fff;
}

.btn:hover {
background-color: #16ecb3;
}

#user {
padding: 2rem;
white-space: pre;
line-height: 1.2;
font-size: 1rem;
color: rgb(4, 24, 54);
}
6 changes: 6 additions & 0 deletions demos/demo-parse-server-auth/src/apiRouter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import express from 'express';
import { authRouter } from './auth/authRouter';

export const apiRouter = express.Router();

apiRouter.use('/auth', authRouter);
44 changes: 44 additions & 0 deletions demos/demo-parse-server-auth/src/auth/MoralisAuthAdapter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Note: do not import Parse dependency. see https://github.com/parse-community/parse-server/issues/6467
import Moralis from 'moralis';

function validateAuthData(authData: any) {
const { message, signature, network, id, authId } = authData;

return Moralis.Auth.verify({
message: message,
signature: signature,
network: 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;
}

// @ts-ignore (see note at top of file)
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Moralis auth failed, invalid data');
})
.catch(() => {
// @ts-ignore (see note at top of file)
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Moralis auth failed, invalid data');
});
}

function validateAppId() {
return Promise.resolve();
}

export default {
validateAuthData,
validateAppId,
};
34 changes: 34 additions & 0 deletions demos/demo-parse-server-auth/src/auth/authController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { requestMessage, verifyMessage } from './authService';
import { NextFunction, Request, Response } from 'express';

export async function request(req: Request, res: Response, next: NextFunction) {
try {
const { address, chain, network } = req.body;

const message = await requestMessage({
address,
chain,
network,
});

res.status(200).json({ message });
} catch (err) {
next(err);
}
}

export async function verify(req: Request, res: Response, next: NextFunction) {
try {
const { network, message, signature } = req.body;

const user = await verifyMessage({
network,
message,
signature,
});

res.status(200).json({ user });
} catch (err) {
next(err);
}
}
7 changes: 7 additions & 0 deletions demos/demo-parse-server-auth/src/auth/authRouter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import express from 'express';
import { verify, request } from './authController';

export const authRouter = express.Router();

authRouter.route('/request-message').post(request);
authRouter.route('/sign-message').post(verify);
Loading

0 comments on commit 7f0fc3f

Please sign in to comment.