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 @@ -11,6 +11,7 @@ import { isValidPrimaryIdentityPublicKey, isValidSIWENonce, + isValidSIWEMessageType, } from 'lib/utils/siwe-utils.js'; import { getMessageForException } from './utils.js'; @@ -138,6 +139,17 @@ }); return; } + const siweMessageType = req.header('siwe-message-type'); + if ( + siweMessageType !== null && + siweMessageType !== undefined && + !isValidSIWEMessageType(siweMessageType) + ) { + res.status(400).send({ + message: 'Invalid siwe message type.', + }); + return; + } const [{ jsURL, fontURLs, cssInclude }, LandingSSR] = await Promise.all([ getAssetInfo(), @@ -200,6 +212,7 @@ basename={routerBasename} siweNonce={siweNonce} siwePrimaryIdentityPublicKey={siwePrimaryIdentityPublicKey} + siweMessageType={siweMessageType} />, ); reactStream.pipe(res, { end: false }); @@ -209,11 +222,15 @@ const siwePrimaryIdentityPublicKeyString = siwePrimaryIdentityPublicKey ? `"${siwePrimaryIdentityPublicKey}"` : 'null'; + const siweMessageTypeString = siweMessageType + ? `"${siweMessageType}"` + : 'null'; // prettier-ignore res.end(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 @@ -11,16 +11,24 @@ +basename: string, +siweNonce: ?string, +siwePrimaryIdentityPublicKey: ?string, + +siweMessageType: ?string, }; function LandingSSR(props: LandingSSRProps): React.Node { - const { url, basename, siweNonce, siwePrimaryIdentityPublicKey } = props; + const { + url, + basename, + siweNonce, + siwePrimaryIdentityPublicKey, + siweMessageType, + } = props; const siweContextValue = React.useMemo( () => ({ siweNonce, siwePrimaryIdentityPublicKey, + siweMessageType, }), - [siweNonce, siwePrimaryIdentityPublicKey], + [siweNonce, siwePrimaryIdentityPublicKey, siweMessageType], ); const routerContext = React.useMemo(() => ({}), []); return ( diff --git a/landing/root.js b/landing/root.js --- a/landing/root.js +++ b/landing/root.js @@ -9,12 +9,14 @@ declare var routerBasename: string; declare var siweNonce: ?string; declare var siwePrimaryIdentityPublicKey: ?string; +declare var siweMessageType: ?string; function RootComponent(): React.Node { const siweContextValue = React.useMemo( () => ({ siweNonce, siwePrimaryIdentityPublicKey, + siweMessageType, }), [], ); diff --git a/landing/siwe-context.js b/landing/siwe-context.js --- a/landing/siwe-context.js +++ b/landing/siwe-context.js @@ -5,11 +5,13 @@ export type SIWEContextType = { +siweNonce: ?string, +siwePrimaryIdentityPublicKey: ?string, + +siweMessageType: ?string, }; const SIWEContext: React.Context = React.createContext({ siweNonce: null, siwePrimaryIdentityPublicKey: null, + siweMessageType: null, }); export { SIWEContext }; 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 @@ -136,3 +136,15 @@ +signature: string, +fid?: ?string, }; + +export const SIWEMessageTypes = Object.freeze({ + MSG_AUTH: 'msg_auth', + MSG_BACKUP: 'msg_backup', +}); + +export type SIWEMessageType = $Values; + +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 @@ -2,9 +2,11 @@ import invariant from 'invariant'; import { SiweMessage } from 'siwe'; +import t, { type TEnums } from 'tcomb'; import { isDev } from './dev-utils.js'; -import type { SIWEMessage } from '../types/siwe-types.js'; +import { type SIWEMessage, SIWEMessageTypes } from '../types/siwe-types.js'; +import { values } from '../utils/objects.js'; const siweNonceRegex: RegExp = /^[a-zA-Z0-9]{17}$/; function isValidSIWENonce(candidate: string): boolean { @@ -21,6 +23,11 @@ return primaryIdentityPublicKeyRegex.test(candidate); } +const siweMessageTypeValidator: TEnums = t.enums.of(values(SIWEMessageTypes)); +function isValidSIWEMessageType(candidate: string): boolean { + return siweMessageTypeValidator.is(candidate); +} + const siweStatementLegalAgreement: string = 'By continuing, I accept the Comm Terms of Service: https://comm.app/terms'; @@ -111,6 +118,7 @@ export { isValidSIWENonce, isValidEthereumAddress, + isValidSIWEMessageType, primaryIdentityPublicKeyRegex, isValidPrimaryIdentityPublicKey, createSIWEMessage, diff --git a/native/account/fullscreen-siwe-panel.react.js b/native/account/fullscreen-siwe-panel.react.js --- a/native/account/fullscreen-siwe-panel.react.js +++ b/native/account/fullscreen-siwe-panel.react.js @@ -6,7 +6,7 @@ import { ActivityIndicator, View } from 'react-native'; import { setDataLoadedActionType } from 'lib/actions/client-db-store-actions.js'; -import type { SIWEResult } from 'lib/types/siwe-types.js'; +import { type SIWEResult, SIWEMessageTypes } from 'lib/types/siwe-types.js'; import { ServerError } from 'lib/utils/errors.js'; import { useDispatch } from 'lib/utils/redux-utils.js'; import { usingCommServicesAccessToken } from 'lib/utils/services-utils.js'; @@ -152,6 +152,7 @@ onClosed={ifBeforeSuccessGoBackToPrompt} onClosing={ifBeforeSuccessGoBackToPrompt} onSuccessfulWalletSignature={onSuccess} + siweMessageType={SIWEMessageTypes.MSG_AUTH} setLoading={setLoading} /> diff --git a/native/account/registration/connect-ethereum.react.js b/native/account/registration/connect-ethereum.react.js --- a/native/account/registration/connect-ethereum.react.js +++ b/native/account/registration/connect-ethereum.react.js @@ -10,7 +10,7 @@ } from 'lib/actions/user-actions.js'; import { useLegacyAshoatKeyserverCall } from 'lib/keyserver-conn/legacy-keyserver-call.js'; import { createLoadingStatusSelector } from 'lib/selectors/loading-selectors.js'; -import type { SIWEResult } from 'lib/types/siwe-types.js'; +import { type SIWEResult, SIWEMessageTypes } from 'lib/types/siwe-types.js'; import { useDispatchActionPromise } from 'lib/utils/redux-promise-utils.js'; import { usingCommServicesAccessToken } from 'lib/utils/services-utils.js'; @@ -200,6 +200,7 @@ onClosed={onPanelClosed} closing={panelState === 'closing'} onSuccessfulWalletSignature={onSuccessfulWalletSignature} + siweMessageType={SIWEMessageTypes.MSG_AUTH} setLoading={siwePanelSetLoading} keyserverCallParamOverride={serverCallParamOverride} /> diff --git a/native/account/siwe-panel.react.js b/native/account/siwe-panel.react.js --- a/native/account/siwe-panel.react.js +++ b/native/account/siwe-panel.react.js @@ -17,7 +17,11 @@ import type { ServerCallSelectorParams } from 'lib/keyserver-conn/call-keyserver-endpoint-provider.react.js'; import { useLegacyAshoatKeyserverCall } from 'lib/keyserver-conn/legacy-keyserver-call.js'; import { createLoadingStatusSelector } from 'lib/selectors/loading-selectors.js'; -import type { SIWEWebViewMessage, SIWEResult } from 'lib/types/siwe-types.js'; +import type { + SIWEWebViewMessage, + SIWEResult, + SIWEMessageType, +} from 'lib/types/siwe-types.js'; import { getContentSigningKey } from 'lib/utils/crypto-utils.js'; import { useDispatchActionPromise } from 'lib/utils/redux-promise-utils.js'; import { usingCommServicesAccessToken } from 'lib/utils/services-utils.js'; @@ -45,6 +49,7 @@ +onClosed: () => mixed, +onClosing: () => mixed, +onSuccessfulWalletSignature: SIWEResult => mixed, + +siweMessageType: SIWEMessageType, +closing: boolean, +setLoading: boolean => mixed, +keyserverCallParamOverride?: Partial, @@ -65,6 +70,7 @@ ); const { onClosing } = props; + const { siweMessageType } = props; const legacySiweAuthCallLoading = useSelector( state => legacySiweAuthLoadingStatusSelector(state) === 'loading', @@ -186,9 +192,10 @@ headers: { 'siwe-nonce': nonce, 'siwe-primary-identity-public-key': primaryIdentityPublicKey, + 'siwe-message-type': siweMessageType, }, }), - [nonce, primaryIdentityPublicKey], + [nonce, primaryIdentityPublicKey, siweMessageType], ); const onWebViewLoaded = React.useCallback(() => {