Hi @johnversus, thanks for the response - I’m still attempting to find out how to add a custom provider for the auth using the new Moralis Auth API and the parse server migration.
I’ve successfully logged in existing users with Metamask, but not MagicLink. There’s a note about authentication in the migration docs, but that doesn’t include custom providers, and the only tutorial was able to find is for NextJS which obviously doesn’t work with the Parse server setup. The V1 version of the SDK had the Magic Connector already built (here’s the GitHub link ), and I can’t find anything for self-hosted.
When I try to write the code for the MagicLink provider myself, I’m using my old (from pre-migration) magic connector like so:
import { ethers } from 'ethers';
import AbstractWeb3Connector from './AbstractWeb3Connector';
export default class MagicWeb3Connector extends AbstractWeb3Connector {
type = 'MagicLink';
async activate({
apiKey,
newSession,
// Options passed to loginWithMagicLink
email,
phone,
showUI,
redirectURI,
loginCredential, // required for loginWithCredential after an email login callback
// Options passed to new Magic creation
network,
locale,
extensions,
testMode,
endpoint,
} = {}) {
let magic = null;
let ether = null;
if (!apiKey) {
throw new Error('"apiKey" not provided, please provide Api Key');
}
if (!network) {
throw new Error('"network" not provided, please provide network');
}
let Magic;
try {
Magic = require('magic-sdk')?.Magic;
} catch (error) {
// Do nothing. User might not need walletconnect
}
if (!Magic) {
Magic = window?.Magic;
}
if (!Magic) {
throw new Error('Cannot enable via MagicLink: dependency "magic-sdk" is missing');
}
try {
magic = new Magic(apiKey, {
network: network,
...(locale && { locale }),
...(extensions && { extensions }),
...(testMode && { testMode }),
...(endpoint && { endpoint }),
});
if (newSession) {
if (magic?.user) {
try {
await magic?.user?.logout();
} catch (error) {
// Do nothing
}
}
}
ether = new ethers.providers.Web3Provider(magic.rpcProvider);
if (loginCredential) {
console.log("attempting login with credential")
await magic.auth.loginWithCredential('loginCredential');
} else if (email) {
await magic.auth.loginWithMagicLink({
email: email,
...(showUI && { showUI }),
...(redirectURI && { redirectURI }),
});
} else if (phone) {
await magic.auth.loginWithSMS({
phoneNumber: phone,
...(showUI && { showUI }),
...(redirectURI && { redirectURI }),
});
} else {
throw new Error("Neither phone nor email were provided.")
}
} catch (err) {
throw new Error('Error during enable via MagicLink, please double check network and apikey');
}
const loggedIn = await magic.user.isLoggedIn();
if (loggedIn) {
const signer = ether.getSigner();
const { chainId } = await ether.getNetwork();
const address = (await signer.getAddress()).toLowerCase();
// Assign Constants
this.account = address;
this.provider = ether.provider;
this.chainId = `0x${chainId.toString(16)}`;
// Assign magic user for deactivation
this.magicUser = magic;
this.subscribeToEvents(this.provider);
return {
provider: this.provider,
account: this.account,
chainId: this.chainId,
};
}
throw new Error('Error during enable via MagicLink, login to magic failed');
}
deactivate = async () => {
this.unsubscribeToEvents(this.provider);
if (this.magicUser) {
await this.magicUser.user.logout();
}
this.account = null;
this.chainId = null;
this.provider = null;
};
}
And then attempting to use it in the new handleAuth
function that you pointed out:
const loginWithEmail = async () => {
let magicConnector = new MagicWeb3Connector()
let magicAccount = await magicConnector.activate({
email: email,
apiKey: "", //redacted
network: "mainnet",
showUI: true
})
console.log(magicAccount)
const { account, chainId, provider } = magicAccount;
try {
// Enable web3 to get user address and chain
await enableWeb3({ throwOnError: true, provider });
if (!account) {
throw new Error('Connecting to chain failed, as no connected account was found');
}
if (!chainId) {
throw new Error('Connecting to chain failed, as no connected chain was found');
}
// Get message to sign from the auth api
const { message } = await Moralis.Cloud.run('requestMessage', {
address: account,
chain: parseInt(chainId, 16),
networkType: 'evm',
});
// Authenticate and login via parse
await authenticate({
signingMessage: message,
throwOnError: true,
});
} catch (error) {
console.log(error)
} finally {
handleLoginSuccess()
}
}
This does login the user from the Magic point of view (because it console logs the logged in account successfully), but Moralis still opens the Metamask window to sign – I think the problem is probably in the requestMessage
function from the Auth API.
Any idea the next steps for making the new Moralis Auth API work with MagicLink?