Page MenuHomePhabricator

D12033.id40164.diff
No OneTemporary

D12033.id40164.diff

diff --git a/keyserver/src/responders/landing-handler.js b/keyserver/src/responders/landing-handler.js
--- a/keyserver/src/responders/landing-handler.js
+++ b/keyserver/src/responders/landing-handler.js
@@ -13,6 +13,7 @@
isValidPrimaryIdentityPublicKey,
isValidSIWENonce,
isValidSIWEMessageType,
+ isValidSIWEMessageString,
} from 'lib/utils/siwe-utils.js';
import { getMessageForException } from './utils.js';
@@ -152,6 +153,25 @@
return;
}
const siweMessageType = ((siweMessageTypeRawString: any): SIWEMessageType);
+ const siweMessageToSign = req.header('siwe-message-to-sign');
+
+ if (
+ siweMessageToSign !== null &&
+ siweMessageToSign !== undefined &&
+ !isValidSIWEMessageString(decodeURIComponent(siweMessageToSign))
+ ) {
+ res.status(400).send({
+ message: 'Invalid siwe message to sign.',
+ });
+ return;
+ }
+
+ if (siweMessageToSign && (siweNonce || siwePrimaryIdentityPublicKey)) {
+ res.status(400).send({
+ message:
+ 'Nonce and complete message to sign cannot be provided at the same time.',
+ });
+ }
const [{ jsURL, fontURLs, cssInclude }, LandingSSR] = await Promise.all([
getAssetInfo(),
@@ -215,6 +235,7 @@
siweNonce={siweNonce}
siwePrimaryIdentityPublicKey={siwePrimaryIdentityPublicKey}
siweMessageType={siweMessageType}
+ siweMessageToSign={siweMessageToSign}
/>,
);
reactStream.pipe(res, { end: false });
@@ -227,12 +248,16 @@
const siweMessageTypeString = siweMessageType
? `"${siweMessageType}"`
: 'null';
+ const siweMessageToSignString = siweMessageToSign
+ ? `"${siweMessageToSign}"`
+ : 'null';
// prettier-ignore
res.end(html`</div>
<script>var routerBasename = "${routerBasename}";</script>
<script>var siweNonce = ${siweNonceString};</script>
<script>var siwePrimaryIdentityPublicKey = ${siwePrimaryIdentityPublicKeyString};</script>
<script>var siweMessageType = ${siweMessageTypeString};</script>
+ <script>var siweMessageToSign = ${siweMessageToSignString};</script>
<script src="${jsURL}"></script>
</body>
</html>
diff --git a/landing/landing-ssr.react.js b/landing/landing-ssr.react.js
--- a/landing/landing-ssr.react.js
+++ b/landing/landing-ssr.react.js
@@ -14,6 +14,7 @@
+siweNonce: ?string,
+siwePrimaryIdentityPublicKey: ?string,
+siweMessageType: ?SIWEMessageType,
+ +siweMessageToSign: ?string,
};
function LandingSSR(props: LandingSSRProps): React.Node {
const {
@@ -22,6 +23,7 @@
siweNonce,
siwePrimaryIdentityPublicKey,
siweMessageType,
+ siweMessageToSign,
} = props;
const siweContextValue = React.useMemo(
@@ -29,8 +31,14 @@
siweNonce,
siwePrimaryIdentityPublicKey,
siweMessageType,
+ siweMessageToSign,
}),
- [siweNonce, siwePrimaryIdentityPublicKey, siweMessageType],
+ [
+ siweNonce,
+ siwePrimaryIdentityPublicKey,
+ siweMessageType,
+ siweMessageToSign,
+ ],
);
const routerContext = React.useMemo(() => ({}), []);
return (
diff --git a/landing/root.js b/landing/root.js
--- a/landing/root.js
+++ b/landing/root.js
@@ -12,6 +12,7 @@
declare var siweNonce: ?string;
declare var siwePrimaryIdentityPublicKey: ?string;
declare var siweMessageType: ?SIWEMessageType;
+declare var siweMessageToSign: ?string;
function RootComponent(): React.Node {
const siweContextValue = React.useMemo(
@@ -19,6 +20,7 @@
siweNonce,
siwePrimaryIdentityPublicKey,
siweMessageType,
+ siweMessageToSign,
}),
[],
);
diff --git a/landing/siwe-context.js b/landing/siwe-context.js
--- a/landing/siwe-context.js
+++ b/landing/siwe-context.js
@@ -8,12 +8,14 @@
+siweNonce: ?string,
+siwePrimaryIdentityPublicKey: ?string,
+siweMessageType: ?SIWEMessageType,
+ +siweMessageToSign: ?string,
};
const SIWEContext: React.Context<SIWEContextType> = React.createContext({
siweNonce: null,
siwePrimaryIdentityPublicKey: null,
siweMessageType: null,
+ siweMessageToSign: null,
});
export { SIWEContext };
diff --git a/landing/siwe.react.js b/landing/siwe.react.js
--- a/landing/siwe.react.js
+++ b/landing/siwe.react.js
@@ -63,40 +63,72 @@
});
}
+async function signCompleteMessageWithEthereum(
+ address: string,
+ message: string,
+ signer: Signer,
+) {
+ const decodedMessage = decodeURIComponent(message);
+ const signature = await signer.signMessage({ message: decodedMessage });
+ postMessageToNativeWebView({
+ type: 'siwe_success',
+ address,
+ message: decodedMessage,
+ signature,
+ });
+}
+
const queryClient = new QueryClient();
function SIWE(): React.Node {
const { address } = useAccount();
const { data: signer } = useWalletClient();
- const { siweNonce, siwePrimaryIdentityPublicKey, siweMessageType } =
- React.useContext(SIWEContext);
+ const {
+ siweNonce,
+ siwePrimaryIdentityPublicKey,
+ siweMessageType,
+ siweMessageToSign,
+ } = React.useContext(SIWEContext);
+
const onClick = React.useCallback(() => {
- invariant(siweNonce, 'nonce must be present during SIWE attempt');
invariant(siweMessageType, 'message type must be set during SIWE attempt');
invariant(
- siwePrimaryIdentityPublicKey,
- 'primaryIdentityPublicKey must be present during SIWE attempt',
+ siweMessageToSign || (siwePrimaryIdentityPublicKey && siweNonce),
+ 'nonce with primaryIdentityPublicKey or complete message to sign must be ' +
+ 'present during SIWE attempt',
);
- const statement = getSIWEStatementForPublicKey(
- siwePrimaryIdentityPublicKey,
- siweMessageType,
- );
- void signInWithEthereum(address, signer, siweNonce, statement);
+
+ if (siweMessageToSign) {
+ void signCompleteMessageWithEthereum(address, siweMessageToSign, signer);
+ return;
+ }
+
+ if (siweNonce && siwePrimaryIdentityPublicKey) {
+ const statement = getSIWEStatementForPublicKey(
+ siwePrimaryIdentityPublicKey,
+ siweMessageType,
+ );
+ void signInWithEthereum(address, signer, siweNonce, statement);
+ }
}, [
address,
signer,
siweNonce,
siwePrimaryIdentityPublicKey,
siweMessageType,
+ siweMessageToSign,
]);
const { openConnectModal, connectModalOpen } = useConnectModal();
- const hasNonce = siweNonce !== null && siweNonce !== undefined;
+ const hasNonceOrCompleteMessage =
+ (siweNonce !== null && siweNonce !== undefined) ||
+ (siweMessageToSign !== null && siweMessageToSign !== undefined);
+
React.useEffect(() => {
- if (hasNonce && openConnectModal) {
+ if (hasNonceOrCompleteMessage && openConnectModal) {
openConnectModal();
}
- }, [hasNonce, openConnectModal]);
+ }, [hasNonceOrCompleteMessage, openConnectModal]);
const [wcModalOpen, setWCModalOpen] = React.useState(false);
@@ -135,10 +167,12 @@
</div>
);
}
- if (!hasNonce) {
+ if (!hasNonceOrCompleteMessage) {
return (
<div className={css.wrapper}>
- <h1 className={css.h1}>Unable to proceed: nonce not found.</h1>
+ <h1 className={css.h1}>
+ Unable to proceed: neither nonce nor complete message found.
+ </h1>
</div>
);
} else if (!signer) {
diff --git a/lib/types/siwe-types.js b/lib/types/siwe-types.js
--- a/lib/types/siwe-types.js
+++ b/lib/types/siwe-types.js
@@ -141,10 +141,18 @@
export const SIWEMessageTypes = Object.freeze({
MSG_AUTH: 'msg_auth',
MSG_BACKUP: 'msg_backup',
+ MSG_BACKUP_RESTORE: 'msg_backup_restore',
});
export type SIWEMessageType = $Values<typeof SIWEMessageTypes>;
+export type SIWESignatureRequestData =
+ | { +messageType: SIWEMessageType }
+ | {
+ +messageType: 'msg_backup_restore',
+ +messageToSign: string,
+ };
+
export type SIWEBackupSecrets = {
+message: string,
+signature: string,
diff --git a/lib/utils/siwe-utils.js b/lib/utils/siwe-utils.js
--- a/lib/utils/siwe-utils.js
+++ b/lib/utils/siwe-utils.js
@@ -82,6 +82,11 @@
);
}
+function isValidSIWEMessageString(candidate: string): boolean {
+ const candidateMessage = new SiweMessage(candidate);
+ return isValidSIWEMessage(candidateMessage);
+}
+
function getSIWEStatementForPublicKey(
publicKey: string,
messageType: SIWEMessageType,
@@ -134,7 +139,12 @@
`Your signature on this message will be used to derive ` +
`a secret key that will encrypt your Comm backup.`;
+const siweBackupRestoreMessageSigningExplanationStatements: string =
+ `Your signature on this message will be used to derive ` +
+ `a secret key that will decrypt you Comm backup.`;
+
const siweBackupMessageSigningButtonStatement = 'Create a backup key';
+const siweBackupRestoreMessageSigningButtonStatement = 'Retrieve a backup key';
const userTextsForSIWEMessageTypes: {
+[signatureRequestType: string]: {
@@ -153,6 +163,11 @@
showTermsAgreement: false,
buttonStatement: siweBackupMessageSigningButtonStatement,
},
+ [SIWEMessageTypes.MSG_BACKUP_RESTORE]: {
+ explanationStatement: siweBackupRestoreMessageSigningExplanationStatements,
+ showTermsAgreement: false,
+ buttonStatement: siweBackupRestoreMessageSigningButtonStatement,
+ },
};
export {
@@ -163,6 +178,7 @@
isValidPrimaryIdentityPublicKey,
createSIWEMessage,
isValidSIWEMessage,
+ isValidSIWEMessageString,
getSIWEStatementForPublicKey,
isValidSIWEStatementWithPublicKey,
getPublicKeyFromSIWEStatement,

File Metadata

Mime Type
text/plain
Expires
Wed, Nov 27, 11:48 AM (21 h, 4 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2590331
Default Alt Text
D12033.id40164.diff (9 KB)

Event Timeline