Skip to content

Commit

Permalink
feat: siwe
Browse files Browse the repository at this point in the history
  • Loading branch information
hai-ko committed Nov 24, 2023
1 parent fc35eca commit 679f0db
Show file tree
Hide file tree
Showing 7 changed files with 71 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export async function getBillboardProfile(
const wallet = new ethers.Wallet(billboard.privateKey);
const storageKeyCreationMessage = getStorageKeyCreationMessage(
'0xca8f04fdc80d659997f69b02',
wallet.address,
);
const storageKeySig = await wallet.signMessage(
storageKeyCreationMessage,
Expand Down
1 change: 1 addition & 0 deletions packages/billboard-client/test/helper/mockUserProfile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export const mockUserProfile = async (
}> => {
const storageKeyCreationMessage = getStorageKeyCreationMessage(
'0xca8f04fdc80d659997f69b02',
wallet.address,
);

const storageKeySig = await wallet.signMessage(storageKeyCreationMessage);
Expand Down
20 changes: 16 additions & 4 deletions packages/lib/crypto/src/KeyCreation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,23 @@ export async function createSigningKeyPair(seed?: string): Promise<KeyPair> {
};
}

export function getStorageKeyCreationMessage(nonce: string) {
export function getStorageKeyCreationMessage(nonce: string, address: string) {
// TODO: during linked profile implementation these values should be fetched from env
const statement =
`Connect the DM3 MESSENGER with your wallet. Sign in with a signature. ` +
`Keys for secure communication are derived from this signature.\n\n` +
`(There is no paid transaction initiated. The signature is used off-chain only.)`;
const domain = 'dm3.chat';
const uri = 'https://dm3.chat';
const version = '1';

return (
`Connect the dm3 app with your wallet.` +
` Keys for secure communication are derived from the signature.` +
` No paid transaction will be executed.\nNonce: ${nonce}`
`${domain} wants you to sign in with your Ethereum account:\n` +
`${ethers.utils.getAddress(address)}\n\n` +
`${statement}\n\n` +
`URI: ${uri}\n` +
`Version: ${version}\n` +
`Nonce: ${nonce}`
);
}

Expand Down
29 changes: 23 additions & 6 deletions packages/lib/profile/src/Profile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,22 @@ export const PROFILE_RECORD_NAME = 'network.dm3.profile';
* signs a profile with an ethereum account key
* @param stringifiedProfile stringified dm3 user profile object
*/
export function getProfileCreationMessage(stringifiedProfile: string) {
export function getProfileCreationMessage(
stringifiedProfile: string,
address: string,
) {
const domain = 'dm3.chat';
const uri = 'https://dm3.chat';
const version = '1';

return (
`Please sign this message to link your dm3 profile with your Wallet. ` +
`(This signature will not trigger any transaction or cost gas fees.) ` +
`Your dm3 profile:\n\n${stringifiedProfile}`
`${domain} wants you register your dm3 account with your Ethereum account:\n` +
`${ethers.utils.getAddress(address)}\n\n` +
`Register your dm3 profile. This is required only once!\n` +
`(There is no paid transaction initiated. The signature is used off-chain only.)\n\n` +
`URI: ${uri}\n` +
`Version: ${version}\n` +
`dm3 Profile: ${stringifiedProfile}`
);
}

Expand Down Expand Up @@ -116,6 +127,7 @@ export function checkUserProfileWithAddress(
): boolean {
const createUserProfileMessage = getProfileCreationMessage(
stringify(profile),
accountAddress,
);

return (
Expand Down Expand Up @@ -192,12 +204,15 @@ export function isSameEnsName(

async function createKeyPairsFromSig(
sign: (msg: string) => Promise<string>,

address: string,
nonce: string,
storageKey?: string,
): Promise<ProfileKeys> {
if (!storageKey) {
const storageKeyCreationMessage = getStorageKeyCreationMessage(nonce);
const storageKeyCreationMessage = getStorageKeyCreationMessage(
nonce,
address,
);
const signature = await sign(storageKeyCreationMessage);

const newStorageKey = await createStorageKey(signature);
Expand Down Expand Up @@ -235,6 +250,7 @@ export async function createProfile(

const keys = await createKeyPairsFromSig(
(msg: string) => signer(msg, accountAddress),
accountAddress,
nonce,
storageKey,
);
Expand All @@ -247,6 +263,7 @@ export async function createProfile(

const profileCreationMessage = getProfileCreationMessage(
stringify(profile),
accountAddress,
);
const profileSig = await signer(profileCreationMessage, accountAddress);
return {
Expand Down
41 changes: 22 additions & 19 deletions packages/messenger-widget/src/components/SignIn/bl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,8 @@ export const checkState = async (
const browserDataFile =
state.connection.account && state.uiState.browserStorageBackup
? await localforage.getItem(
getBrowserStorageKey(state.connection.account.ensName),
)
getBrowserStorageKey(state.connection.account.ensName),
)
: null;

const isCollectingSignInData =
Expand Down Expand Up @@ -171,7 +171,10 @@ export async function createKeyPairsFromSignature(
throw Error('No eth address');
}

const storageKeyCreationMessage = getStorageKeyCreationMessage(nonce);
const storageKeyCreationMessage = getStorageKeyCreationMessage(
nonce,
ethAddress,
);

const signature = await personalSign(
provider,
Expand Down Expand Up @@ -347,7 +350,7 @@ export async function signProfile(
): Promise<string> {
try {
const profileCreationMessage =
getProfileCreationMessage(stringifiedProfile);
getProfileCreationMessage(stringifiedProfile, address);
return await personalSign(provider, address, profileCreationMessage);
} catch (error: any) {
const err = error?.message.split(':');
Expand Down Expand Up @@ -481,12 +484,12 @@ export async function getDatabase(
}> {
return profileExists
? getExistingDatebase(
storageLocation,
storageToken,
state,
dispatch,
setSignInBtnContent,
)
storageLocation,
storageToken,
state,
dispatch,
setSignInBtnContent,
)
: createNewDatabase(state, setSignInBtnContent);
}

Expand Down Expand Up @@ -814,16 +817,16 @@ export async function getWeb3Provider(provider: unknown): Promise<{
}> {
return provider
? {
provider: new ethers.providers.Web3Provider(
provider as
| ethers.providers.ExternalProvider
| ethers.providers.JsonRpcFetchFunc,
),
connectionState: ConnectionState.AccountConnectReady,
}
provider: new ethers.providers.Web3Provider(
provider as
| ethers.providers.ExternalProvider
| ethers.providers.JsonRpcFetchFunc,
),
connectionState: ConnectionState.AccountConnectReady,
}
: {
connectionState: ConnectionState.ConnectionRejected,
};
connectionState: ConnectionState.ConnectionRejected,
};
}

function handleNewProvider(
Expand Down
6 changes: 4 additions & 2 deletions packages/react/src/session/SignIn/signProfile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ export async function signProfile(
stringifiedProfile: string,
): Promise<string> {
try {
const profileCreationMessage =
getProfileCreationMessage(stringifiedProfile);
const profileCreationMessage = getProfileCreationMessage(
stringifiedProfile,
address,
);
return await personalSign(provider, address, profileCreationMessage);
} catch (e) {
throw Error("Can't signIn profile");
Expand Down
5 changes: 4 additions & 1 deletion packages/react/src/session/SignIn/signProfileKeyPair.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ export async function createKeyPairsFromSig(
throw Error('No eth address');
}

const storageKeyCreationMessage = getStorageKeyCreationMessage(nonce);
const storageKeyCreationMessage = getStorageKeyCreationMessage(
nonce,
ethAddress,
);

const signature = await personalSign(
provider,
Expand Down

0 comments on commit 679f0db

Please sign in to comment.