Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F3373779
D12033.id40164.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
9 KB
Referenced Files
None
Subscribers
None
D12033.id40164.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D12033: Introduce new header to siwe endpoint
Attached
Detach File
Event Timeline
Log In to Comment